adminforth 1.1.91 → 1.1.93
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/dataConnectors/baseConnector.ts +2 -2
- package/dataConnectors/mongo.ts +2 -2
- package/dataConnectors/postgres.ts +2 -2
- package/dataConnectors/sqlite.ts +2 -2
- package/dist/plugins/TwoFactorsAuthPlugin/index.js +2 -3
- package/dist/spa/spa/src/components/Toast.vue +1 -1
- package/index.ts +5 -5
- package/modules/codeInjector.ts +2 -2
- package/package.json +2 -2
- package/plugins/AuditLogPlugin/index.ts +3 -3
- package/plugins/ForeignInlineListPlugin/index.ts +4 -4
- package/plugins/S3UploadPlugin/custom/s3uploader.vue +24 -4
- package/plugins/S3UploadPlugin/index.ts +4 -4
- package/plugins/S3UploadPlugin/package.json +1 -1
- package/plugins/TwoFactorsAuthPlugin/dist/auth.js +108 -0
- package/plugins/TwoFactorsAuthPlugin/dist/dataConnectors/baseConnector.js +90 -0
- package/plugins/TwoFactorsAuthPlugin/dist/dataConnectors/mongo.js +191 -0
- package/plugins/TwoFactorsAuthPlugin/dist/dataConnectors/postgres.js +295 -0
- package/plugins/TwoFactorsAuthPlugin/dist/dataConnectors/sqlite.js +246 -0
- package/plugins/TwoFactorsAuthPlugin/dist/index.js +1186 -0
- package/plugins/TwoFactorsAuthPlugin/dist/modules/codeInjector.js +546 -0
- package/plugins/TwoFactorsAuthPlugin/dist/modules/styleGenerator.js +43 -0
- package/plugins/TwoFactorsAuthPlugin/dist/modules/styles.js +92 -0
- package/plugins/TwoFactorsAuthPlugin/dist/modules/utils.js +301 -0
- package/plugins/TwoFactorsAuthPlugin/dist/plugins/TwoFactorsAuthPlugin/index.js +149 -0
- package/plugins/TwoFactorsAuthPlugin/dist/plugins/TwoFactorsAuthPlugin/types.js +1 -0
- package/plugins/TwoFactorsAuthPlugin/dist/plugins/base.js +34 -0
- package/plugins/TwoFactorsAuthPlugin/dist/servers/express.js +230 -0
- package/plugins/TwoFactorsAuthPlugin/dist/types/AdminForthConfig.js +105 -0
- package/plugins/TwoFactorsAuthPlugin/index.ts +10 -10
- package/plugins/TwoFactorsAuthPlugin/package-lock.json +2 -2
- package/plugins/TwoFactorsAuthPlugin/package.json +8 -6
- package/plugins/TwoFactorsAuthPlugin/tsconfig.json +112 -0
- package/plugins/base.ts +4 -4
- package/servers/express.ts +4 -4
- package/spa/src/components/Toast.vue +1 -1
- package/tsconfig.json +1 -1
- package/types/AdminForthConfig.ts +34 -28
- package/types/FrontendAPI.ts +3 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { AdminForthResource,
|
|
1
|
+
import { AdminForthResource, IAdminForthDataSourceConnectorBase, AdminForthSortDirections, AdminForthFilterOperators, AdminForthResourceColumn } from "../types/AdminForthConfig.js";
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
export default class AdminForthBaseConnector implements
|
|
4
|
+
export default class AdminForthBaseConnector implements IAdminForthDataSourceConnectorBase {
|
|
5
5
|
getPrimaryKey(resource: AdminForthResource): string {
|
|
6
6
|
for (const col of resource.dataSourceColumns) {
|
|
7
7
|
if (col.primaryKey) {
|
package/dataConnectors/mongo.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import dayjs from 'dayjs';
|
|
2
2
|
import { MongoClient } from 'mongodb';
|
|
3
|
-
import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections,
|
|
3
|
+
import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections, IAdminForthDataSourceConnector } from '../types/AdminForthConfig.js';
|
|
4
4
|
|
|
5
|
-
class MongoConnector implements
|
|
5
|
+
class MongoConnector implements IAdminForthDataSourceConnector {
|
|
6
6
|
db: MongoClient
|
|
7
7
|
|
|
8
8
|
constructor({ url }: { url: string }) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import dayjs from 'dayjs';
|
|
2
2
|
import pkg from 'pg';
|
|
3
|
-
import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections,
|
|
3
|
+
import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections, IAdminForthDataSourceConnector } from '../types/AdminForthConfig.js';
|
|
4
4
|
import AdminForthBaseConnector from './baseConnector.js';
|
|
5
5
|
const { Client } = pkg;
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class PostgresConnector extends AdminForthBaseConnector implements
|
|
8
|
+
class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDataSourceConnector {
|
|
9
9
|
|
|
10
10
|
db: any;
|
|
11
11
|
|
package/dataConnectors/sqlite.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import betterSqlite3 from 'better-sqlite3';
|
|
2
|
-
import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections,
|
|
2
|
+
import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections, IAdminForthDataSourceConnector, AdminForthResource, AdminForthResourceColumn } from '../types/AdminForthConfig.js';
|
|
3
3
|
import AdminForthBaseConnector from './baseConnector.js';
|
|
4
4
|
import dayjs from 'dayjs';
|
|
5
5
|
|
|
6
|
-
class SQLiteConnector extends AdminForthBaseConnector implements
|
|
6
|
+
class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthDataSourceConnector {
|
|
7
7
|
|
|
8
8
|
db: any;
|
|
9
9
|
|
|
@@ -7,9 +7,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import AdminForthPlugin from "
|
|
10
|
+
import AdminForthPlugin from "adminforth/plugins/base.js";
|
|
11
11
|
import twofactor from 'node-2fa';
|
|
12
|
-
import AdminForthAuth from "../../auth.js";
|
|
13
12
|
export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
14
13
|
constructor(options) {
|
|
15
14
|
super(options, import.meta.url);
|
|
@@ -18,7 +17,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
|
|
|
18
17
|
modifyResourceConfig(adminforth, resourceConfig) {
|
|
19
18
|
super.modifyResourceConfig(adminforth, resourceConfig);
|
|
20
19
|
this.adminforth = adminforth;
|
|
21
|
-
this.adminForthAuth =
|
|
20
|
+
this.adminForthAuth = adminforth.auth;
|
|
22
21
|
const customPages = this.adminforth.config.customization.customPages;
|
|
23
22
|
customPages.push({
|
|
24
23
|
path: '/confirm2fa',
|
|
@@ -55,7 +55,7 @@ function closeToast() {
|
|
|
55
55
|
onMounted(() => {
|
|
56
56
|
if (props.toast.timeout === 'unlimited') return;
|
|
57
57
|
else {
|
|
58
|
-
setTimeout(() => {emit('close');}, props.toast.timeout
|
|
58
|
+
setTimeout(() => {emit('close');}, (props.toast.timeout || 10) * 1e3 );
|
|
59
59
|
}
|
|
60
60
|
});
|
|
61
61
|
|
package/index.ts
CHANGED
|
@@ -9,8 +9,8 @@ import ExpressServer from './servers/express.js';
|
|
|
9
9
|
import {v1 as uuid} from 'uuid';
|
|
10
10
|
import fs from 'fs';
|
|
11
11
|
import { ADMINFORTH_VERSION, listify } from './modules/utils.js';
|
|
12
|
-
import { AdminForthConfig,
|
|
13
|
-
AdminForthFilterOperators, AdminForthDataTypes, AdminForthResourcePages,
|
|
12
|
+
import { AdminForthConfig, IAdminForth, AdminForthComponentDeclaration, AdminForthComponentDeclarationFull,
|
|
13
|
+
AdminForthFilterOperators, AdminForthDataTypes, AdminForthResourcePages, IHttpServer,
|
|
14
14
|
BeforeSaveFunction,
|
|
15
15
|
AfterSaveFunction,
|
|
16
16
|
BeforeDataSourceRequestFunction,
|
|
@@ -19,7 +19,7 @@ import { AdminForthConfig, AdminForthClass, AdminForthComponentDeclaration, Admi
|
|
|
19
19
|
AllowedActionsEnum,
|
|
20
20
|
AllowedActions,
|
|
21
21
|
ActionCheckSource,
|
|
22
|
-
|
|
22
|
+
IAdminForthDataSourceConnector,
|
|
23
23
|
BeforeLoginConfirmationFunction
|
|
24
24
|
} from './types/AdminForthConfig.js';
|
|
25
25
|
import path from 'path';
|
|
@@ -30,7 +30,7 @@ import AdminForthPlugin from './plugins/base.js';
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
class AdminForth implements
|
|
33
|
+
class AdminForth implements IAdminForth {
|
|
34
34
|
static Types = AdminForthDataTypes;
|
|
35
35
|
|
|
36
36
|
static Utils = {
|
|
@@ -649,7 +649,7 @@ class AdminForth implements AdminForthClass {
|
|
|
649
649
|
}
|
|
650
650
|
}
|
|
651
651
|
|
|
652
|
-
setupEndpoints(server:
|
|
652
|
+
setupEndpoints(server: IHttpServer) {
|
|
653
653
|
server.endpoint({
|
|
654
654
|
noAuth: true,
|
|
655
655
|
method: 'POST',
|
package/modules/codeInjector.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { promisify } from 'util';
|
|
|
9
9
|
import AdminForth from '../index.js';
|
|
10
10
|
import { ADMIN_FORTH_ABSOLUTE_PATH, getComponentNameFromPath, transformObject, deepMerge } from './utils.js';
|
|
11
11
|
import { styles } from './styles.js'
|
|
12
|
-
import { AdminForthComponentDeclaration,
|
|
12
|
+
import { AdminForthComponentDeclaration, ICodeInjector } from '../types/AdminForthConfig.js';
|
|
13
13
|
import { StylesGenerator } from './styleGenerator.js';
|
|
14
14
|
|
|
15
15
|
|
|
@@ -36,7 +36,7 @@ function notifyWatcherIssue(limit) {
|
|
|
36
36
|
console.log('Run ulimit -n 10000 to increase the limit for open files.');
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
class CodeInjector implements
|
|
39
|
+
class CodeInjector implements ICodeInjector {
|
|
40
40
|
|
|
41
41
|
allWatchers = [];
|
|
42
42
|
adminforth: AdminForth;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adminforth",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.93",
|
|
4
4
|
"description": "OpenSource Vue3 powered forth-generation admin panel",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
9
9
|
"build": "tsc",
|
|
10
|
-
"prepareDist": "cp -r spa dist/spa
|
|
10
|
+
"prepareDist": "cp -r spa dist/spa",
|
|
11
11
|
"rollout": "tsc && npm run prepareDist && npm version patch && npm publish && cd documentation && npm run build && npm run deploy",
|
|
12
12
|
"docs": "typedoc"
|
|
13
13
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import AdminForth from "../../index.js";
|
|
2
2
|
import {
|
|
3
|
-
AdminForthResource,
|
|
3
|
+
AdminForthResource, IAdminForth, BeforeDataSourceRequestFunction,
|
|
4
4
|
AllowedActionsEnum,
|
|
5
5
|
BeforeSaveFunction,
|
|
6
6
|
AdminUser,
|
|
@@ -17,7 +17,7 @@ import { PluginOptions } from "./types.js";
|
|
|
17
17
|
export default class AuditLogPlugin extends AdminForthPlugin {
|
|
18
18
|
|
|
19
19
|
options: PluginOptions;
|
|
20
|
-
adminforth:
|
|
20
|
+
adminforth: IAdminForth;
|
|
21
21
|
auditLogResource: string;
|
|
22
22
|
|
|
23
23
|
constructor(options: PluginOptions) {
|
|
@@ -77,7 +77,7 @@ export default class AuditLogPlugin extends AdminForthPlugin {
|
|
|
77
77
|
return {ok: true};
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
modifyResourceConfig(adminforth:
|
|
80
|
+
modifyResourceConfig(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
|
|
81
81
|
super.modifyResourceConfig(adminforth, resourceConfig);
|
|
82
82
|
this.adminforth = adminforth;
|
|
83
83
|
this.auditLogResource = resourceConfig.resourceId;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AdminForthResource, AdminForthResourcePages,
|
|
1
|
+
import { AdminForthResource, AdminForthResourcePages, IAdminForth, IHttpServer } from "../../types/AdminForthConfig.js";
|
|
2
2
|
import AdminForthPlugin from "../base.js";
|
|
3
3
|
import { PluginOptions } from "./types.js";
|
|
4
4
|
|
|
@@ -6,14 +6,14 @@ import { PluginOptions } from "./types.js";
|
|
|
6
6
|
export default class ForeignInlineListPlugin extends AdminForthPlugin {
|
|
7
7
|
foreignResource: AdminForthResource;
|
|
8
8
|
options: PluginOptions;
|
|
9
|
-
adminforth:
|
|
9
|
+
adminforth: IAdminForth;
|
|
10
10
|
|
|
11
11
|
constructor(options: PluginOptions) {
|
|
12
12
|
super(options, import.meta.url);
|
|
13
13
|
this.options = options;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
setupEndpoints(server:
|
|
16
|
+
setupEndpoints(server: IHttpServer) {
|
|
17
17
|
server.endpoint({
|
|
18
18
|
method: 'POST',
|
|
19
19
|
path: `/plugin/${this.pluginInstanceId}/get_resource`,
|
|
@@ -34,7 +34,7 @@ export default class ForeignInlineListPlugin extends AdminForthPlugin {
|
|
|
34
34
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
modifyResourceConfig(adminforth:
|
|
37
|
+
modifyResourceConfig(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
|
|
38
38
|
super.modifyResourceConfig(adminforth, resourceConfig);
|
|
39
39
|
this.adminforth = adminforth;
|
|
40
40
|
|
|
@@ -103,11 +103,9 @@ const onFileChange = async (e) => {
|
|
|
103
103
|
}
|
|
104
104
|
reader.readAsDataURL(file);
|
|
105
105
|
}
|
|
106
|
-
|
|
107
|
-
progress.value += 1;
|
|
108
|
-
}, 20);
|
|
106
|
+
|
|
109
107
|
|
|
110
|
-
await callAdminForthApi({
|
|
108
|
+
const { url, previewUrl, s3Path } = await callAdminForthApi({
|
|
111
109
|
path: `/plugin/${props.meta.pluginInstanceId}/get_s3_upload_url`,
|
|
112
110
|
method: 'POST',
|
|
113
111
|
body: {
|
|
@@ -117,6 +115,28 @@ const onFileChange = async (e) => {
|
|
|
117
115
|
originalExtension: extension,
|
|
118
116
|
},
|
|
119
117
|
});
|
|
118
|
+
|
|
119
|
+
console.log('S3 upload URL:', url);
|
|
120
|
+
|
|
121
|
+
const formData = new FormData();
|
|
122
|
+
for (const key in s3Path.fields) {
|
|
123
|
+
formData.append(key, s3Path.fields[key]);
|
|
124
|
+
}
|
|
125
|
+
formData.append('file', file);
|
|
126
|
+
// upload as multipart request and update upload progress
|
|
127
|
+
const response = await fetch(url, {
|
|
128
|
+
method: 'POST',
|
|
129
|
+
body: formData,
|
|
130
|
+
headers: {
|
|
131
|
+
'Content-Type': 'multipart/form-data',
|
|
132
|
+
},
|
|
133
|
+
onUploadProgress: (progressEvent) => {
|
|
134
|
+
progress.value = Math.round((progressEvent.loaded / progressEvent.total) * 100);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
const data = await response.json();
|
|
138
|
+
console.log('S3 upload response:', data);
|
|
139
|
+
|
|
120
140
|
}
|
|
121
141
|
|
|
122
142
|
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
2
|
+
import { IAdminForth, IHttpServer } from "../../types/AdminForthConfig.js";
|
|
3
3
|
import AdminForthPlugin from "../base.js";
|
|
4
4
|
import { PluginOptions } from './types.js';
|
|
5
5
|
import AWS from 'aws-sdk';
|
|
6
6
|
|
|
7
7
|
export default class S3UploadPlugin extends AdminForthPlugin {
|
|
8
8
|
options: PluginOptions;
|
|
9
|
-
adminforth:
|
|
9
|
+
adminforth: IAdminForth;
|
|
10
10
|
|
|
11
11
|
constructor(options: PluginOptions) {
|
|
12
12
|
super(options, import.meta.url);
|
|
13
13
|
this.options = options;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
modifyResourceConfig(adminforth:
|
|
16
|
+
modifyResourceConfig(adminforth: IAdminForth, resourceConfig: any) {
|
|
17
17
|
super.modifyResourceConfig(adminforth, resourceConfig);
|
|
18
18
|
// after column to store the path of the uploaded file, add new VirtualColumn,
|
|
19
19
|
// show only in edit and create views
|
|
@@ -63,7 +63,7 @@ export default class S3UploadPlugin extends AdminForthPlugin {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
setupEndpoints(server:
|
|
66
|
+
setupEndpoints(server: IHttpServer) {
|
|
67
67
|
server.endpoint({
|
|
68
68
|
method: 'POST',
|
|
69
69
|
path: `/plugin/${this.pluginInstanceId}/get_s3_upload_url`,
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import jwt from 'jsonwebtoken';
|
|
11
|
+
import crypto from 'crypto';
|
|
12
|
+
// Function to generate a password hash using PBKDF2
|
|
13
|
+
function calcPasswordHash(password, salt, iterations = 100000, keyLength = 64, digest = 'sha512') {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
crypto.pbkdf2(password, salt, iterations, keyLength, digest, (err, derivedKey) => {
|
|
16
|
+
if (err)
|
|
17
|
+
reject(err);
|
|
18
|
+
resolve(derivedKey.toString('hex'));
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
// Function to generate a random salt
|
|
23
|
+
function generateSalt(length = 16) {
|
|
24
|
+
return crypto.randomBytes(length).toString('hex');
|
|
25
|
+
}
|
|
26
|
+
class AdminForthAuth {
|
|
27
|
+
constructor(adminforth) {
|
|
28
|
+
this.adminforth = adminforth;
|
|
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
|
+
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
|
+
removeCustomCookie({ response, name }) {
|
|
38
|
+
response.setHeader('Set-Cookie', `adminforth_test'='2'; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict`);
|
|
39
|
+
}
|
|
40
|
+
setCustomCookie({ response, payload }) {
|
|
41
|
+
const { name, value, expiry, httpOnly } = payload;
|
|
42
|
+
response.setHeader('Set-Cookie', `adminforth_${name}=${value}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; Expires=${new Date(Date.now() + expiry).toUTCString()} `);
|
|
43
|
+
}
|
|
44
|
+
issueJWT(payload, type) {
|
|
45
|
+
// read ADMINFORH_SECRET from environment if not drop error
|
|
46
|
+
const secret = process.env.ADMINFORTH_SECRET;
|
|
47
|
+
if (!secret) {
|
|
48
|
+
throw new Error('ADMINFORTH_SECRET environment not set');
|
|
49
|
+
}
|
|
50
|
+
// issue JWT token
|
|
51
|
+
const expiresIn = process.env.ADMINFORTH_AUTH_EXPIRESIN || '24h';
|
|
52
|
+
return jwt.sign(Object.assign(Object.assign({}, payload), { t: type }), secret, { expiresIn });
|
|
53
|
+
}
|
|
54
|
+
verify(jwtToken, mustHaveType) {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
// read ADMINFORH_SECRET from environment if not drop error
|
|
57
|
+
const secret = process.env.ADMINFORTH_SECRET;
|
|
58
|
+
if (!secret) {
|
|
59
|
+
throw new Error('ADMINFORTH_SECRET environment not set');
|
|
60
|
+
}
|
|
61
|
+
let decoded;
|
|
62
|
+
try {
|
|
63
|
+
// verify JWT token
|
|
64
|
+
decoded = jwt.verify(jwtToken, secret);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
if (err.name === 'TokenExpiredError') {
|
|
68
|
+
console.error('Token expired:', err.message);
|
|
69
|
+
}
|
|
70
|
+
else if (err.name === 'JsonWebTokenError') {
|
|
71
|
+
console.error('Token error:', err.message);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
console.error('Failed to verify JWT token', err);
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
const { pk, t } = decoded;
|
|
79
|
+
if (t !== mustHaveType) {
|
|
80
|
+
console.error(`Invalid token type during verification: ${t}, must be ${mustHaveType}`);
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
if (pk === null) {
|
|
84
|
+
decoded.isRoot = true;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const dbUser = yield this.adminforth.getUserByPk(pk);
|
|
88
|
+
decoded.dbUser = dbUser;
|
|
89
|
+
}
|
|
90
|
+
return decoded;
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
static generatePasswordHash(password) {
|
|
94
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
95
|
+
const salt = generateSalt();
|
|
96
|
+
const hashedPassword = yield calcPasswordHash(password, salt);
|
|
97
|
+
return `${salt}:${hashedPassword}`;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
static verifyPassword(password, hashedPassword) {
|
|
101
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
102
|
+
const [salt, hash] = hashedPassword.split(':');
|
|
103
|
+
const newHash = yield calcPasswordHash(password, salt);
|
|
104
|
+
return newHash === hash;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export default AdminForthAuth;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { AdminForthFilterOperators } from "../types/AdminForthConfig.js";
|
|
11
|
+
export default class AdminForthBaseConnector {
|
|
12
|
+
getPrimaryKey(resource) {
|
|
13
|
+
for (const col of resource.dataSourceColumns) {
|
|
14
|
+
if (col.primaryKey) {
|
|
15
|
+
return col.name;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
getRecordByPrimaryKeyWithOriginalTypes(resource, id) {
|
|
20
|
+
throw new Error('Method not implemented.');
|
|
21
|
+
}
|
|
22
|
+
getDataWithOriginalTypes({ resource, limit, offset, sort, filters }) {
|
|
23
|
+
throw new Error('Method not implemented.');
|
|
24
|
+
}
|
|
25
|
+
discoverFields(resource) {
|
|
26
|
+
throw new Error('Method not implemented.');
|
|
27
|
+
}
|
|
28
|
+
getFieldValue(field, value) {
|
|
29
|
+
throw new Error('Method not implemented.');
|
|
30
|
+
}
|
|
31
|
+
setFieldValue(field, value) {
|
|
32
|
+
throw new Error('Method not implemented.');
|
|
33
|
+
}
|
|
34
|
+
getMinMaxForColumnsWithOriginalTypes({ resource, columns }) {
|
|
35
|
+
throw new Error('Method not implemented.');
|
|
36
|
+
}
|
|
37
|
+
createRecord({ resource, record }) {
|
|
38
|
+
throw new Error('Method not implemented.');
|
|
39
|
+
}
|
|
40
|
+
updateRecord({ resource, recordId, newValues }) {
|
|
41
|
+
throw new Error('Method not implemented.');
|
|
42
|
+
}
|
|
43
|
+
deleteRecord({ resource, recordId }) {
|
|
44
|
+
throw new Error('Method not implemented.');
|
|
45
|
+
}
|
|
46
|
+
getData(_a) {
|
|
47
|
+
return __awaiter(this, arguments, void 0, function* ({ resource, limit, offset, sort, filters }) {
|
|
48
|
+
if (filters) {
|
|
49
|
+
filters.map((f) => {
|
|
50
|
+
if (f.operator == AdminForthFilterOperators.IN || f.operator == AdminForthFilterOperators.NIN) {
|
|
51
|
+
f.value = f.value.map((val) => this.setFieldValue(resource.dataSourceColumns.find((col) => col.name == f.field), val));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
f.value = this.setFieldValue(resource.dataSourceColumns.find((col) => col.name == f.field), f.value);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const d = yield this.getDataWithOriginalTypes({ resource, limit, offset, sort, filters });
|
|
59
|
+
// call getFieldValue for each field
|
|
60
|
+
d.data.map((record) => {
|
|
61
|
+
for (const col of resource.dataSourceColumns) {
|
|
62
|
+
record[col.name] = this.getFieldValue(col, record[col.name]);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
return d;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
getMinMaxForColumns(_a) {
|
|
69
|
+
return __awaiter(this, arguments, void 0, function* ({ resource, columns }) {
|
|
70
|
+
const mm = yield this.getMinMaxForColumnsWithOriginalTypes({ resource, columns });
|
|
71
|
+
const result = {};
|
|
72
|
+
for (const col of columns) {
|
|
73
|
+
result[col.name] = {
|
|
74
|
+
min: this.getFieldValue(col, mm[col.name].min),
|
|
75
|
+
max: this.getFieldValue(col, mm[col.name].max),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
getRecordByPrimaryKey(resource, recordId) {
|
|
82
|
+
return this.getRecordByPrimaryKeyWithOriginalTypes(resource, recordId).then((record) => {
|
|
83
|
+
const newRecord = {};
|
|
84
|
+
for (const col of resource.dataSourceColumns) {
|
|
85
|
+
newRecord[col.name] = this.getFieldValue(col, record[col.name]);
|
|
86
|
+
}
|
|
87
|
+
return newRecord;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|