adminforth 1.1.66 → 1.1.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/auth.ts +19 -4
- package/dist/auth.js +14 -4
- package/dist/index.js +3 -6
- package/dist/plugins/AuditLogPlugin/custom/AuditLogView.vue +2 -2
- package/dist/plugins/AuditLogPlugin/index.js +0 -1
- package/dist/servers/express.js +1 -1
- package/index.ts +3 -7
- package/package.json +1 -1
- package/plugins/AuditLogPlugin/custom/AuditLogView.vue +2 -2
- package/plugins/AuditLogPlugin/index.ts +0 -1
- package/servers/express.ts +1 -1
- package/types/AdminForthConfig.ts +2 -1
package/auth.ts
CHANGED
|
@@ -3,6 +3,7 @@ import jwt from 'jsonwebtoken';
|
|
|
3
3
|
|
|
4
4
|
import crypto from 'crypto';
|
|
5
5
|
import AdminForth from './index.js';
|
|
6
|
+
import { th } from '@faker-js/faker';
|
|
6
7
|
|
|
7
8
|
// Function to generate a password hash using PBKDF2
|
|
8
9
|
function calcPasswordHash(password, salt, iterations = 100000, keyLength = 64, digest = 'sha512') {
|
|
@@ -26,7 +27,18 @@ class AdminForthAuth {
|
|
|
26
27
|
this.adminforth = adminforth;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
removeAuthCookie(response) {
|
|
31
|
+
response.setHeader('Set-Cookie', `adminforth_jwt=; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; Expires=Thu, 01 Jan 1970 00:00:00 GMT`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setAuthCookie({ response, username, pk}: {
|
|
35
|
+
response: any, username: string, pk: string | null
|
|
36
|
+
}) {
|
|
37
|
+
const token = this.issueJWT({ username, pk, }, 'auth');
|
|
38
|
+
response.setHeader('Set-Cookie', `adminforth_jwt=${token}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
issueJWT(payload: Object, type: string) {
|
|
30
42
|
// read ADMINFORH_SECRET from environment if not drop error
|
|
31
43
|
const secret = process.env.ADMINFORTH_SECRET;
|
|
32
44
|
if (!secret) {
|
|
@@ -35,10 +47,10 @@ class AdminForthAuth {
|
|
|
35
47
|
|
|
36
48
|
// issue JWT token
|
|
37
49
|
const expiresIn = process.env.ADMINFORTH_AUTH_EXPIRESIN || '24h';
|
|
38
|
-
return jwt.sign(payload, secret, { expiresIn });
|
|
50
|
+
return jwt.sign({...payload, t: type}, secret, { expiresIn });
|
|
39
51
|
}
|
|
40
52
|
|
|
41
|
-
async verify(jwtToken) {
|
|
53
|
+
async verify(jwtToken: string, mustHaveType: string): Promise<Object> {
|
|
42
54
|
// read ADMINFORH_SECRET from environment if not drop error
|
|
43
55
|
const secret = process.env.ADMINFORTH_SECRET;
|
|
44
56
|
if (!secret) {
|
|
@@ -58,7 +70,10 @@ class AdminForthAuth {
|
|
|
58
70
|
}
|
|
59
71
|
return null;
|
|
60
72
|
}
|
|
61
|
-
const { pk } = decoded;
|
|
73
|
+
const { pk, t } = decoded;
|
|
74
|
+
if (t !== mustHaveType) {
|
|
75
|
+
throw new Error(`Invalid token type during verification: ${t}, must be ${mustHaveType}`);
|
|
76
|
+
}
|
|
62
77
|
if (pk === null) {
|
|
63
78
|
decoded.isRoot = true;
|
|
64
79
|
} else {
|
package/dist/auth.js
CHANGED
|
@@ -27,7 +27,14 @@ class AdminForthAuth {
|
|
|
27
27
|
constructor(adminforth) {
|
|
28
28
|
this.adminforth = adminforth;
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
removeAuthCookie(response) {
|
|
31
|
+
response.setHeader('Set-Cookie', `adminforth_jwt=; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; Expires=Thu, 01 Jan 1970 00:00:00 GMT`);
|
|
32
|
+
}
|
|
33
|
+
setAuthCookie({ response, username, pk }) {
|
|
34
|
+
const token = this.issueJWT({ username, pk, }, 'auth');
|
|
35
|
+
response.setHeader('Set-Cookie', `adminforth_jwt=${token}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict`);
|
|
36
|
+
}
|
|
37
|
+
issueJWT(payload, type) {
|
|
31
38
|
// read ADMINFORH_SECRET from environment if not drop error
|
|
32
39
|
const secret = process.env.ADMINFORTH_SECRET;
|
|
33
40
|
if (!secret) {
|
|
@@ -35,9 +42,9 @@ class AdminForthAuth {
|
|
|
35
42
|
}
|
|
36
43
|
// issue JWT token
|
|
37
44
|
const expiresIn = process.env.ADMINFORTH_AUTH_EXPIRESIN || '24h';
|
|
38
|
-
return jwt.sign(payload, secret, { expiresIn });
|
|
45
|
+
return jwt.sign(Object.assign(Object.assign({}, payload), { t: type }), secret, { expiresIn });
|
|
39
46
|
}
|
|
40
|
-
verify(jwtToken) {
|
|
47
|
+
verify(jwtToken, mustHaveType) {
|
|
41
48
|
return __awaiter(this, void 0, void 0, function* () {
|
|
42
49
|
// read ADMINFORH_SECRET from environment if not drop error
|
|
43
50
|
const secret = process.env.ADMINFORTH_SECRET;
|
|
@@ -61,7 +68,10 @@ class AdminForthAuth {
|
|
|
61
68
|
}
|
|
62
69
|
return null;
|
|
63
70
|
}
|
|
64
|
-
const { pk } = decoded;
|
|
71
|
+
const { pk, t } = decoded;
|
|
72
|
+
if (t !== mustHaveType) {
|
|
73
|
+
throw new Error(`Invalid token type during verification: ${t}, must be ${mustHaveType}`);
|
|
74
|
+
}
|
|
65
75
|
if (pk === null) {
|
|
66
76
|
decoded.isRoot = true;
|
|
67
77
|
}
|
package/dist/index.js
CHANGED
|
@@ -541,7 +541,7 @@ class AdminForth {
|
|
|
541
541
|
const { username, password } = body;
|
|
542
542
|
let token;
|
|
543
543
|
if (username === this.config.rootUser.username && password === this.config.rootUser.password) {
|
|
544
|
-
|
|
544
|
+
this.auth.setAuthCookie({ response, username, pk: null });
|
|
545
545
|
}
|
|
546
546
|
else {
|
|
547
547
|
// get resource from db
|
|
@@ -575,15 +575,12 @@ class AdminForth {
|
|
|
575
575
|
console.log('User record', userRecord, passwordHash); // why does it has no hash?
|
|
576
576
|
const valid = yield AdminForthAuth.verifyPassword(password, passwordHash);
|
|
577
577
|
if (valid) {
|
|
578
|
-
|
|
579
|
-
username, pk: userRecord[userResource.columns.find((col) => col.primaryKey).name]
|
|
580
|
-
});
|
|
578
|
+
this.auth.setAuthCookie({ response, username, pk: userRecord[userResource.columns.find((col) => col.primaryKey).name] });
|
|
581
579
|
}
|
|
582
580
|
else {
|
|
583
581
|
return { error: INVALID_MESSAGE };
|
|
584
582
|
}
|
|
585
583
|
}
|
|
586
|
-
response.setHeader('Set-Cookie', `adminforth_jwt=${token}; Path=${this.config.baseUrl || '/'}; HttpOnly; SameSite=Strict`);
|
|
587
584
|
return { ok: true };
|
|
588
585
|
}),
|
|
589
586
|
});
|
|
@@ -599,7 +596,7 @@ class AdminForth {
|
|
|
599
596
|
method: 'POST',
|
|
600
597
|
path: '/logout',
|
|
601
598
|
handler: (_e) => __awaiter(this, [_e], void 0, function* ({ response }) {
|
|
602
|
-
|
|
599
|
+
this.auth.removeAuthCookie({ response });
|
|
603
600
|
return { ok: true };
|
|
604
601
|
}),
|
|
605
602
|
});
|
|
@@ -14,8 +14,8 @@ const props = defineProps(['column', 'record', 'meta', 'resource', 'adminUser'])
|
|
|
14
14
|
:mode="'split'"
|
|
15
15
|
:theme="'light'"
|
|
16
16
|
:language="'JSON'"
|
|
17
|
-
:prev="props.record[props.meta.resourceColumns.resourceDataColumnName].oldRecord"
|
|
18
|
-
:current="props.record[props.meta.resourceColumns.resourceDataColumnName].newRecord"
|
|
17
|
+
:prev="JSON.stringify(JSON.parse(props.record[props.meta.resourceColumns.resourceDataColumnName]).oldRecord, null, 2)"
|
|
18
|
+
:current="JSON.stringify(JSON.parse(props.record[props.meta.resourceColumns.resourceDataColumnName]).newRecord, null, 2)"
|
|
19
19
|
/>
|
|
20
20
|
</template>
|
|
21
21
|
|
|
@@ -21,7 +21,6 @@ class AuditLogPlugin extends AdminForthPlugin {
|
|
|
21
21
|
'oldRecord': oldRecord || {},
|
|
22
22
|
'newRecord': newRecord
|
|
23
23
|
};
|
|
24
|
-
// console.log('newData', newData)
|
|
25
24
|
const record = {
|
|
26
25
|
[this.options.resourceColumns.resourceIdColumnName]: resource.resourceId,
|
|
27
26
|
[this.options.resourceColumns.resourceActionColumnName]: action,
|
package/dist/servers/express.js
CHANGED
|
@@ -149,7 +149,7 @@ class ExpressServer {
|
|
|
149
149
|
res.status(401).send('Unauthorized by AdminForth');
|
|
150
150
|
return;
|
|
151
151
|
}
|
|
152
|
-
const adminforthUser = yield this.adminforth.auth.verify(jwt);
|
|
152
|
+
const adminforthUser = yield this.adminforth.auth.verify(jwt, 'auth');
|
|
153
153
|
if (!adminforthUser) {
|
|
154
154
|
res.status(401).send('Unauthorized by AdminForth');
|
|
155
155
|
}
|
package/index.ts
CHANGED
|
@@ -626,7 +626,7 @@ class AdminForth implements AdminForthClass {
|
|
|
626
626
|
const { username, password } = body;
|
|
627
627
|
let token;
|
|
628
628
|
if (username === this.config.rootUser.username && password === this.config.rootUser.password) {
|
|
629
|
-
|
|
629
|
+
this.auth.setAuthCookie({ response, username, pk: null });
|
|
630
630
|
} else {
|
|
631
631
|
// get resource from db
|
|
632
632
|
if (!this.config.auth) {
|
|
@@ -664,15 +664,11 @@ class AdminForth implements AdminForthClass {
|
|
|
664
664
|
console.log('User record', userRecord, passwordHash) // why does it has no hash?
|
|
665
665
|
const valid = await AdminForthAuth.verifyPassword(password, passwordHash);
|
|
666
666
|
if (valid) {
|
|
667
|
-
|
|
668
|
-
username, pk: userRecord[userResource.columns.find((col) => col.primaryKey).name]
|
|
669
|
-
});
|
|
667
|
+
this.auth.setAuthCookie({ response, username, pk: userRecord[userResource.columns.find((col) => col.primaryKey).name] });
|
|
670
668
|
} else {
|
|
671
669
|
return { error: INVALID_MESSAGE };
|
|
672
670
|
}
|
|
673
671
|
}
|
|
674
|
-
|
|
675
|
-
response.setHeader('Set-Cookie', `adminforth_jwt=${token}; Path=${this.config.baseUrl || '/'}; HttpOnly; SameSite=Strict`);
|
|
676
672
|
return { ok: true };
|
|
677
673
|
},
|
|
678
674
|
});
|
|
@@ -690,7 +686,7 @@ class AdminForth implements AdminForthClass {
|
|
|
690
686
|
method: 'POST',
|
|
691
687
|
path: '/logout',
|
|
692
688
|
handler: async ({ response }) => {
|
|
693
|
-
|
|
689
|
+
this.auth.removeAuthCookie({ response });
|
|
694
690
|
return { ok: true };
|
|
695
691
|
},
|
|
696
692
|
})
|
package/package.json
CHANGED
|
@@ -14,8 +14,8 @@ const props = defineProps(['column', 'record', 'meta', 'resource', 'adminUser'])
|
|
|
14
14
|
:mode="'split'"
|
|
15
15
|
:theme="'light'"
|
|
16
16
|
:language="'JSON'"
|
|
17
|
-
:prev="props.record[props.meta.resourceColumns.resourceDataColumnName].oldRecord"
|
|
18
|
-
:current="props.record[props.meta.resourceColumns.resourceDataColumnName].newRecord"
|
|
17
|
+
:prev="JSON.stringify(JSON.parse(props.record[props.meta.resourceColumns.resourceDataColumnName]).oldRecord, null, 2)"
|
|
18
|
+
:current="JSON.stringify(JSON.parse(props.record[props.meta.resourceColumns.resourceDataColumnName]).newRecord, null, 2)"
|
|
19
19
|
/>
|
|
20
20
|
</template>
|
|
21
21
|
|
|
@@ -36,7 +36,6 @@ export default class AuditLogPlugin extends AdminForthPlugin {
|
|
|
36
36
|
'oldRecord': oldRecord || {},
|
|
37
37
|
'newRecord': newRecord
|
|
38
38
|
}
|
|
39
|
-
// console.log('newData', newData)
|
|
40
39
|
const record = {
|
|
41
40
|
[this.options.resourceColumns.resourceIdColumnName]: resource.resourceId,
|
|
42
41
|
[this.options.resourceColumns.resourceActionColumnName]: action,
|
package/servers/express.ts
CHANGED
|
@@ -157,7 +157,7 @@ class ExpressServer implements ExpressHttpServer {
|
|
|
157
157
|
res.status(401).send('Unauthorized by AdminForth');
|
|
158
158
|
return
|
|
159
159
|
}
|
|
160
|
-
const adminforthUser = await this.adminforth.auth.verify(jwt);
|
|
160
|
+
const adminforthUser = await this.adminforth.auth.verify(jwt, 'auth');
|
|
161
161
|
if (!adminforthUser) {
|
|
162
162
|
res.status(401).send('Unauthorized by AdminForth');
|
|
163
163
|
} else {
|
|
@@ -101,8 +101,9 @@ export interface AdminForthClass {
|
|
|
101
101
|
createResourceRecord(params: { resource: AdminForthResource, record: any, adminUser: AdminUser }): Promise<any>;
|
|
102
102
|
|
|
103
103
|
auth: {
|
|
104
|
+
verify(jwt : string, mustHaveType: string): Promise<any>;
|
|
104
105
|
|
|
105
|
-
|
|
106
|
+
issueJWT(payload: Object, type: string): string;
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
/**
|