Skip to content

Commit d4178cb

Browse files
committed
Bug-fix Auth test
1 parent cc37418 commit d4178cb

File tree

5 files changed

+289
-252
lines changed

5 files changed

+289
-252
lines changed

composer.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@
99
"email": "anshu.krishna5@gmail.com"
1010
}
1111
],
12-
"version": "11.1",
12+
"version": "11.2",
1313
"minimum-stability": "stable",
1414
"require": {
1515
"php": ">=8.1",
16-
"anshu-krishna/data-validator": "^2.0",
17-
"anshu-krishna/php-utilities": "^1.0"
16+
"anshu-krishna/data-validator": "^2.6.1",
17+
"anshu-krishna/php-utilities": "^1.1"
1818
},
1919
"autoload": {
2020
"psr-4": {
2121
"Krishna\\API\\": "src"
2222
}
2323
}
24-
}
24+
}

example/client/component/api-fetch.js

Lines changed: 174 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -1,174 +1,175 @@
1-
import './key-val.js';
2-
import {w3CodeColor} from './w3CodeColor.js';
3-
import {API, APIProxy} from '../API.js';
4-
5-
class APIFetch extends HTMLElement {
6-
static __tag = 'api-fetch';
7-
static __template = document.createElement('template');
8-
static #funcpattern = /^[_a-zA-Z][_a-zA-Z0-9-.]*$/;
9-
#root;
10-
#pcntr;
11-
#ccntr;
12-
#rcntr;
13-
#ocntr;
14-
#fname;
15-
#api;
16-
constructor() {
17-
super();
18-
19-
this.#api = new API('../server/public', window.location.href);
20-
21-
this.#root = this.attachShadow({mode: 'closed'});
22-
this.#root.appendChild(APIFetch.__template.content.cloneNode(true));
23-
this.#root.querySelector('#add_para').onclick = () => {
24-
this.#root.querySelector('#para_cntr').appendChild(document.createElement('key-val'));
25-
};
26-
27-
this.#fname = this.#root.querySelector('#func');
28-
this.#pcntr = this.#root.querySelector('#para_cntr');
29-
this.#ccntr = this.#root.querySelector('#code_cntr pre');
30-
this.#rcntr = this.#root.querySelector('#resp_cntr pre');
31-
this.#ocntr = this.#root.querySelector('#out_cntr');
32-
33-
this.#ocntr.style.display = 'none';
34-
35-
this.#root.querySelector('#fetch').onclick = async () => {
36-
this.#ocntr.style.display = 'none';
37-
if(!APIFetch.#funcpattern.test(this.#fname.value)) {
38-
this.#fname.setCustomValidity(`Required 'function-name' pattern: ${APIFetch.#funcpattern}`);
39-
this.#fname.reportValidity();
40-
return;
41-
}
42-
let fname = this.#fname.value;
43-
let param = {};
44-
for(let kv of Array.from(this.#pcntr.querySelectorAll('key-val'))) {
45-
let d = kv.data;
46-
if(d === null) {
47-
return;
48-
}
49-
param = {...param, ...d};
50-
}
51-
let resp = await this.#api.fetchRaw(fname, param);
52-
this.#rcntr.innerHTML = JSON.stringify(resp, null, 4);
53-
54-
this.#root.querySelector('#resp_cntr').style.background = (resp.status === 0) ? '#4caf50' : '#f44336';
55-
56-
let paramjson = JSON.stringify(param);
57-
let hasparam = Object.entries(param).length === 0;
58-
let paramstr1 = hasparam ? '' : `, ${paramjson}`;
59-
let paramstr2 = hasparam ? '' : paramjson;
60-
let jsonfname = JSON.stringify(fname);
61-
62-
this.#ccntr.innerText = `<script type="module">
63-
import {API, APIProxy} from './API.js';
64-
const url = '../server/public'; /* The API URL eg: '', 'api' */
65-
const base = window.location.href /* The API base path eg: 'https://api.example.com' */
66-
67-
{ /* Using the API class directly */
68-
const api = new API(url, base);
69-
70-
/* Fetch raw response */
71-
let rawResp = await api.fetchRaw(${jsonfname}${paramstr1});
72-
console.log(rawResp);
73-
74-
/* Fetch response value */
75-
try {
76-
let val = await api.fetch(${jsonfname}${paramstr1});
77-
console.log(val);
78-
} catch (error) {
79-
console.error(error);
80-
}
81-
}
82-
{ /* Using APIProxy */
83-
const api = new APIProxy(url, base);
84-
85-
/* Fetch raw response */
86-
let rawResp = await api.fetchRaw.${fname}(${paramstr2});
87-
console.log(rawResp);
88-
89-
/* Fetch response value */
90-
try {
91-
let val = await api.fetch.${fname}(${paramstr2});
92-
console.log(val);
93-
} catch (error) {
94-
console.error(error);
95-
}
96-
}
97-
</script>`;
98-
w3CodeColor(this.#ccntr, 'html');
99-
this.#ocntr.style.display = 'grid';
100-
};
101-
}
102-
}
103-
APIFetch.__template.innerHTML = `<style>
104-
* {
105-
box-sizing: border-box;
106-
}
107-
#cntr {
108-
padding: 0.5em;
109-
}
110-
button {
111-
cursor: pointer;
112-
padding: 0.5em;
113-
}
114-
input {
115-
height: 2.5em;
116-
padding: 0.5em;
117-
vertical-align: middle;
118-
}
119-
header {
120-
font-weight: bold;
121-
font-size: larger;
122-
}
123-
pre {
124-
font-family: Consolas,'Courier New', monospace;
125-
white-space: pre-wrap;
126-
padding: 0;
127-
margin: 0;
128-
margin-top: 0.5em;
129-
}
130-
#cntr {
131-
display: grid;
132-
gap: 0.5em;
133-
grid-template-columns: 1fr;
134-
background: #1a237e;
135-
color: white;
136-
}
137-
#para_cntr {
138-
display: grid;
139-
gap: 0.5em;
140-
}
141-
#out_cntr {
142-
display: grid;
143-
grid-template-columns: 1fr 1fr;
144-
padding: 0.5em 1em;
145-
gap: 0.5em
146-
}
147-
#out_cntr > section {
148-
box-shadow: 1px 1px 1em black;
149-
padding: 0.5em 1em;
150-
background: #e0f2f1;
151-
}
152-
</style><div id="cntr">
153-
<header>API Function: <button id="fetch">Execute 🗘</button></header>
154-
<datalist id="list">
155-
<option value="test">test</option>
156-
<option value="test.lol">lol</option>
157-
<option value="test.ping">ping</option>
158-
</datalist>
159-
<input list="list" type="text" id="func" placeholder="Function Name" required />
160-
<section id="para_cntr">
161-
<header>Parameters: <button id="add_para"><strong>+</strong></button></header>
162-
</section>
163-
</div>
164-
<div id="out_cntr">
165-
<section id="code_cntr">
166-
<header>Code Example:</header>
167-
<pre></pre>
168-
</section>
169-
<section id="resp_cntr">
170-
<header>Raw Response:</header>
171-
<pre></pre>
172-
</section>
173-
</div>`;
1+
import './key-val.js';
2+
import {w3CodeColor} from './w3CodeColor.js';
3+
import {API, APIProxy} from '../API.js';
4+
5+
class APIFetch extends HTMLElement {
6+
static __tag = 'api-fetch';
7+
static __template = document.createElement('template');
8+
static #funcpattern = /^[_a-zA-Z][_a-zA-Z0-9-.]*$/;
9+
#root;
10+
#pcntr;
11+
#ccntr;
12+
#rcntr;
13+
#ocntr;
14+
#fname;
15+
#api;
16+
constructor() {
17+
super();
18+
19+
this.#api = new API('../server/public', window.location.href);
20+
21+
this.#root = this.attachShadow({mode: 'closed'});
22+
this.#root.appendChild(APIFetch.__template.content.cloneNode(true));
23+
this.#root.querySelector('#add_para').onclick = () => {
24+
this.#root.querySelector('#para_cntr').appendChild(document.createElement('key-val'));
25+
};
26+
27+
this.#fname = this.#root.querySelector('#func');
28+
this.#pcntr = this.#root.querySelector('#para_cntr');
29+
this.#ccntr = this.#root.querySelector('#code_cntr pre');
30+
this.#rcntr = this.#root.querySelector('#resp_cntr pre');
31+
this.#ocntr = this.#root.querySelector('#out_cntr');
32+
33+
this.#ocntr.style.display = 'none';
34+
35+
this.#root.querySelector('#fetch').onclick = async () => {
36+
this.#ocntr.style.display = 'none';
37+
if(!APIFetch.#funcpattern.test(this.#fname.value)) {
38+
this.#fname.setCustomValidity(`Required 'function-name' pattern: ${APIFetch.#funcpattern}`);
39+
this.#fname.reportValidity();
40+
return;
41+
}
42+
let fname = this.#fname.value;
43+
let param = {};
44+
for(let kv of Array.from(this.#pcntr.querySelectorAll('key-val'))) {
45+
let d = kv.data;
46+
if(d === null) {
47+
return;
48+
}
49+
param = {...param, ...d};
50+
}
51+
let resp = await this.#api.fetchRaw(fname, param);
52+
this.#rcntr.innerHTML = JSON.stringify(resp, null, 4);
53+
54+
this.#root.querySelector('#resp_cntr').style.background = (resp.status === 0) ? '#4caf50' : '#f44336';
55+
56+
let paramjson = JSON.stringify(param);
57+
let hasparam = Object.entries(param).length === 0;
58+
let paramstr1 = hasparam ? '' : `, ${paramjson}`;
59+
let paramstr2 = hasparam ? '' : paramjson;
60+
let jsonfname = JSON.stringify(fname);
61+
62+
this.#ccntr.innerText = `<script type="module">
63+
import {API, APIProxy} from './API.js';
64+
const url = '../server/public'; /* The API URL eg: '', 'api' */
65+
const base = window.location.href /* The API base path eg: 'https://api.example.com' */
66+
67+
{ /* Using the API class directly */
68+
const api = new API(url, base);
69+
70+
/* Fetch raw response */
71+
let rawResp = await api.fetchRaw(${jsonfname}${paramstr1});
72+
console.log(rawResp);
73+
74+
/* Fetch response value */
75+
try {
76+
let val = await api.fetch(${jsonfname}${paramstr1});
77+
console.log(val);
78+
} catch (error) {
79+
console.error(error);
80+
}
81+
}
82+
{ /* Using APIProxy */
83+
const api = new APIProxy(url, base);
84+
85+
/* Fetch raw response */
86+
let rawResp = await api.fetchRaw.${fname}(${paramstr2});
87+
console.log(rawResp);
88+
89+
/* Fetch response value */
90+
try {
91+
let val = await api.fetch.${fname}(${paramstr2});
92+
console.log(val);
93+
} catch (error) {
94+
console.error(error);
95+
}
96+
}
97+
</script>`;
98+
w3CodeColor(this.#ccntr, 'html');
99+
this.#ocntr.style.display = 'grid';
100+
};
101+
}
102+
}
103+
APIFetch.__template.innerHTML = `<style>
104+
* {
105+
box-sizing: border-box;
106+
}
107+
#cntr {
108+
padding: 0.5em;
109+
}
110+
button {
111+
cursor: pointer;
112+
padding: 0.5em;
113+
}
114+
input {
115+
height: 2.5em;
116+
padding: 0.5em;
117+
vertical-align: middle;
118+
}
119+
header {
120+
font-weight: bold;
121+
font-size: larger;
122+
}
123+
pre {
124+
font-family: Consolas,'Courier New', monospace;
125+
white-space: pre-wrap;
126+
padding: 0;
127+
margin: 0;
128+
margin-top: 0.5em;
129+
}
130+
#cntr {
131+
display: grid;
132+
gap: 0.5em;
133+
grid-template-columns: 1fr;
134+
background: #1a237e;
135+
color: white;
136+
}
137+
#para_cntr {
138+
display: grid;
139+
gap: 0.5em;
140+
}
141+
#out_cntr {
142+
display: grid;
143+
grid-template-columns: 1fr 1fr;
144+
padding: 0.5em 1em;
145+
gap: 0.5em
146+
}
147+
#out_cntr > section {
148+
box-shadow: 1px 1px 1em black;
149+
padding: 0.5em 1em;
150+
background: #e0f2f1;
151+
}
152+
</style><div id="cntr">
153+
<header>API Function: <button id="fetch">Execute 🗘</button></header>
154+
<datalist id="list">
155+
<option value="test">test</option>
156+
<option value="test.lol">lol</option>
157+
<option value="test.ping">ping</option>
158+
<option value="test.auth">auth</option>
159+
</datalist>
160+
<input list="list" type="text" id="func" placeholder="Function Name" required />
161+
<section id="para_cntr">
162+
<header>Parameters: <button id="add_para"><strong>+</strong></button></header>
163+
</section>
164+
</div>
165+
<div id="out_cntr">
166+
<section id="code_cntr">
167+
<header>Code Example:</header>
168+
<pre></pre>
169+
</section>
170+
<section id="resp_cntr">
171+
<header>Raw Response:</header>
172+
<pre></pre>
173+
</section>
174+
</div>`;
174175
customElements.define(APIFetch.__tag, APIFetch);

example/server/function/Test/Auth.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
namespace ExampleApp;
3+
4+
use Krishna\API\AuthenticatorInterface;
5+
use Krishna\API\Func;
6+
use Krishna\DataValidator\Returner;
7+
8+
class Dummy implements AuthenticatorInterface {
9+
public function authenticate(array $param, string $functionName): Returner {
10+
if($param['allow'] ?? false) {
11+
return Returner::valid();
12+
}
13+
return Returner::invalid('AuthError: Not allowed');
14+
}
15+
}
16+
17+
Func::add_authenticator(new \ExampleApp\Dummy);
18+
19+
Func::set_signature([
20+
'allow' => 'bool'
21+
]);
22+
23+
Func::set_definition(function(array $params, string $funcname) {
24+
return 'Auth passed';
25+
});

0 commit comments

Comments
 (0)