Skip to content

Commit 32d76c8

Browse files
committed
dev-demo: integrate LevelDB key-value operations in API and enhance SystemTest UI
AdminForth/1703/make-s3-adapter-support-url-pa
1 parent 7ada00d commit 32d76c8

3 files changed

Lines changed: 168 additions & 31 deletions

File tree

dev-demo/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ node_modules
33
.sqlite
44
.env
55
db
6-
images/*
6+
images/*
7+
testdb/*

dev-demo/api.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ import { Express, Response } from "express";
22
import { Filters, IAdminForth, IAdminUserExpressRequest } from "adminforth";
33
import * as z from "zod";
44
import TwoFactorsAuthPlugin from "../plugins/adminforth-two-factors-auth/index.js";
5+
import LevelDBKeyValueAdapter from '../adapters/adminforth-key-value-adapter-leveldb/index.js';
6+
7+
const levelDbAdapter = new LevelDBKeyValueAdapter({
8+
dbPath: './testdb',
9+
});
510

611
const DASHBOARD_CAR_SOURCES = [
712
{ resourceId: 'cars_sl', label: 'SQLite' },
@@ -184,7 +189,32 @@ export function initApi(app: Express, admin: IAdminForth) {
184189
const { adminUser } = _req;
185190
const t2fa = admin.getPluginByClassName<TwoFactorsAuthPlugin>('TwoFactorsAuthPlugin');
186191
const verifyResult = await t2fa.verifyAuto(adminUser);
187-
res.json({ message: "2FA call received!" });
192+
res.json({ message: "2FA call received!", verifyResult });
193+
}
194+
)
195+
);
196+
app.post(`${admin.config.baseUrl}/api/getLevelDbKeys/`,
197+
admin.express.authorize(
198+
async (_req: IAdminUserExpressRequest, res: Response) => {
199+
console.log('Received getLevelDbKeys');
200+
const { prefix } = _req.body;
201+
const keys = await levelDbAdapter.listByPrefix(prefix, 100);
202+
res.json({ keys });
203+
}
204+
)
205+
);
206+
app.post(`${admin.config.baseUrl}/api/addLevelDbKey/`,
207+
admin.express.authorize(
208+
async (_req: IAdminUserExpressRequest, res: Response) => {
209+
console.log('Received addLevelDbKey');
210+
const {key, value} = _req.body;
211+
await levelDbAdapter.set(key, value);
212+
// for (let i = 0; i < 100; i++) {
213+
// await levelDbAdapter.set(`clean=true||${new Date().toISOString()}||record_${i}`, `true`);
214+
// console.log(`Added record ${i}`);
215+
// await new Promise((resolve) => setTimeout(resolve, 100));
216+
// }
217+
res.json({ ok: true });
188218
}
189219
)
190220
);

dev-demo/custom/SystemTest.vue

Lines changed: 135 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,90 @@
11
<template>
2-
<div class="flex flex-col max-w-[200px] m-10 mt-20 gap-10">
3-
<Button @click="createJob">
4-
Create Job
5-
</Button>
6-
<Button @click="addTaskToTheLastJob">
7-
Add Task to the Last Job
8-
</Button>
9-
<Button @click="deleteTaskFromTheLastJob">
10-
Delete Task from the Last Job
11-
</Button>
12-
<Button @click="callHelloWorldApi">
13-
Call API
14-
</Button>
15-
16-
<Button @click="callHelloWorldApi">
17-
Refresh badge
18-
</Button>
19-
20-
<Button @click="doTest2faCall">
21-
Test 2FA API Call
22-
</Button>
23-
24-
<Button @click="get2FaConfirmationResultWindow">
25-
2fa window.get2FaConfirmationResult (global window api)
26-
</Button>
27-
<Button @click="get2FaConfirmationResultTwoFactorsAuth">
28-
2fa twoFactorsAuth.get2FaConfirmationResult
29-
</Button>
2+
<div class="m-6 mt-14 w-full max-w-2xl rounded-2xl border border-slate-200 bg-white/80 p-5 shadow-sm backdrop-blur-sm">
3+
<div class="grid gap-4 md:grid-cols-2">
4+
<section class="rounded-xl border border-slate-200 bg-slate-50 p-4">
5+
<div class="mb-3 text-xs font-semibold uppercase tracking-wider text-slate-500">
6+
LevelDB
7+
</div>
8+
<div class="flex flex-col gap-3">
9+
<div class="flex w-full gap-3">
10+
<Input class="w-full" v-model="levelDbKey" placeholder="LevelDB key" />
11+
<Input class="w-full" v-model="levelDbValue" placeholder="LevelDB value" />
12+
</div>
13+
<Button class="w-full" @click="addLevelDbKeyValue">
14+
Add level DB key/value
15+
</Button>
16+
<Input class="w-full" v-model="levelDbPrefix" placeholder="LevelDB prefix" />
17+
<Button class="w-full" @click="getLevelDbKeys">
18+
Get level db keys
19+
</Button>
20+
</div>
21+
</section>
22+
23+
<section class="rounded-xl border border-slate-200 bg-slate-50 p-4">
24+
<div class="mb-3 text-xs font-semibold uppercase tracking-wider text-slate-500">
25+
Jobs
26+
</div>
27+
<div class="flex flex-col gap-3">
28+
<Button class="w-full" @click="createJob">
29+
Create Job
30+
</Button>
31+
<Button class="w-full" @click="addTaskToTheLastJob">
32+
Add Task to the Last Job
33+
</Button>
34+
<Button class="w-full" @click="deleteTaskFromTheLastJob">
35+
Delete Task from the Last Job
36+
</Button>
37+
</div>
38+
</section>
39+
40+
<section class="rounded-xl border border-slate-200 bg-slate-50 p-4">
41+
<div class="mb-3 text-xs font-semibold uppercase tracking-wider text-slate-500">
42+
API
43+
</div>
44+
<div class="flex flex-col gap-3">
45+
<Button class="w-full" @click="callHelloWorldApi">
46+
Call API
47+
</Button>
48+
<Button class="w-full" @click="callHelloWorldApi">
49+
Refresh badge
50+
</Button>
51+
</div>
52+
</section>
53+
54+
<section class="rounded-xl border border-slate-200 bg-slate-50 p-4">
55+
<div class="mb-3 text-xs font-semibold uppercase tracking-wider text-slate-500">
56+
2FA
57+
</div>
58+
<div class="flex flex-col gap-3">
59+
<Button class="w-full px-4" @click="doTest2faCall">
60+
Test 2FA API Call
61+
</Button>
62+
<Button class="w-full px-4" @click="get2FaConfirmationResultWindow">
63+
2fa window.get2FaConfirmationResult (global window api)
64+
</Button>
65+
<Button class="w-full px-4" @click="get2FaConfirmationResultTwoFactorsAuth">
66+
2fa twoFactorsAuth. get2FaConfirmationResult
67+
</Button>
68+
</div>
69+
</section>
70+
</div>
71+
72+
<section class="mt-4 rounded-xl border border-slate-200 bg-slate-50 p-4">
73+
<div class="mb-3 text-xs font-semibold uppercase tracking-wider text-slate-500">
74+
Last API Output
75+
</div>
76+
<textarea
77+
v-model="lastApiOutput"
78+
class="h-72 w-full resize-y rounded-lg border border-slate-300 bg-white p-3 font-mono text-xs text-slate-700 outline-none"
79+
readonly
80+
/>
81+
</section>
3082
</div>
3183
</template>
3284

3385
<script setup lang="ts">
3486
import { ref, watch } from 'vue';
35-
import { Button } from '@/afcl'
87+
import { Button, Input } from '@/afcl'
3688
import { useAdminforth } from '@/adminforth';
3789
import { callApi } from '@/utils';
3890
@@ -43,26 +95,72 @@ import { useTwoFactorsAuth } from '@/custom/plugins/TwoFactorsAuthPlugin/use2faA
4395
4496
const { get2FaConfirmationResult } = useTwoFactorsAuth();
4597
const valueStart = ref()
98+
const levelDbKey = ref('');
99+
const levelDbValue = ref('');
100+
const levelDbPrefix = ref('');
101+
const lastApiOutput = ref('No output yet. Click a button to run an action.');
102+
103+
function setLastApiOutput(actionName: string, data: unknown, isError = false) {
104+
const status = isError ? 'ERROR' : 'OK';
105+
const serializedData = typeof data === 'string'
106+
? data
107+
: JSON.stringify(data, null, 2);
108+
109+
lastApiOutput.value = `[${status}] ${actionName}\n\n${serializedData}`;
110+
}
46111
47112
watch(valueStart, (newVal) => {
48113
console.log('New start value:', newVal);
49114
});
50115
116+
async function addLevelDbKeyValue() {
117+
try {
118+
const response = await callApi({
119+
path: '/api/addLevelDbKey/',
120+
method: 'POST',
121+
body: {
122+
key: levelDbKey.value,
123+
value: levelDbValue.value,
124+
},
125+
});
126+
console.log('LevelDB key/value added:', response);
127+
setLastApiOutput('Add level DB key/value', response);
128+
} catch (error) {
129+
console.error('Error adding LevelDB key/value:', error);
130+
setLastApiOutput('Add level DB key/value', String(error), true);
131+
}
132+
}
133+
134+
async function getLevelDbKeys() {
135+
try {
136+
const response = await callApi({ path: '/api/getLevelDbKeys/', method: 'POST', body: { prefix: levelDbPrefix.value } });
137+
console.log('LevelDB keys:', response);
138+
setLastApiOutput('Get level db keys', response);
139+
} catch (error) {
140+
console.error('Error getting LevelDB keys:', error);
141+
setLastApiOutput('Get level db keys', String(error), true);
142+
}
143+
}
144+
51145
async function createJob() {
52146
try {
53147
const res = await callApi({path: '/api/create-job/', method: 'POST'});
54148
console.log('Job created successfully:', res);
149+
setLastApiOutput('Create Job', res);
55150
} catch (error) {
56151
console.error('Error creating job:', error);
152+
setLastApiOutput('Create Job', String(error), true);
57153
}
58154
}
59155
60156
async function addTaskToTheLastJob() {
61157
try {
62158
const res = await callApi({path: '/api/add-task-to-last-job/', method: 'POST'});
63159
console.log('Task added to the last job successfully:', res);
160+
setLastApiOutput('Add Task to the Last Job', res);
64161
} catch (error) {
65162
console.error('Error adding task to the last job:', error);
163+
setLastApiOutput('Add Task to the Last Job', String(error), true);
66164
}
67165
}
68166
@@ -76,35 +174,43 @@ async function deleteTaskFromTheLastJob() {
76174
}
77175
});
78176
console.log('Task deleted from the last job successfully:', res);
177+
setLastApiOutput('Delete Task from the Last Job', res);
79178
} catch (error) {
80179
console.error('Error deleting task from the last job:', error);
180+
setLastApiOutput('Delete Task from the Last Job', String(error), true);
81181
}
82182
}
83183
84184
async function callHelloWorldApi() {
85185
try {
86186
const response = await callApi({ path: '/api/hello/', method: 'GET' });
87187
console.log('API response:', response);
188+
setLastApiOutput('Call API', response);
88189
} catch (error) {
89190
console.error('API error:', error);
191+
setLastApiOutput('Call API', String(error), true);
90192
}
91193
}
92194
93195
async function doTest2faCall() {
94196
try {
95197
const response = await callApi({ path: '/api/test2faCall/', method: 'GET' });
198+
setLastApiOutput('Test 2FA API Call', response);
96199
} catch (error) {
97200
console.error('2FA API error:', error);
201+
setLastApiOutput('Test 2FA API Call', String(error), true);
98202
}
99203
}
100204
101205
async function get2FaConfirmationResultWindow() {
102206
const verificationResult = await window.adminforthTwoFaModal.get2FaConfirmationResult(); // this will ask user to enter code
103207
console.log('2FA verification result (window):', verificationResult);
208+
setLastApiOutput('2fa window.get2FaConfirmationResult', verificationResult);
104209
}
105210
106211
async function get2FaConfirmationResultTwoFactorsAuth() {
107212
const verificationResult = await get2FaConfirmationResult(); // this will ask user to enter code
108213
console.log('2FA verification result (twoFactorsAuth):', verificationResult);
214+
setLastApiOutput('2fa twoFactorsAuth.get2FaConfirmationResult', verificationResult);
109215
}
110216
</script>

0 commit comments

Comments
 (0)