@appweaver/data 0.0.0-stage → 2.0.0
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/LICENSE +21 -0
- package/README.md +61 -2
- package/config.d.ts +6 -0
- package/config.js +22 -0
- package/database/create-client.d.ts +11 -0
- package/database/create-client.js +145 -0
- package/database/database-config.d.ts +14 -0
- package/database/database-config.js +40 -0
- package/database/database-error.d.ts +49 -0
- package/database/database-error.js +216 -0
- package/database/index.d.ts +3 -0
- package/database/index.js +19 -0
- package/database/prisma-database.d.ts +33 -0
- package/database/prisma-database.js +178 -0
- package/database/run-transaction.d.ts +21 -0
- package/database/run-transaction.js +15 -0
- package/export/export-config.d.ts +7 -0
- package/export/export-config.js +17 -0
- package/export/export-service.d.ts +22 -0
- package/export/export-service.js +188 -0
- package/export/index.d.ts +1 -0
- package/export/index.js +17 -0
- package/factory/create-model.d.ts +11 -0
- package/factory/create-model.js +479 -0
- package/factory/create-policy.d.ts +12 -0
- package/factory/create-policy.js +20 -0
- package/factory/create-service.d.ts +14 -0
- package/factory/create-service.js +116 -0
- package/index.d.ts +22 -0
- package/index.js +38 -0
- package/internal.d.ts +2 -0
- package/internal.js +6 -0
- package/module.d.ts +3 -0
- package/module.js +81 -0
- package/package.json +67 -3
- package/prisma/client/browser.d.ts +39 -0
- package/prisma/client/browser.js +56 -0
- package/prisma/client/client.d.ts +58 -0
- package/prisma/client/client.js +70 -0
- package/prisma/client/commonInputTypes.d.ts +345 -0
- package/prisma/client/commonInputTypes.js +11 -0
- package/prisma/client/enums.d.ts +1 -0
- package/prisma/client/enums.js +11 -0
- package/prisma/client/internal/class.d.ts +198 -0
- package/prisma/client/internal/class.js +85 -0
- package/prisma/client/internal/prismaNamespace.d.ts +1125 -0
- package/prisma/client/internal/prismaNamespace.js +204 -0
- package/prisma/client/internal/prismaNamespaceBrowser.d.ts +137 -0
- package/prisma/client/internal/prismaNamespaceBrowser.js +175 -0
- package/prisma/client/models/ApiKey.d.ts +1167 -0
- package/prisma/client/models/ApiKey.js +2 -0
- package/prisma/client/models/ConnectedAccount.d.ts +1094 -0
- package/prisma/client/models/ConnectedAccount.js +2 -0
- package/prisma/client/models/File.d.ts +1291 -0
- package/prisma/client/models/File.js +2 -0
- package/prisma/client/models/OneTimeToken.d.ts +1055 -0
- package/prisma/client/models/OneTimeToken.js +2 -0
- package/prisma/client/models/Permission.d.ts +1209 -0
- package/prisma/client/models/Permission.js +2 -0
- package/prisma/client/models/Role.d.ts +1209 -0
- package/prisma/client/models/Role.js +2 -0
- package/prisma/client/models/Seeder.d.ts +1023 -0
- package/prisma/client/models/Seeder.js +2 -0
- package/prisma/client/models.d.ts +8 -0
- package/prisma/client/models.js +2 -0
- package/resource/load-data-resources.d.ts +13 -0
- package/resource/load-data-resources.js +37 -0
- package/resource/model-schema.d.ts +34 -0
- package/resource/model-schema.js +54 -0
- package/resource/resource-config.d.ts +16 -0
- package/resource/resource-config.js +62 -0
- package/resource/resource-loader.d.ts +25 -0
- package/resource/resource-loader.js +138 -0
- package/resource/resource-service.d.ts +462 -0
- package/resource/resource-service.js +1042 -0
- package/resource/schemas/index.d.ts +3 -0
- package/resource/schemas/index.js +19 -0
- package/resource/schemas/resource-aggregate-schema.d.ts +53 -0
- package/resource/schemas/resource-aggregate-schema.js +130 -0
- package/resource/schemas/resource-filter-schema.d.ts +39 -0
- package/resource/schemas/resource-filter-schema.js +153 -0
- package/resource/schemas/resource-sort-schema.d.ts +38 -0
- package/resource/schemas/resource-sort-schema.js +113 -0
- package/resource/utils/aggregate-util.d.ts +113 -0
- package/resource/utils/aggregate-util.js +322 -0
- package/resource/utils/cursor-util.d.ts +60 -0
- package/resource/utils/cursor-util.js +116 -0
- package/resource/utils/date-util.d.ts +22 -0
- package/resource/utils/date-util.js +112 -0
- package/resource/utils/delete-util.d.ts +131 -0
- package/resource/utils/delete-util.js +385 -0
- package/resource/utils/filter-util.d.ts +24 -0
- package/resource/utils/filter-util.js +289 -0
- package/resource/utils/prune-util.d.ts +11 -0
- package/resource/utils/prune-util.js +56 -0
- package/resource/utils/relation-util.d.ts +75 -0
- package/resource/utils/relation-util.js +400 -0
- package/resource/utils/sort-util.d.ts +31 -0
- package/resource/utils/sort-util.js +235 -0
- package/resource/utils/text-search-util.d.ts +14 -0
- package/resource/utils/text-search-util.js +39 -0
- package/resources.d.ts +10 -0
- package/resources.js +26 -0
- package/security/auth-config.d.ts +23 -0
- package/security/auth-config.js +43 -0
- package/security/create-auth-resources.d.ts +28 -0
- package/security/create-auth-resources.js +163 -0
- package/security/helper.d.ts +109 -0
- package/security/helper.js +298 -0
- package/security/resources/api-key/model.d.ts +2 -0
- package/security/resources/api-key/model.js +67 -0
- package/security/resources/api-key/policy.d.ts +2 -0
- package/security/resources/api-key/policy.js +27 -0
- package/security/resources/api-key/service.d.ts +3 -0
- package/security/resources/api-key/service.js +34 -0
- package/security/resources/connected-account/model.d.ts +2 -0
- package/security/resources/connected-account/model.js +57 -0
- package/security/resources/connected-account/service.d.ts +2 -0
- package/security/resources/connected-account/service.js +7 -0
- package/security/resources/one-time-token/model.d.ts +2 -0
- package/security/resources/one-time-token/model.js +36 -0
- package/security/resources/permission/model.d.ts +2 -0
- package/security/resources/permission/model.js +16 -0
- package/security/resources/role/model.d.ts +2 -0
- package/security/resources/role/model.js +22 -0
- package/security/store/database-security-store.d.ts +5 -0
- package/security/store/database-security-store.js +54 -0
- package/seeder/create-seeder.d.ts +29 -0
- package/seeder/create-seeder.js +28 -0
- package/seeder/index.d.ts +2 -0
- package/seeder/index.js +18 -0
- package/seeder/resources/seeder/model.d.ts +2 -0
- package/seeder/resources/seeder/model.js +38 -0
- package/seeder/seeder.d.ts +29 -0
- package/seeder/seeder.js +197 -0
- package/storage/file-service.d.ts +133 -0
- package/storage/file-service.js +586 -0
- package/storage/image-config.d.ts +3 -0
- package/storage/image-config.js +11 -0
- package/storage/resources/file/model.d.ts +2 -0
- package/storage/resources/file/model.js +80 -0
- package/types/auth.d.ts +23 -0
- package/types/auth.js +2 -0
- package/types/generated.d.ts +366 -0
- package/types/generated.js +3 -0
- package/types/storage.d.ts +35 -0
- package/types/storage.js +2 -0
- package/utils/export-util.d.ts +8 -0
- package/utils/export-util.js +26 -0
- package/utils/file-util.d.ts +106 -0
- package/utils/file-util.js +254 -0
- package/utils/model-util.d.ts +36 -0
- package/utils/model-util.js +154 -0
- package/utils/policy-util.d.ts +18 -0
- package/utils/policy-util.js +28 -0
- package/utils/virtual-util.d.ts +11 -0
- package/utils/virtual-util.js +53 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** The placeholder a text search object marks the searched text with. */
|
|
2
|
+
export declare const TEXT_SEARCH_PLACEHOLDER = "{input}";
|
|
3
|
+
/**
|
|
4
|
+
* Builds the database filter of a text search object for the searched text,
|
|
5
|
+
* replacing every placeholder occurrence in its string values (i.e.
|
|
6
|
+
* `'{input}'`) with the text. An `OR` given as an object is turned into the
|
|
7
|
+
* list the database expects, each entry becoming one condition, the way the
|
|
8
|
+
* `_or` operator of a query filter reads it.
|
|
9
|
+
*
|
|
10
|
+
* @param {Object} template The text search object configured on the service.
|
|
11
|
+
* @param {string} input The searched text.
|
|
12
|
+
* @return {Object} A new filter object, the template is left untouched.
|
|
13
|
+
*/
|
|
14
|
+
export declare function bindTextSearch(template: any, input: string): any;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TEXT_SEARCH_PLACEHOLDER = void 0;
|
|
4
|
+
exports.bindTextSearch = bindTextSearch;
|
|
5
|
+
const common_1 = require("@appweaver/common");
|
|
6
|
+
/** The placeholder a text search object marks the searched text with. */
|
|
7
|
+
exports.TEXT_SEARCH_PLACEHOLDER = '{input}';
|
|
8
|
+
/**
|
|
9
|
+
* Builds the database filter of a text search object for the searched text,
|
|
10
|
+
* replacing every placeholder occurrence in its string values (i.e.
|
|
11
|
+
* `'{input}'`) with the text. An `OR` given as an object is turned into the
|
|
12
|
+
* list the database expects, each entry becoming one condition, the way the
|
|
13
|
+
* `_or` operator of a query filter reads it.
|
|
14
|
+
*
|
|
15
|
+
* @param {Object} template The text search object configured on the service.
|
|
16
|
+
* @param {string} input The searched text.
|
|
17
|
+
* @return {Object} A new filter object, the template is left untouched.
|
|
18
|
+
*/
|
|
19
|
+
function bindTextSearch(template, input) {
|
|
20
|
+
if ((0, common_1.isString)(template)) {
|
|
21
|
+
return template.replaceAll(exports.TEXT_SEARCH_PLACEHOLDER, input);
|
|
22
|
+
}
|
|
23
|
+
if ((0, common_1.isArray)(template)) {
|
|
24
|
+
return template.map((item) => bindTextSearch(item, input));
|
|
25
|
+
}
|
|
26
|
+
if (!(0, common_1.isPlainObject)(template)) {
|
|
27
|
+
return template;
|
|
28
|
+
}
|
|
29
|
+
const bound = {};
|
|
30
|
+
for (const [key, value] of Object.entries(template)) {
|
|
31
|
+
bound[key] =
|
|
32
|
+
key === 'OR' && (0, common_1.isPlainObject)(value)
|
|
33
|
+
? Object.entries(value).map(([field, condition]) => ({
|
|
34
|
+
[field]: bindTextSearch(condition, input)
|
|
35
|
+
}))
|
|
36
|
+
: bindTextSearch(value, input);
|
|
37
|
+
}
|
|
38
|
+
return bound;
|
|
39
|
+
}
|
package/resources.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { default as apiKey } from './security/resources/api-key/model';
|
|
2
|
+
export { default as connectedAccount } from './security/resources/connected-account/model';
|
|
3
|
+
export { default as oneTimeToken } from './security/resources/one-time-token/model';
|
|
4
|
+
export { default as role } from './security/resources/role/model';
|
|
5
|
+
export { default as permission } from './security/resources/permission/model';
|
|
6
|
+
export { default as seeder } from './seeder/resources/seeder/model';
|
|
7
|
+
export { default as file } from './storage/resources/file/model';
|
|
8
|
+
export { default as apiKeyService } from './security/resources/api-key/service';
|
|
9
|
+
export { default as connectedAccountService } from './security/resources/connected-account/service';
|
|
10
|
+
export { default as apiKeyPolicy } from './security/resources/api-key/policy';
|
package/resources.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.apiKeyPolicy = exports.connectedAccountService = exports.apiKeyService = exports.file = exports.seeder = exports.permission = exports.role = exports.oneTimeToken = exports.connectedAccount = exports.apiKey = void 0;
|
|
7
|
+
var model_1 = require("./security/resources/api-key/model");
|
|
8
|
+
Object.defineProperty(exports, "apiKey", { enumerable: true, get: function () { return __importDefault(model_1).default; } });
|
|
9
|
+
var model_2 = require("./security/resources/connected-account/model");
|
|
10
|
+
Object.defineProperty(exports, "connectedAccount", { enumerable: true, get: function () { return __importDefault(model_2).default; } });
|
|
11
|
+
var model_3 = require("./security/resources/one-time-token/model");
|
|
12
|
+
Object.defineProperty(exports, "oneTimeToken", { enumerable: true, get: function () { return __importDefault(model_3).default; } });
|
|
13
|
+
var model_4 = require("./security/resources/role/model");
|
|
14
|
+
Object.defineProperty(exports, "role", { enumerable: true, get: function () { return __importDefault(model_4).default; } });
|
|
15
|
+
var model_5 = require("./security/resources/permission/model");
|
|
16
|
+
Object.defineProperty(exports, "permission", { enumerable: true, get: function () { return __importDefault(model_5).default; } });
|
|
17
|
+
var model_6 = require("./seeder/resources/seeder/model");
|
|
18
|
+
Object.defineProperty(exports, "seeder", { enumerable: true, get: function () { return __importDefault(model_6).default; } });
|
|
19
|
+
var model_7 = require("./storage/resources/file/model");
|
|
20
|
+
Object.defineProperty(exports, "file", { enumerable: true, get: function () { return __importDefault(model_7).default; } });
|
|
21
|
+
var service_1 = require("./security/resources/api-key/service");
|
|
22
|
+
Object.defineProperty(exports, "apiKeyService", { enumerable: true, get: function () { return __importDefault(service_1).default; } });
|
|
23
|
+
var service_2 = require("./security/resources/connected-account/service");
|
|
24
|
+
Object.defineProperty(exports, "connectedAccountService", { enumerable: true, get: function () { return __importDefault(service_2).default; } });
|
|
25
|
+
var policy_1 = require("./security/resources/api-key/policy");
|
|
26
|
+
Object.defineProperty(exports, "apiKeyPolicy", { enumerable: true, get: function () { return __importDefault(policy_1).default; } });
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const passwordConfig: Readonly<{
|
|
2
|
+
ENABLED: boolean;
|
|
3
|
+
MIN_LENGTH: number;
|
|
4
|
+
MAX_LENGTH: number;
|
|
5
|
+
UPPERCASE: boolean;
|
|
6
|
+
LOWERCASE: boolean;
|
|
7
|
+
NUMERIC: boolean;
|
|
8
|
+
SPECIAL: boolean;
|
|
9
|
+
}>;
|
|
10
|
+
export declare const apiKeyConfig: Readonly<{
|
|
11
|
+
MAX_DURATION?: number | undefined;
|
|
12
|
+
ENABLED: boolean;
|
|
13
|
+
KEEP_DATABASE_TABLE: boolean;
|
|
14
|
+
HEADER_NAME: string;
|
|
15
|
+
DELIMITER: string;
|
|
16
|
+
}>;
|
|
17
|
+
export declare const systemConfig: Readonly<{
|
|
18
|
+
ADMIN_INITIAL_PASSWORD?: string | undefined;
|
|
19
|
+
ADMIN_INITIAL_EMAIL: string;
|
|
20
|
+
}>;
|
|
21
|
+
export declare const connectedAccountConfig: Readonly<{
|
|
22
|
+
CONNECTED_ACCOUNTS_KEEP_DATABASE_TABLE: boolean;
|
|
23
|
+
}>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.connectedAccountConfig = exports.systemConfig = exports.apiKeyConfig = exports.passwordConfig = void 0;
|
|
4
|
+
const typebox_1 = require("@sinclair/typebox");
|
|
5
|
+
const common_1 = require("@appweaver/common");
|
|
6
|
+
exports.passwordConfig = (0, common_1.defineConfig)('security.password', {
|
|
7
|
+
/** Enable password-based authentication. Default: `true`. */
|
|
8
|
+
ENABLED: typebox_1.Type.Boolean({ default: true }),
|
|
9
|
+
/** Minimum password length. Default: `8`. */
|
|
10
|
+
MIN_LENGTH: typebox_1.Type.Integer({ default: 8 }),
|
|
11
|
+
/** Maximum password length. Default: `100`. */
|
|
12
|
+
MAX_LENGTH: typebox_1.Type.Integer({ default: 100 }),
|
|
13
|
+
/** Require at least one uppercase letter. Default: `true`. */
|
|
14
|
+
UPPERCASE: typebox_1.Type.Boolean({ default: true }),
|
|
15
|
+
/** Require at least one lowercase letter. Default: `true`. */
|
|
16
|
+
LOWERCASE: typebox_1.Type.Boolean({ default: true }),
|
|
17
|
+
/** Require at least one digit. Default: `true`. */
|
|
18
|
+
NUMERIC: typebox_1.Type.Boolean({ default: true }),
|
|
19
|
+
/** Require at least one special character. Default: `true`. */
|
|
20
|
+
SPECIAL: typebox_1.Type.Boolean({ default: true })
|
|
21
|
+
});
|
|
22
|
+
exports.apiKeyConfig = (0, common_1.defineConfig)('security.apiKey', {
|
|
23
|
+
/** Enable API key authentication. Default: `false`. */
|
|
24
|
+
ENABLED: typebox_1.Type.Boolean({ default: false }),
|
|
25
|
+
/** Keep the API key database table after migrations. Default: `false`. */
|
|
26
|
+
KEEP_DATABASE_TABLE: typebox_1.Type.Boolean({ default: false }),
|
|
27
|
+
/** Request the header name for the API key. Default: `'x-api-key'`. */
|
|
28
|
+
HEADER_NAME: typebox_1.Type.String({ default: 'x-api-key' }),
|
|
29
|
+
/** Maximum API key validity duration in milliseconds. */
|
|
30
|
+
MAX_DURATION: typebox_1.Type.Optional(typebox_1.Type.Integer()),
|
|
31
|
+
/** Prefix delimiter between key ID and secret value. Default: `'AK'`. */
|
|
32
|
+
DELIMITER: typebox_1.Type.String({ default: 'AK' })
|
|
33
|
+
});
|
|
34
|
+
exports.systemConfig = (0, common_1.defineConfig)('system', {
|
|
35
|
+
/** Initial admin account email created on the first run. Default: `'admin@appweaver.co'`. */
|
|
36
|
+
ADMIN_INITIAL_EMAIL: typebox_1.Type.String({ default: 'admin@appweaver.co' }),
|
|
37
|
+
/** Initial admin account password. */
|
|
38
|
+
ADMIN_INITIAL_PASSWORD: typebox_1.Type.Optional(typebox_1.Type.String())
|
|
39
|
+
});
|
|
40
|
+
exports.connectedAccountConfig = (0, common_1.defineConfig)('security.oauth2', {
|
|
41
|
+
/** Keep the `ConnectedAccount` database table even when every OAuth2 provider is disabled. Default: `false`. */
|
|
42
|
+
CONNECTED_ACCOUNTS_KEEP_DATABASE_TABLE: typebox_1.Type.Boolean({ default: false })
|
|
43
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Ctor, IResourceService, ModelName, RegistryType, ResourceModel, ResourceModelConfig, ResourceServiceConfig } from '@appweaver/common';
|
|
2
|
+
import { CheckOAuth2UserFn, RegistrationDataFn, RegistrationFilesFn } from '../types/auth';
|
|
3
|
+
/** The fields an auth model adds to the configured ones. */
|
|
4
|
+
type AuthFieldName = 'email' | 'passwordHash' | 'verifiedEmail' | 'twoFactorAuth' | 'enabled' | 'logoutAt' | 'password' | 'roles' | 'apiKeys';
|
|
5
|
+
/**
|
|
6
|
+
* Creates the resource model of an authenticatable user, adding the email, password, verification, two-factor, and
|
|
7
|
+
* role fields to the configured ones.
|
|
8
|
+
*
|
|
9
|
+
* @param {ResourceModelConfig} modelConfig - The model configuration.
|
|
10
|
+
* @return {ResourceModel} The created auth resource model.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createAuthModel<S extends string, R extends string, F extends string, V extends string>(modelConfig: ResourceModelConfig<S, R, F, V, AuthFieldName>): ResourceModel;
|
|
13
|
+
/**
|
|
14
|
+
* Creates the resource service of an authenticatable user, hashing the password on create and update, along with the
|
|
15
|
+
* callbacks preparing the data and files of a registered user. Once the types are generated, the model, create, and
|
|
16
|
+
* update types are inferred from the model name.
|
|
17
|
+
*
|
|
18
|
+
* @param {ResourceServiceConfig} config - The service configuration with the model name, hooks, and registration
|
|
19
|
+
* callbacks.
|
|
20
|
+
* @return {Ctor<IResourceService>} The created service class, defined in the application context.
|
|
21
|
+
*/
|
|
22
|
+
export declare function createAuthService<N extends ModelName, T = RegistryType<N, 'model'>, C = RegistryType<N, 'create'>, U = RegistryType<N, 'update'>>(config: ResourceServiceConfig<T, C, U> & {
|
|
23
|
+
modelName: N;
|
|
24
|
+
registrationData?: RegistrationDataFn<C>;
|
|
25
|
+
registrationFiles?: RegistrationFilesFn;
|
|
26
|
+
checkOAuth2User?: CheckOAuth2UserFn;
|
|
27
|
+
}): Ctor<IResourceService<T, T, C, U>>;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAuthModel = createAuthModel;
|
|
4
|
+
exports.createAuthService = createAuthService;
|
|
5
|
+
const common_1 = require("@appweaver/common");
|
|
6
|
+
const auth_config_1 = require("./auth-config");
|
|
7
|
+
const helper_1 = require("./helper");
|
|
8
|
+
const create_model_1 = require("../factory/create-model");
|
|
9
|
+
const create_service_1 = require("../factory/create-service");
|
|
10
|
+
/**
|
|
11
|
+
* Creates the resource model of an authenticatable user, adding the email, password, verification, two-factor, and
|
|
12
|
+
* role fields to the configured ones.
|
|
13
|
+
*
|
|
14
|
+
* @param {ResourceModelConfig} modelConfig - The model configuration.
|
|
15
|
+
* @return {ResourceModel} The created auth resource model.
|
|
16
|
+
*/
|
|
17
|
+
function createAuthModel(modelConfig) {
|
|
18
|
+
const config = modelConfig;
|
|
19
|
+
const authModelScalars = {
|
|
20
|
+
email: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
unique: true,
|
|
23
|
+
maxLength: 255,
|
|
24
|
+
format: 'email'
|
|
25
|
+
},
|
|
26
|
+
passwordHash: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
required: false,
|
|
29
|
+
hidden: true
|
|
30
|
+
},
|
|
31
|
+
verifiedEmail: {
|
|
32
|
+
type: 'boolean',
|
|
33
|
+
default: false
|
|
34
|
+
},
|
|
35
|
+
twoFactorAuth: {
|
|
36
|
+
type: 'enum',
|
|
37
|
+
values: Object.values(common_1.TwoFactorAuth),
|
|
38
|
+
default: common_1.TwoFactorAuth.None
|
|
39
|
+
},
|
|
40
|
+
enabled: {
|
|
41
|
+
type: 'boolean',
|
|
42
|
+
default: true
|
|
43
|
+
},
|
|
44
|
+
logoutAt: {
|
|
45
|
+
type: 'dateTime',
|
|
46
|
+
required: false
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
// Override email properties if already present in the model config
|
|
50
|
+
if (config.scalars?.email?.type === 'string') {
|
|
51
|
+
authModelScalars.email = {
|
|
52
|
+
...authModelScalars.email,
|
|
53
|
+
...config.scalars.email
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const authModelVirtual = {
|
|
57
|
+
password: {
|
|
58
|
+
type: 'string',
|
|
59
|
+
required: true,
|
|
60
|
+
input: {
|
|
61
|
+
type: 'all'
|
|
62
|
+
},
|
|
63
|
+
output: {
|
|
64
|
+
type: 'none'
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
const authModelRelations = {
|
|
69
|
+
roles: {
|
|
70
|
+
model: 'Role',
|
|
71
|
+
type: 'manyToMany',
|
|
72
|
+
input: {
|
|
73
|
+
type: 'all'
|
|
74
|
+
},
|
|
75
|
+
output: {
|
|
76
|
+
type: 'always',
|
|
77
|
+
include: {
|
|
78
|
+
permissions: {
|
|
79
|
+
type: 'always'
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
...(auth_config_1.apiKeyConfig.ENABLED
|
|
85
|
+
? {
|
|
86
|
+
apiKeys: {
|
|
87
|
+
model: 'ApiKey',
|
|
88
|
+
type: 'oneToMany',
|
|
89
|
+
mappedBy: (0, common_1.uncapitalize)(config.name),
|
|
90
|
+
input: {
|
|
91
|
+
type: 'none'
|
|
92
|
+
},
|
|
93
|
+
output: {
|
|
94
|
+
type: 'none'
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
: {}),
|
|
99
|
+
...((0, helper_1.isOAuth2Enabled)()
|
|
100
|
+
? {
|
|
101
|
+
connectedAccounts: {
|
|
102
|
+
model: 'ConnectedAccount',
|
|
103
|
+
type: 'oneToMany',
|
|
104
|
+
mappedBy: (0, common_1.uncapitalize)(config.name),
|
|
105
|
+
input: {
|
|
106
|
+
type: 'none'
|
|
107
|
+
},
|
|
108
|
+
output: {
|
|
109
|
+
type: 'none'
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
: {})
|
|
114
|
+
};
|
|
115
|
+
const authModelInputOmit = ['verifiedEmail', 'logoutAt'];
|
|
116
|
+
config.scalars = { ...config.scalars, ...authModelScalars };
|
|
117
|
+
config.virtual = { ...config.virtual, ...authModelVirtual };
|
|
118
|
+
config.relations = { ...config.relations, ...authModelRelations };
|
|
119
|
+
config.create = {
|
|
120
|
+
...(config.create ?? {}),
|
|
121
|
+
omit: [...(config.create?.omit ?? []), ...authModelInputOmit]
|
|
122
|
+
};
|
|
123
|
+
config.update = {
|
|
124
|
+
...(config.update ?? {}),
|
|
125
|
+
omit: [...(config.update?.omit ?? []), ...authModelInputOmit]
|
|
126
|
+
};
|
|
127
|
+
const model = (0, create_model_1.createModel)(config);
|
|
128
|
+
model[common_1.RESOURCE_AUTH] = true;
|
|
129
|
+
return model;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Creates the resource service of an authenticatable user, hashing the password on create and update, along with the
|
|
133
|
+
* callbacks preparing the data and files of a registered user. Once the types are generated, the model, create, and
|
|
134
|
+
* update types are inferred from the model name.
|
|
135
|
+
*
|
|
136
|
+
* @param {ResourceServiceConfig} config - The service configuration with the model name, hooks, and registration
|
|
137
|
+
* callbacks.
|
|
138
|
+
* @return {Ctor<IResourceService>} The created service class, defined in the application context.
|
|
139
|
+
*/
|
|
140
|
+
function createAuthService(config) {
|
|
141
|
+
// Capture original functions to invoke after new auth logic
|
|
142
|
+
const beforeCreate = config.beforeCreate;
|
|
143
|
+
const beforeUpdate = config.beforeUpdate;
|
|
144
|
+
config.beforeCreate = async (data) => {
|
|
145
|
+
await (0, helper_1.updatePasswordHash)(data, data['password']);
|
|
146
|
+
await beforeCreate?.(data);
|
|
147
|
+
};
|
|
148
|
+
config.beforeUpdate = async (id, data) => {
|
|
149
|
+
await (0, helper_1.updatePasswordHash)(data, data['password'], true);
|
|
150
|
+
await beforeUpdate?.(id, data);
|
|
151
|
+
};
|
|
152
|
+
if (!config.registrationData) {
|
|
153
|
+
config.registrationData = (_, email, password) => {
|
|
154
|
+
return {
|
|
155
|
+
email,
|
|
156
|
+
password
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
const service = (0, create_service_1.createService)(config);
|
|
161
|
+
service[common_1.RESOURCE_AUTH] = true;
|
|
162
|
+
return service;
|
|
163
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { AuthUser, IResourceService, ResourceModel, ValidationResult } from '@appweaver/common';
|
|
2
|
+
/**
|
|
3
|
+
* Evaluates and retrieves the resource authentication model from the available resource models.
|
|
4
|
+
*
|
|
5
|
+
* The function iterates through the resource models in the given context and returns the first model
|
|
6
|
+
* that satisfies the `isResourceAuthModel` condition. If no such model is found, it returns undefined.
|
|
7
|
+
*
|
|
8
|
+
* @return {ResourceModel | undefined} The resource authentication model if present, otherwise undefined.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resourceAuthModel(): ResourceModel | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Provides authentication service for a resource by identifying and injecting
|
|
13
|
+
* the appropriate resource authentication service if available.
|
|
14
|
+
*
|
|
15
|
+
* @return {IResourceService<AuthUser, AuthUser> | undefined} The resource authentication service
|
|
16
|
+
* instance if found, otherwise undefined.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resourceAuthService(): IResourceService<AuthUser, AuthUser> | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Hashes a plain text password with the Argon2id function of the runtime and a random salt. The hash holds the
|
|
21
|
+
* Argon2 parameters and the salt, in the PHC string format `$argon2id$v=19$m=19456,t=2,p=1$<salt>$<key>`.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} password - The plain text password to be hashed.
|
|
24
|
+
* @return {Promise<string>} A promise that resolves to the hashed password.
|
|
25
|
+
*/
|
|
26
|
+
export declare function hashPassword(password: string): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Validates a plain text password against a hashed password, using the parameters stored in the hash. A hash not in
|
|
29
|
+
* the form {@link hashPassword} produces never matches.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} password - The plain text password to validate.
|
|
32
|
+
* @param {string} passwordHash - The hashed password to compare against.
|
|
33
|
+
* @return {Promise<boolean>} Returns a promise that resolves to `true` if the password matches the hash,
|
|
34
|
+
* otherwise `false`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function checkPassword(password: string, passwordHash: string): Promise<boolean>;
|
|
37
|
+
/**
|
|
38
|
+
* Tells whether a password hash was made with other parameters than {@link hashPassword} uses now, so it should be
|
|
39
|
+
* replaced with a new hash of the password, e.g. on the next successful login.
|
|
40
|
+
*
|
|
41
|
+
* @param {string} passwordHash - The stored password hash.
|
|
42
|
+
* @return {boolean} `true` if the hash is not a current Argon2id hash, otherwise `false`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function needsRehash(passwordHash: string): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Updates the password hash for a given user and optionally logs the user out by setting a logout timestamp.
|
|
47
|
+
*
|
|
48
|
+
* @param {Partial<AuthUser>} authUser - The user object containing authentication details. Only partial fields are
|
|
49
|
+
* expected.
|
|
50
|
+
* @param {string} [password] - The new password to hash and set for the user. If not provided, no password update
|
|
51
|
+
* occurs.
|
|
52
|
+
* @param {boolean} [logout=false] - Indicates whether to log the user out by setting the logout timestamp.
|
|
53
|
+
* @return Resolves when the password hash is updated and optional logout processing is complete.
|
|
54
|
+
* @throws {AuthError} `AUTH_PASSWORD_WEAK` if the provided password does not satisfy password complexity requirements.
|
|
55
|
+
*/
|
|
56
|
+
export declare function updatePasswordHash(authUser: Partial<AuthUser>, password?: string, logout?: boolean): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Validates the complexity of a given password based on the configured rules.
|
|
59
|
+
* @param {string} password - The password to be validated.
|
|
60
|
+
* @return {ValidationResult} An object with the validation result and message.
|
|
61
|
+
*/
|
|
62
|
+
export declare function validatePasswordComplexity(password: string): ValidationResult;
|
|
63
|
+
/**
|
|
64
|
+
* Checks whether at least one OAuth2 provider is enabled, by resolving each OAuth2 auth source to its
|
|
65
|
+
* `SECURITY_OAUTH2_<PROVIDER>_ENABLED` config flag. New providers are picked up automatically as long as they follow
|
|
66
|
+
* that naming convention.
|
|
67
|
+
*
|
|
68
|
+
* @return {boolean} True when any OAuth2 provider is enabled.
|
|
69
|
+
*/
|
|
70
|
+
export declare function isOAuth2Enabled(): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Checks if the given user has a specific role.
|
|
73
|
+
*
|
|
74
|
+
* @param {AuthUser} authUser - The authenticated user object containing role information.
|
|
75
|
+
* @param {string} role - The name of the role to check for.
|
|
76
|
+
* @return {boolean} True if the user has the specified role; otherwise, false.
|
|
77
|
+
*/
|
|
78
|
+
export declare function hasRole(authUser: AuthUser, role: string): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Checks if the authenticated user has the required roles based on the specified operator.
|
|
81
|
+
*
|
|
82
|
+
* @param {AuthUser} authUser - The authenticated user whose roles are being checked.
|
|
83
|
+
* @param {Array<string> | undefined} roles - The list of roles to check against. If undefined, the method returns
|
|
84
|
+
* true`.
|
|
85
|
+
* @param {'or' | 'and'} [operator='or'] - The logical operator for role matching. Use 'or' to check if the user has at
|
|
86
|
+
* least one role, and 'and' to check if the user has all roles.
|
|
87
|
+
* @return {boolean} Returns `true` if the user satisfies the role check based on the specified operator, otherwise
|
|
88
|
+
* `false`.
|
|
89
|
+
*/
|
|
90
|
+
export declare function hasRoles(authUser: AuthUser, roles: Array<string> | undefined, operator?: 'or' | 'and'): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Determines if the authenticated user has the specified permission.
|
|
93
|
+
*
|
|
94
|
+
* @param {AuthUser} authUser - The authenticated user object containing roles and permissions.
|
|
95
|
+
* @param {string} permission - The name of the permission to check for.
|
|
96
|
+
* @return {boolean} Returns true if the user has the specified permission, otherwise false.
|
|
97
|
+
*/
|
|
98
|
+
export declare function hasPermission(authUser: AuthUser, permission: string): boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Checks if the authenticated user has the specified permissions based on the given operator.
|
|
101
|
+
*
|
|
102
|
+
* @param {AuthUser} authUser - The authenticated user object.
|
|
103
|
+
* @param {string[] | undefined} permissions - The list of permissions to check. If undefined, it defaults to granting
|
|
104
|
+
* access.
|
|
105
|
+
* @param {'or' | 'and'} [operator='or'] - Determines whether all permissions (and) or at least one permission (or) must
|
|
106
|
+
* be satisfied.
|
|
107
|
+
* @return {boolean} Returns true if the user satisfies the permission requirements, false otherwise.
|
|
108
|
+
*/
|
|
109
|
+
export declare function hasPermissions(authUser: AuthUser, permissions: string[] | undefined, operator?: 'or' | 'and'): boolean;
|