@webda/core 4.0.0-beta.3 → 4.0.0-beta.5
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/lib/application/application.d.ts +31 -0
- package/lib/application/application.d.ts.map +1 -1
- package/lib/application/application.js +55 -2
- package/lib/application/application.js.map +1 -1
- package/lib/application/deployment.d.ts +93 -0
- package/lib/application/deployment.d.ts.map +1 -0
- package/lib/application/deployment.js +99 -0
- package/lib/application/deployment.js.map +1 -0
- package/lib/application/unpackedapplication.d.ts.map +1 -1
- package/lib/application/unpackedapplication.js +9 -1
- package/lib/application/unpackedapplication.js.map +1 -1
- package/lib/bin/cli.d.ts +36 -1
- package/lib/bin/cli.d.ts.map +1 -1
- package/lib/bin/cli.js +108 -2
- package/lib/bin/cli.js.map +1 -1
- package/lib/contexts/execution.js +1 -1
- package/lib/contexts/execution.js.map +1 -1
- package/lib/contexts/operationcontext.d.ts +3 -0
- package/lib/contexts/operationcontext.d.ts.map +1 -1
- package/lib/contexts/operationcontext.js +6 -3
- package/lib/contexts/operationcontext.js.map +1 -1
- package/lib/core/core.js +1 -1
- package/lib/core/core.js.map +1 -1
- package/lib/core/hooks.d.ts +22 -0
- package/lib/core/hooks.d.ts.map +1 -1
- package/lib/core/hooks.js +24 -0
- package/lib/core/hooks.js.map +1 -1
- package/lib/core/operations.d.ts.map +1 -1
- package/lib/core/operations.js +13 -11
- package/lib/core/operations.js.map +1 -1
- package/lib/deployers/deployer.d.ts +157 -0
- package/lib/deployers/deployer.d.ts.map +1 -0
- package/lib/deployers/deployer.js +81 -0
- package/lib/deployers/deployer.js.map +1 -0
- package/lib/deployers/git.d.ts +27 -0
- package/lib/deployers/git.d.ts.map +1 -0
- package/lib/deployers/git.js +66 -0
- package/lib/deployers/git.js.map +1 -0
- package/lib/deployers/packager.d.ts +85 -0
- package/lib/deployers/packager.d.ts.map +1 -0
- package/lib/deployers/packager.js +259 -0
- package/lib/deployers/packager.js.map +1 -0
- package/lib/index.d.ts +10 -4
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +10 -4
- package/lib/index.js.map +1 -1
- package/lib/models/aclmodel.d.ts +32 -5
- package/lib/models/aclmodel.d.ts.map +1 -1
- package/lib/models/aclmodel.js +34 -9
- package/lib/models/aclmodel.js.map +1 -1
- package/lib/models/coremodel.model.d.ts.map +1 -1
- package/lib/models/coremodel.model.js.map +1 -1
- package/lib/models/decorator.d.ts +4 -0
- package/lib/models/decorator.d.ts.map +1 -1
- package/lib/models/decorator.js +4 -0
- package/lib/models/decorator.js.map +1 -1
- package/lib/models/deployment.d.ts +2 -21
- package/lib/models/deployment.d.ts.map +1 -1
- package/lib/models/encrypted.model.d.ts +46 -0
- package/lib/models/encrypted.model.d.ts.map +1 -0
- package/lib/models/encrypted.model.js +87 -0
- package/lib/models/encrypted.model.js.map +1 -0
- package/lib/models/ident.model.d.ts +103 -64
- package/lib/models/ident.model.d.ts.map +1 -1
- package/lib/models/ident.model.js +168 -76
- package/lib/models/ident.model.js.map +1 -1
- package/lib/models/ownermodel.model.d.ts +25 -3
- package/lib/models/ownermodel.model.d.ts.map +1 -1
- package/lib/models/ownermodel.model.js +46 -10
- package/lib/models/ownermodel.model.js.map +1 -1
- package/lib/models/password.model.d.ts +78 -0
- package/lib/models/password.model.d.ts.map +1 -0
- package/lib/models/password.model.js +171 -0
- package/lib/models/password.model.js.map +1 -0
- package/lib/models/permissions.d.ts +236 -0
- package/lib/models/permissions.d.ts.map +1 -0
- package/lib/models/permissions.js +495 -0
- package/lib/models/permissions.js.map +1 -0
- package/lib/models/refreshtoken.model.d.ts +30 -0
- package/lib/models/refreshtoken.model.d.ts.map +1 -0
- package/lib/models/refreshtoken.model.js +29 -0
- package/lib/models/refreshtoken.model.js.map +1 -0
- package/lib/models/registry.model.d.ts.map +1 -1
- package/lib/models/registry.model.js.map +1 -1
- package/lib/models/rolemodel.model.d.ts.map +1 -1
- package/lib/models/rolemodel.model.js +1 -2
- package/lib/models/rolemodel.model.js.map +1 -1
- package/lib/models/simpleuser.model.d.ts.map +1 -1
- package/lib/models/simpleuser.model.js +2 -1
- package/lib/models/simpleuser.model.js.map +1 -1
- package/lib/models/user.model.d.ts +33 -21
- package/lib/models/user.model.d.ts.map +1 -1
- package/lib/models/user.model.js +81 -26
- package/lib/models/user.model.js.map +1 -1
- package/lib/rest/restoperationstransport.service.d.ts.map +1 -1
- package/lib/rest/restoperationstransport.service.js +7 -5
- package/lib/rest/restoperationstransport.service.js.map +1 -1
- package/lib/services/audit.model.d.ts +2 -2
- package/lib/services/audit.model.d.ts.map +1 -1
- package/lib/services/audit.model.js +16 -6
- package/lib/services/audit.model.js.map +1 -1
- package/lib/services/binary.service.d.ts +42 -4
- package/lib/services/binary.service.d.ts.map +1 -1
- package/lib/services/binary.service.js +33 -13
- package/lib/services/binary.service.js.map +1 -1
- package/lib/services/domainservice.service.d.ts +111 -1
- package/lib/services/domainservice.service.d.ts.map +1 -1
- package/lib/services/domainservice.service.js +303 -50
- package/lib/services/domainservice.service.js.map +1 -1
- package/lib/services/iauthentication.d.ts +196 -3
- package/lib/services/iauthentication.d.ts.map +1 -1
- package/lib/services/servicecommands.d.ts.map +1 -1
- package/lib/services/servicecommands.js +17 -11
- package/lib/services/servicecommands.js.map +1 -1
- package/lib/services/token.service.d.ts +95 -0
- package/lib/services/token.service.d.ts.map +1 -0
- package/lib/services/token.service.js +182 -0
- package/lib/services/token.service.js.map +1 -0
- package/lib/session/manager.model.d.ts +16 -0
- package/lib/session/manager.model.d.ts.map +1 -1
- package/lib/session/manager.model.js +58 -1
- package/lib/session/manager.model.js.map +1 -1
- package/lib/session/session.d.ts +44 -1
- package/lib/session/session.d.ts.map +1 -1
- package/lib/session/session.js +51 -2
- package/lib/session/session.js.map +1 -1
- package/lib/stores/memory.service.d.ts.map +1 -1
- package/lib/stores/memory.service.js +4 -3
- package/lib/stores/memory.service.js.map +1 -1
- package/lib/templates/templates.d.ts +8 -0
- package/lib/templates/templates.d.ts.map +1 -1
- package/lib/templates/templates.js +10 -1
- package/lib/templates/templates.js.map +1 -1
- package/lib/test/behavior-fixture.model.d.ts +30 -0
- package/lib/test/behavior-fixture.model.d.ts.map +1 -0
- package/lib/test/behavior-fixture.model.js +63 -0
- package/lib/test/behavior-fixture.model.js.map +1 -0
- package/lib/test/legacyident.fixture.model.d.ts +98 -0
- package/lib/test/legacyident.fixture.model.d.ts.map +1 -0
- package/lib/test/legacyident.fixture.model.js +125 -0
- package/lib/test/legacyident.fixture.model.js.map +1 -0
- package/lib/test/objects.d.ts +2 -2
- package/lib/test/objects.d.ts.map +1 -1
- package/lib/test/objects.js +2 -2
- package/lib/test/objects.js.map +1 -1
- package/package.json +32 -11
- package/test/config-cached.json +2 -1
- package/test/config.json +3 -1
- package/test/my-cnf.json +1 -1
- package/webda.module.json +656 -390
- package/lib/services/authentication.service.d.ts +0 -442
- package/lib/services/authentication.service.d.ts.map +0 -1
- package/lib/services/authentication.service.js +0 -932
- package/lib/services/authentication.service.js.map +0 -1
- package/lib/services/oauth.d.ts +0 -250
- package/lib/services/oauth.d.ts.map +0 -1
- package/lib/services/oauth.js +0 -405
- package/lib/services/oauth.js.map +0 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { WEBDA_STORAGE } from "@webda/models";
|
|
2
|
+
/**
|
|
3
|
+
* A model field encrypted at rest with the CryptoService
|
|
4
|
+
*
|
|
5
|
+
* Only the ciphertext is stored (`__ciphertext`, server-only: `__` keys never reach a public output). The value is
|
|
6
|
+
* JSON-serialised, encrypted with the current symmetric key (AES, with a random IV) and wrapped in a JWT signed with
|
|
7
|
+
* that key, so tampering is detected; values encrypted before a key rotation still decrypt while the CryptoService
|
|
8
|
+
* keeps the old key.
|
|
9
|
+
*
|
|
10
|
+
* ```typescript
|
|
11
|
+
* class MyModel extends UuidModel {
|
|
12
|
+
* secret: EncryptedField<{ apiKey: string }>;
|
|
13
|
+
* }
|
|
14
|
+
* await model.secret.set({ apiKey: "..." });
|
|
15
|
+
* await model.save();
|
|
16
|
+
* const { apiKey } = await model.secret.get();
|
|
17
|
+
* ```
|
|
18
|
+
* @WebdaBehavior Webda/Encrypted
|
|
19
|
+
*/
|
|
20
|
+
export declare class EncryptedField<T = any> {
|
|
21
|
+
[WEBDA_STORAGE]: Record<string, any>;
|
|
22
|
+
/** Encrypted value (a JWT wrapping the AES ciphertext), never output */
|
|
23
|
+
__ciphertext?: string;
|
|
24
|
+
/**
|
|
25
|
+
* @returns true when a value is stored
|
|
26
|
+
*/
|
|
27
|
+
isSet(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Encrypt and store a value (does not save the model); undefined clears it
|
|
30
|
+
* @param value - value to store, JSON-serialisable
|
|
31
|
+
*/
|
|
32
|
+
set(value: T | undefined): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Decrypt the stored value
|
|
35
|
+
* @returns the value, undefined when none is stored
|
|
36
|
+
* @throws Error when the ciphertext is invalid (tampered, or encrypted with an unknown key)
|
|
37
|
+
*/
|
|
38
|
+
get(): Promise<T | undefined>;
|
|
39
|
+
/**
|
|
40
|
+
* Remove the stored value (does not save the model)
|
|
41
|
+
*/
|
|
42
|
+
clear(): void;
|
|
43
|
+
get parent(): any;
|
|
44
|
+
toJSON(): Record<string, any>;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=encrypted.model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encrypted.model.d.ts","sourceRoot":"","sources":["../../src/models/encrypted.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAe9C;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,cAAc,CAAC,CAAC,GAAG,GAAG;IACjC,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAM;IAC1C,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,KAAK,IAAI,OAAO,CAEf;IAED;;;OAGG;IACG,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAM7C;IAED;;;;OAIG;IACG,GAAG,IAAI,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAKlC;IAED;;OAEG;IACH,KAAK,IAAI,IAAI,CAEZ;IACD,IAAI,MAAM,QAAgD;IAC1D,MAAM,wBAcL;CACF"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { WEBDA_STORAGE } from "@webda/models";
|
|
2
|
+
import { useDynamicService } from "../core/hooks.js";
|
|
3
|
+
/**
|
|
4
|
+
* @returns the CryptoService
|
|
5
|
+
* @throws Error when no CryptoService is available
|
|
6
|
+
*/
|
|
7
|
+
function crypto() {
|
|
8
|
+
const service = useDynamicService("CryptoService");
|
|
9
|
+
if (!service) {
|
|
10
|
+
throw new Error("Encrypted fields require the CryptoService");
|
|
11
|
+
}
|
|
12
|
+
return service;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A model field encrypted at rest with the CryptoService
|
|
16
|
+
*
|
|
17
|
+
* Only the ciphertext is stored (`__ciphertext`, server-only: `__` keys never reach a public output). The value is
|
|
18
|
+
* JSON-serialised, encrypted with the current symmetric key (AES, with a random IV) and wrapped in a JWT signed with
|
|
19
|
+
* that key, so tampering is detected; values encrypted before a key rotation still decrypt while the CryptoService
|
|
20
|
+
* keeps the old key.
|
|
21
|
+
*
|
|
22
|
+
* ```typescript
|
|
23
|
+
* class MyModel extends UuidModel {
|
|
24
|
+
* secret: EncryptedField<{ apiKey: string }>;
|
|
25
|
+
* }
|
|
26
|
+
* await model.secret.set({ apiKey: "..." });
|
|
27
|
+
* await model.save();
|
|
28
|
+
* const { apiKey } = await model.secret.get();
|
|
29
|
+
* ```
|
|
30
|
+
* @WebdaBehavior Webda/Encrypted
|
|
31
|
+
*/
|
|
32
|
+
export class EncryptedField {
|
|
33
|
+
[WEBDA_STORAGE] = {};
|
|
34
|
+
/** Encrypted value (a JWT wrapping the AES ciphertext), never output */
|
|
35
|
+
__ciphertext;
|
|
36
|
+
/**
|
|
37
|
+
* @returns true when a value is stored
|
|
38
|
+
*/
|
|
39
|
+
isSet() {
|
|
40
|
+
return typeof this.__ciphertext === "string" && this.__ciphertext.length > 0;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Encrypt and store a value (does not save the model); undefined clears it
|
|
44
|
+
* @param value - value to store, JSON-serialisable
|
|
45
|
+
*/
|
|
46
|
+
async set(value) {
|
|
47
|
+
if (value === undefined) {
|
|
48
|
+
this.clear();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
this.__ciphertext = await crypto().encrypt(value);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Decrypt the stored value
|
|
55
|
+
* @returns the value, undefined when none is stored
|
|
56
|
+
* @throws Error when the ciphertext is invalid (tampered, or encrypted with an unknown key)
|
|
57
|
+
*/
|
|
58
|
+
async get() {
|
|
59
|
+
if (!this.isSet()) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
return crypto().decrypt(this.__ciphertext);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Remove the stored value (does not save the model)
|
|
66
|
+
*/
|
|
67
|
+
clear() {
|
|
68
|
+
this.__ciphertext = undefined;
|
|
69
|
+
}
|
|
70
|
+
get parent() { return this[WEBDA_STORAGE]["__parent__"]; }
|
|
71
|
+
toJSON() {
|
|
72
|
+
const result = {};
|
|
73
|
+
for (const key of Object.keys(this)) {
|
|
74
|
+
result[key] = this[key];
|
|
75
|
+
}
|
|
76
|
+
const storage = this[WEBDA_STORAGE];
|
|
77
|
+
if (storage) {
|
|
78
|
+
for (const key of Object.keys(storage)) {
|
|
79
|
+
if (key !== "__parent__") {
|
|
80
|
+
result[key] = storage[key];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=encrypted.model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encrypted.model.js","sourceRoot":"","sources":["../../src/models/encrypted.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD;;;GAGG;AACH,SAAS,MAAM;IACb,MAAM,OAAO,GAAG,iBAAiB,CAAM,eAAe,CAAC,CAAC;IACxD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,cAAc;IACzB,CAAC,aAAa,CAAC,GAAwB,EAAE,CAAC;IAC1C,wEAAwE;IACxE,YAAY,CAAU;IAEtB;;OAEG;IACH,KAAK;QACH,OAAO,OAAO,IAAI,CAAC,YAAY,KAAK,QAAQ,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/E,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAG,CAAC,KAAoB;QAC5B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,MAAM,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACpD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,GAAG;QACP,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YAClB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;IAChC,CAAC;IACD,IAAI,MAAM,KAAK,OAAO,IAAI,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC1D,MAAM;QACJ,MAAM,MAAM,GAAwB,EAAE,CAAC;QACvC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,MAAM,CAAC,GAAG,CAAC,GAAI,IAAY,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QACD,MAAM,OAAO,GAAqC,IAAY,CAAC,aAAa,CAAC,CAAC;QAC9E,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBACvC,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;oBACzB,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;gBAC7B,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
|
|
@@ -1,89 +1,128 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import type { PrimaryKeyType } from "@webda/models";
|
|
2
|
+
import { Model, ModelLink, WEBDA_PRIMARY_KEY, WEBDA_PRIMARY_KEY_SEPARATOR, type Settable } from "@webda/models";
|
|
3
|
+
import * as WebdaError from "../errors/errors.js";
|
|
4
|
+
import type { IOperationContext } from "../contexts/icontext.js";
|
|
5
|
+
import { User } from "./user.model.js";
|
|
6
|
+
import { EncryptedField } from "./encrypted.model.js";
|
|
7
|
+
/** Tokens (credentials) of an identity provider, as the provider returns them */
|
|
8
|
+
export interface IdentTokens {
|
|
9
|
+
/** Access token */
|
|
10
|
+
access_token?: string;
|
|
11
|
+
/** Refresh token */
|
|
12
|
+
refresh_token?: string;
|
|
13
|
+
/** Any other provider field */
|
|
14
|
+
[key: string]: any;
|
|
15
|
+
}
|
|
16
|
+
/** Email sending throttle state of an ident (login failures are top-level `Ident` attributes) */
|
|
17
|
+
export interface IdentThrottle {
|
|
18
|
+
/** Timestamp of the last email sent */
|
|
19
|
+
lastSentAt?: number;
|
|
20
|
+
}
|
|
21
|
+
/** Raised for malformed ident keys (400 INVALID_IDENT) */
|
|
22
|
+
export declare class InvalidIdent extends WebdaError.HttpError {
|
|
23
|
+
/** @param message - error message */
|
|
24
|
+
constructor(message?: string);
|
|
8
25
|
}
|
|
9
26
|
/**
|
|
10
|
-
*
|
|
11
|
-
* @class
|
|
27
|
+
* An identity linked to a user: `<providerUid>:<provider>`
|
|
12
28
|
* @WebdaModel
|
|
13
29
|
*/
|
|
14
|
-
export declare class Ident extends
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Last time the ident was used
|
|
37
|
-
*/
|
|
38
|
-
get _lastUsed(): Date;
|
|
39
|
-
set _lastUsed(value: string | number | Date);
|
|
30
|
+
export declare class Ident extends Model {
|
|
31
|
+
/** Composite primary key */
|
|
32
|
+
[WEBDA_PRIMARY_KEY]: readonly ["providerUid", "provider"];
|
|
33
|
+
[WEBDA_PRIMARY_KEY_SEPARATOR]: string;
|
|
34
|
+
/** Identifier on the provider (normalised email for "email") */
|
|
35
|
+
providerUid: string;
|
|
36
|
+
/** Provider name */
|
|
37
|
+
provider: string;
|
|
38
|
+
/** Owner */
|
|
39
|
+
get _user(): ModelLink<User>;
|
|
40
|
+
set _user(value: string | User | PrimaryKeyType<User> | ModelLink<User>);
|
|
41
|
+
/** Email asserted for this ident */
|
|
42
|
+
email?: string;
|
|
43
|
+
/** When the ident was verified */
|
|
44
|
+
get verifiedAt(): Date;
|
|
45
|
+
set verifiedAt(value: string | number | Date);
|
|
46
|
+
/** Last login with this ident */
|
|
47
|
+
get lastUsedAt(): Date;
|
|
48
|
+
set lastUsedAt(value: string | number | Date);
|
|
49
|
+
/** Email sending throttle state */
|
|
50
|
+
_throttle: IdentThrottle;
|
|
40
51
|
/**
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
52
|
+
* Login attempts counted since the last successful login
|
|
53
|
+
*
|
|
54
|
+
* Top-level so stores can increment it atomically (nested-path atomic operations are not portable)
|
|
55
|
+
*/
|
|
56
|
+
_loginAttempts: number;
|
|
57
|
+
/** Timestamp (ms) of the last counted login attempt */
|
|
58
|
+
_lastLoginAttemptAt?: number;
|
|
59
|
+
/** Provider profile */
|
|
60
|
+
__profile?: any;
|
|
61
|
+
/** Provider tokens, encrypted at rest (`await ident.tokens.get()`) */
|
|
62
|
+
tokens: EncryptedField<IdentTokens>;
|
|
63
|
+
/** @param data - initial data */
|
|
64
|
+
constructor(data?: Settable<Ident>);
|
|
44
65
|
/**
|
|
45
|
-
*
|
|
46
|
-
|
|
47
|
-
|
|
66
|
+
* Build and validate a key
|
|
67
|
+
* @param providerUid - uid on the provider
|
|
68
|
+
* @param provider - provider name
|
|
69
|
+
* @returns the composite key
|
|
70
|
+
*/
|
|
71
|
+
static key(providerUid: string, provider: string): {
|
|
72
|
+
providerUid: string;
|
|
73
|
+
provider: string;
|
|
74
|
+
};
|
|
48
75
|
/**
|
|
49
|
-
*
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
76
|
+
* Parse a v3 storage key `"<providerUid>_<provider>"`, split on its LAST "_" (provider names never
|
|
77
|
+
* contain "_", provider uids such as emails may)
|
|
78
|
+
*
|
|
79
|
+
* Consulted by repositories for keys that are not `"<providerUid>:<provider>"` (see `WEBDA_LEGACY_UID`),
|
|
80
|
+
* so v3 records stay addressable and queryable until they are upgraded.
|
|
81
|
+
* @param uid - raw storage key
|
|
82
|
+
* @returns the key parts, or undefined when the key is not a v3 ident key
|
|
83
|
+
*/
|
|
84
|
+
static parseLegacyUID(uid: string): {
|
|
85
|
+
providerUid: string;
|
|
86
|
+
provider: string;
|
|
87
|
+
} | undefined;
|
|
53
88
|
/**
|
|
54
|
-
*
|
|
89
|
+
* v3 storage key of a record stored before the composite key (v3 kept it as `uuid` in the body)
|
|
90
|
+
*
|
|
91
|
+
* Such an ident has no `providerUid`: it must be upgraded (`@webda/auth` `upgradeIdent`) before use.
|
|
92
|
+
* @returns the v3 key, or undefined for a current ident
|
|
55
93
|
*/
|
|
56
|
-
|
|
94
|
+
getLegacyUID(): string | undefined;
|
|
57
95
|
/**
|
|
58
|
-
*
|
|
96
|
+
* Normalise an email for use as providerUid
|
|
97
|
+
* @param email - raw email
|
|
98
|
+
* @returns trimmed lowercase email
|
|
59
99
|
*/
|
|
60
|
-
|
|
100
|
+
static normalizeEmail(email: string): string;
|
|
61
101
|
/**
|
|
62
|
-
*
|
|
63
|
-
* @returns the result string
|
|
102
|
+
* @returns the owner link
|
|
64
103
|
*/
|
|
65
|
-
|
|
104
|
+
getUser(): ModelLink<User>;
|
|
66
105
|
/**
|
|
67
|
-
*
|
|
68
|
-
* @returns the result
|
|
106
|
+
* @param user - owner uuid or user
|
|
69
107
|
*/
|
|
70
|
-
|
|
108
|
+
setUser(user: string | User): void;
|
|
71
109
|
/**
|
|
72
|
-
*
|
|
73
|
-
* @param type - the type to look up
|
|
110
|
+
* @returns the email of this ident
|
|
74
111
|
*/
|
|
75
|
-
|
|
112
|
+
getEmail(): string | undefined;
|
|
76
113
|
/**
|
|
77
|
-
*
|
|
78
|
-
* @returns the result
|
|
114
|
+
* @returns true when verified
|
|
79
115
|
*/
|
|
80
|
-
|
|
116
|
+
isVerified(): boolean;
|
|
81
117
|
/**
|
|
82
|
-
*
|
|
83
|
-
* @param
|
|
118
|
+
* Only the owner may act on an ident
|
|
119
|
+
* @param ctx - operation context
|
|
120
|
+
* @param action - action name
|
|
121
|
+
* @returns true or a refusal reason
|
|
84
122
|
*/
|
|
85
|
-
|
|
123
|
+
canAct(ctx: IOperationContext, action: string): Promise<string | boolean>;
|
|
86
124
|
/** Generated by @webda/content-mapper: include values held in WEBDA_STORAGE. */
|
|
87
125
|
toJSON(): any;
|
|
126
|
+
protected __hydrateBehaviors(rawData?: any): void;
|
|
88
127
|
}
|
|
89
128
|
//# sourceMappingURL=ident.model.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ident.model.d.ts","sourceRoot":"","sources":["../../src/models/ident.model.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ident.model.d.ts","sourceRoot":"","sources":["../../src/models/ident.model.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,115 +1,207 @@
|
|
|
1
1
|
import { WEBDA_STORAGE } from "@webda/models";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { Model, ModelLink, WEBDA_PRIMARY_KEY, WEBDA_PRIMARY_KEY_SEPARATOR } from "@webda/models";
|
|
3
|
+
import * as WebdaError from "../errors/errors.js";
|
|
4
|
+
import { User } from "./user.model.js";
|
|
5
|
+
import { EncryptedField } from "./encrypted.model.js";
|
|
6
|
+
/** Raised for malformed ident keys (400 INVALID_IDENT) */
|
|
7
|
+
export class InvalidIdent extends WebdaError.HttpError {
|
|
8
|
+
/** @param message - error message */
|
|
9
|
+
constructor(message = "Invalid ident") {
|
|
10
|
+
super(message, 400);
|
|
11
|
+
}
|
|
7
12
|
}
|
|
13
|
+
const SEPARATOR = ":";
|
|
8
14
|
/**
|
|
9
|
-
*
|
|
10
|
-
* @class
|
|
15
|
+
* An identity linked to a user: `<providerUid>:<provider>`
|
|
11
16
|
* @WebdaModel
|
|
12
17
|
*/
|
|
13
|
-
export class Ident extends
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
export class Ident extends Model {
|
|
19
|
+
/** Composite primary key */
|
|
20
|
+
[WEBDA_PRIMARY_KEY] = ["providerUid", "provider"];
|
|
21
|
+
// Must stay a string literal: the content mapper reads it textually
|
|
22
|
+
[WEBDA_PRIMARY_KEY_SEPARATOR] = ":";
|
|
23
|
+
/** Identifier on the provider (normalised email for "email") */
|
|
24
|
+
providerUid;
|
|
25
|
+
/** Provider name */
|
|
26
|
+
provider;
|
|
27
|
+
/** Owner */
|
|
28
|
+
get _user() {
|
|
29
|
+
return this[WEBDA_STORAGE]["_user"];
|
|
19
30
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
*/
|
|
39
|
-
get _lastUsed() {
|
|
40
|
-
return this[WEBDA_STORAGE]["_lastUsed"] ?? undefined;
|
|
31
|
+
set _user(value) {
|
|
32
|
+
if (value instanceof ModelLink) {
|
|
33
|
+
this[WEBDA_STORAGE]["_user"] = value;
|
|
34
|
+
}
|
|
35
|
+
else if (value != null) {
|
|
36
|
+
const inst = this[WEBDA_STORAGE]["_user"] || new ModelLink(User);
|
|
37
|
+
inst.set(value);
|
|
38
|
+
this[WEBDA_STORAGE]["_user"] = inst;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
this[WEBDA_STORAGE]["_user"] = value;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Email asserted for this ident */
|
|
45
|
+
email;
|
|
46
|
+
/** When the ident was verified */
|
|
47
|
+
get verifiedAt() {
|
|
48
|
+
return this[WEBDA_STORAGE]["verifiedAt"];
|
|
41
49
|
}
|
|
42
|
-
set
|
|
43
|
-
this[WEBDA_STORAGE]["
|
|
50
|
+
set verifiedAt(value) {
|
|
51
|
+
this[WEBDA_STORAGE]["verifiedAt"] = value !== undefined && value !== null ? new Date(value) : value;
|
|
44
52
|
}
|
|
53
|
+
/** Last login with this ident */
|
|
54
|
+
get lastUsedAt() {
|
|
55
|
+
return this[WEBDA_STORAGE]["lastUsedAt"];
|
|
56
|
+
}
|
|
57
|
+
set lastUsedAt(value) {
|
|
58
|
+
this[WEBDA_STORAGE]["lastUsedAt"] = value !== undefined && value !== null ? new Date(value) : value;
|
|
59
|
+
}
|
|
60
|
+
/** Email sending throttle state */
|
|
61
|
+
_throttle = {};
|
|
45
62
|
/**
|
|
46
|
-
*
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
63
|
+
* Login attempts counted since the last successful login
|
|
64
|
+
*
|
|
65
|
+
* Top-level so stores can increment it atomically (nested-path atomic operations are not portable)
|
|
66
|
+
*/
|
|
67
|
+
_loginAttempts = 0;
|
|
68
|
+
/** Timestamp (ms) of the last counted login attempt */
|
|
69
|
+
_lastLoginAttemptAt;
|
|
70
|
+
/** Provider profile */
|
|
71
|
+
__profile;
|
|
72
|
+
/** Provider tokens, encrypted at rest (`await ident.tokens.get()`) */
|
|
73
|
+
tokens;
|
|
74
|
+
/** @param data - initial data */
|
|
75
|
+
constructor(data) {
|
|
76
|
+
super();
|
|
77
|
+
Object.assign(this, data);
|
|
78
|
+
// Raw stored data (or none) must become an EncryptedField behavior
|
|
79
|
+
if (!(this.tokens instanceof EncryptedField)) {
|
|
80
|
+
this.__hydrateBehaviors?.({ tokens: data?.tokens ?? {} });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
53
83
|
/**
|
|
54
|
-
*
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
84
|
+
* Build and validate a key
|
|
85
|
+
* @param providerUid - uid on the provider
|
|
86
|
+
* @param provider - provider name
|
|
87
|
+
* @returns the composite key
|
|
88
|
+
*/
|
|
89
|
+
static key(providerUid, provider) {
|
|
90
|
+
for (const [name, v] of [
|
|
91
|
+
["providerUid", providerUid],
|
|
92
|
+
["provider", provider]
|
|
93
|
+
]) {
|
|
94
|
+
if (typeof v !== "string" || v.length === 0 || v.includes(SEPARATOR)) {
|
|
95
|
+
throw new InvalidIdent(`${name} must be a non-empty string without '${SEPARATOR}'`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return { providerUid, provider };
|
|
58
99
|
}
|
|
59
|
-
|
|
60
|
-
|
|
100
|
+
/**
|
|
101
|
+
* Parse a v3 storage key `"<providerUid>_<provider>"`, split on its LAST "_" (provider names never
|
|
102
|
+
* contain "_", provider uids such as emails may)
|
|
103
|
+
*
|
|
104
|
+
* Consulted by repositories for keys that are not `"<providerUid>:<provider>"` (see `WEBDA_LEGACY_UID`),
|
|
105
|
+
* so v3 records stay addressable and queryable until they are upgraded.
|
|
106
|
+
* @param uid - raw storage key
|
|
107
|
+
* @returns the key parts, or undefined when the key is not a v3 ident key
|
|
108
|
+
*/
|
|
109
|
+
static parseLegacyUID(uid) {
|
|
110
|
+
if (typeof uid !== "string" || uid.includes(SEPARATOR)) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
const i = uid.lastIndexOf("_");
|
|
114
|
+
if (i <= 0 || i === uid.length - 1) {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
return { providerUid: uid.substring(0, i), provider: uid.substring(i + 1) };
|
|
61
118
|
}
|
|
62
119
|
/**
|
|
63
|
-
*
|
|
64
|
-
|
|
65
|
-
|
|
120
|
+
* v3 storage key of a record stored before the composite key (v3 kept it as `uuid` in the body)
|
|
121
|
+
*
|
|
122
|
+
* Such an ident has no `providerUid`: it must be upgraded (`@webda/auth` `upgradeIdent`) before use.
|
|
123
|
+
* @returns the v3 key, or undefined for a current ident
|
|
124
|
+
*/
|
|
125
|
+
getLegacyUID() {
|
|
126
|
+
const uuid = this.uuid;
|
|
127
|
+
if (this.providerUid || typeof uuid !== "string" || !Ident.parseLegacyUID(uuid)) {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
return uuid;
|
|
131
|
+
}
|
|
66
132
|
/**
|
|
67
|
-
*
|
|
133
|
+
* Normalise an email for use as providerUid
|
|
134
|
+
* @param email - raw email
|
|
135
|
+
* @returns trimmed lowercase email
|
|
68
136
|
*/
|
|
69
|
-
|
|
137
|
+
static normalizeEmail(email) {
|
|
138
|
+
return `${email ?? ""}`.trim().toLowerCase();
|
|
139
|
+
}
|
|
70
140
|
/**
|
|
71
|
-
*
|
|
72
|
-
* @returns the result string
|
|
141
|
+
* @returns the owner link
|
|
73
142
|
*/
|
|
74
|
-
|
|
75
|
-
return this.
|
|
143
|
+
getUser() {
|
|
144
|
+
return this._user;
|
|
76
145
|
}
|
|
77
146
|
/**
|
|
78
|
-
*
|
|
79
|
-
* @returns the result
|
|
147
|
+
* @param user - owner uuid or user
|
|
80
148
|
*/
|
|
81
|
-
|
|
82
|
-
|
|
149
|
+
setUser(user) {
|
|
150
|
+
const uuid = typeof user === "string" ? user : user.getUUID();
|
|
151
|
+
this._user ??= new ModelLink(User).set(uuid);
|
|
152
|
+
this._user.set(uuid);
|
|
83
153
|
}
|
|
84
154
|
/**
|
|
85
|
-
*
|
|
86
|
-
* @param type - the type to look up
|
|
155
|
+
* @returns the email of this ident
|
|
87
156
|
*/
|
|
88
|
-
|
|
89
|
-
this.
|
|
157
|
+
getEmail() {
|
|
158
|
+
return this.email;
|
|
90
159
|
}
|
|
91
160
|
/**
|
|
92
|
-
*
|
|
93
|
-
* @returns the result
|
|
161
|
+
* @returns true when verified
|
|
94
162
|
*/
|
|
95
|
-
|
|
96
|
-
return this.
|
|
163
|
+
isVerified() {
|
|
164
|
+
return this.verifiedAt !== undefined && this.verifiedAt !== null;
|
|
97
165
|
}
|
|
98
166
|
/**
|
|
99
|
-
*
|
|
100
|
-
* @param
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
167
|
+
* Only the owner may act on an ident
|
|
168
|
+
* @param ctx - operation context
|
|
169
|
+
* @param action - action name
|
|
170
|
+
* @returns true or a refusal reason
|
|
171
|
+
*/
|
|
172
|
+
async canAct(ctx, action) {
|
|
173
|
+
if (!ctx.getCurrentUserId() || this._user?.toString() !== ctx.getCurrentUserId()) {
|
|
174
|
+
return "You can't act on this ident";
|
|
175
|
+
}
|
|
176
|
+
return true;
|
|
104
177
|
}
|
|
105
178
|
/** Generated by @webda/content-mapper: include values held in WEBDA_STORAGE. */
|
|
106
179
|
toJSON() {
|
|
107
|
-
const
|
|
180
|
+
const parent = super.toJSON ? super.toJSON() : {};
|
|
181
|
+
const result = parent === this ? {} : parent;
|
|
108
182
|
for (const key of Object.keys(this)) {
|
|
109
183
|
result[key] = this[key];
|
|
110
184
|
}
|
|
111
185
|
Object.assign(result, this[WEBDA_STORAGE]);
|
|
112
186
|
return result;
|
|
113
187
|
}
|
|
188
|
+
__hydrateBehaviors(rawData) {
|
|
189
|
+
{
|
|
190
|
+
let v = this.tokens;
|
|
191
|
+
if (rawData !== undefined && rawData !== null && rawData["tokens"] !== undefined) {
|
|
192
|
+
v = rawData["tokens"];
|
|
193
|
+
}
|
|
194
|
+
if (!(v instanceof EncryptedField)) {
|
|
195
|
+
const inst = new EncryptedField();
|
|
196
|
+
if (v !== undefined && v !== null) {
|
|
197
|
+
Object.assign(inst, v);
|
|
198
|
+
}
|
|
199
|
+
v = inst;
|
|
200
|
+
}
|
|
201
|
+
v[WEBDA_STORAGE] = v[WEBDA_STORAGE] || {};
|
|
202
|
+
v[WEBDA_STORAGE]["__parent__"] = { instance: this, attribute: "tokens" };
|
|
203
|
+
this.tokens = v;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
114
206
|
}
|
|
115
207
|
//# sourceMappingURL=ident.model.js.map
|