@webda/auth 0.0.0-stage → 4.0.0-beta.10
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 +166 -0
- package/README.md +59 -2
- package/lib/authentication.service.d.ts +322 -0
- package/lib/authentication.service.d.ts.map +1 -0
- package/lib/authentication.service.js +978 -0
- package/lib/authentication.service.js.map +1 -0
- package/lib/certificate/certificate.service.d.ts +139 -0
- package/lib/certificate/certificate.service.d.ts.map +1 -0
- package/lib/certificate/certificate.service.js +343 -0
- package/lib/certificate/certificate.service.js.map +1 -0
- package/lib/compat/upgrade.d.ts +71 -0
- package/lib/compat/upgrade.d.ts.map +1 -0
- package/lib/compat/upgrade.js +200 -0
- package/lib/compat/upgrade.js.map +1 -0
- package/lib/email/emailpassword.service.d.ts +249 -0
- package/lib/email/emailpassword.service.d.ts.map +1 -0
- package/lib/email/emailpassword.service.js +714 -0
- package/lib/email/emailpassword.service.js.map +1 -0
- package/lib/email/tokens.d.ts +36 -0
- package/lib/email/tokens.d.ts.map +1 -0
- package/lib/email/tokens.js +46 -0
- package/lib/email/tokens.js.map +1 -0
- package/lib/errors.d.ts +53 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +74 -0
- package/lib/errors.js.map +1 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +12 -0
- package/lib/index.js.map +1 -0
- package/lib/mfa/secondfactor.service.d.ts +44 -0
- package/lib/mfa/secondfactor.service.d.ts.map +1 -0
- package/lib/mfa/secondfactor.service.js +38 -0
- package/lib/mfa/secondfactor.service.js.map +1 -0
- package/lib/mfa/totp.service.d.ts +41 -0
- package/lib/mfa/totp.service.d.ts.map +1 -0
- package/lib/mfa/totp.service.js +63 -0
- package/lib/mfa/totp.service.js.map +1 -0
- package/lib/oauth/oauth.service.d.ts +296 -0
- package/lib/oauth/oauth.service.d.ts.map +1 -0
- package/lib/oauth/oauth.service.js +560 -0
- package/lib/oauth/oauth.service.js.map +1 -0
- package/lib/provider.d.ts +53 -0
- package/lib/provider.d.ts.map +1 -0
- package/lib/provider.js +55 -0
- package/lib/provider.js.map +1 -0
- package/lib/test/authtest.d.ts +39 -0
- package/lib/test/authtest.d.ts.map +1 -0
- package/lib/test/authtest.js +62 -0
- package/lib/test/authtest.js.map +1 -0
- package/lib/test/emailtest.d.ts +25 -0
- package/lib/test/emailtest.d.ts.map +1 -0
- package/lib/test/emailtest.js +42 -0
- package/lib/test/emailtest.js.map +1 -0
- package/lib/test/fakeoauth.service.d.ts +45 -0
- package/lib/test/fakeoauth.service.d.ts.map +1 -0
- package/lib/test/fakeoauth.service.js +78 -0
- package/lib/test/fakeoauth.service.js.map +1 -0
- package/lib/test/mfauser.fixture.model.d.ts +11 -0
- package/lib/test/mfauser.fixture.model.d.ts.map +1 -0
- package/lib/test/mfauser.fixture.model.js +44 -0
- package/lib/test/mfauser.fixture.model.js.map +1 -0
- package/lib/test/stubprovider.d.ts +35 -0
- package/lib/test/stubprovider.d.ts.map +1 -0
- package/lib/test/stubprovider.js +46 -0
- package/lib/test/stubprovider.js.map +1 -0
- package/lib/test/v3.d.ts +29 -0
- package/lib/test/v3.d.ts.map +1 -0
- package/lib/test/v3.js +47 -0
- package/lib/test/v3.js.map +1 -0
- package/lib/throttle.d.ts +41 -0
- package/lib/throttle.d.ts.map +1 -0
- package/lib/throttle.js +49 -0
- package/lib/throttle.js.map +1 -0
- package/package.json +69 -3
- package/test/config.json +23 -0
- package/webda.module.json +891 -0
package/lib/provider.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useDynamicService } from "@webda/core";
|
|
2
|
+
import { EmailDomainNotAllowed } from "./errors.js";
|
|
3
|
+
/**
|
|
4
|
+
* @param email - an email address
|
|
5
|
+
* @returns the lowercased part after the last "@", undefined if none
|
|
6
|
+
*/
|
|
7
|
+
export function emailDomain(email) {
|
|
8
|
+
const idx = email.lastIndexOf("@");
|
|
9
|
+
return idx < 0
|
|
10
|
+
? undefined
|
|
11
|
+
: email
|
|
12
|
+
.substring(idx + 1)
|
|
13
|
+
.trim()
|
|
14
|
+
.toLowerCase();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Apply a provider email policy to a resolved identity without mutating it
|
|
18
|
+
* @param identity - identity asserted by the provider
|
|
19
|
+
* @param policy - the provider policy, if any
|
|
20
|
+
* @returns the identity to use (a copy with emailVerified forced to false when the claim is not trusted)
|
|
21
|
+
* @throws EmailDomainNotAllowed when the email is missing or its domain is not allowed
|
|
22
|
+
*/
|
|
23
|
+
export function applyEmailPolicy(identity, policy) {
|
|
24
|
+
if (!policy)
|
|
25
|
+
return identity;
|
|
26
|
+
const domain = identity.email ? emailDomain(identity.email) : undefined;
|
|
27
|
+
const norm = (list) => list.map(d => d.trim().toLowerCase());
|
|
28
|
+
const trust = policy.trustEmailVerification;
|
|
29
|
+
let out = identity;
|
|
30
|
+
if (identity.emailVerified && trust !== undefined && trust !== true) {
|
|
31
|
+
if (trust === false || !domain || !norm(trust).includes(domain)) {
|
|
32
|
+
out = { ...identity, emailVerified: false };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// The allow-list only admits a present, listed and (still) verified email
|
|
36
|
+
if (policy.allowedEmailDomains &&
|
|
37
|
+
(!domain || !out.emailVerified || !norm(policy.allowedEmailDomains).includes(domain))) {
|
|
38
|
+
throw new EmailDomainNotAllowed();
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* @param service - any service
|
|
44
|
+
* @returns true when it implements AuthProvider
|
|
45
|
+
*/
|
|
46
|
+
export function isAuthProvider(service) {
|
|
47
|
+
return !!service && typeof service.providerName === "string" && typeof service.getPublicInfo === "function";
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* @returns the Authentication service
|
|
51
|
+
*/
|
|
52
|
+
export function useAuthentication() {
|
|
53
|
+
return useDynamicService("Authentication");
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0D,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAExG,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAgCpD;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACnC,OAAO,GAAG,GAAG,CAAC;QACZ,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,KAAK;aACF,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC;aAClB,IAAI,EAAE;aACN,WAAW,EAAE,CAAC;AACvB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,QAA0B,EAC1B,MAAuC;IAEvC,IAAI,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IAC7B,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,MAAM,IAAI,GAAG,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IACvE,MAAM,KAAK,GAAG,MAAM,CAAC,sBAAsB,CAAC;IAC5C,IAAI,GAAG,GAAG,QAAQ,CAAC;IACnB,IAAI,QAAQ,CAAC,aAAa,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACpE,IAAI,KAAK,KAAK,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAChE,GAAG,GAAG,EAAE,GAAG,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,0EAA0E;IAC1E,IACE,MAAM,CAAC,mBAAmB;QAC1B,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EACrF,CAAC;QACD,MAAM,IAAI,qBAAqB,EAAE,CAAC;IACpC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,OAAY;IACzC,OAAO,CAAC,CAAC,OAAO,IAAI,OAAO,OAAO,CAAC,YAAY,KAAK,QAAQ,IAAI,OAAO,OAAO,CAAC,aAAa,KAAK,UAAU,CAAC;AAC9G,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,iBAAiB,CAAiB,gBAAgB,CAAC,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { WebContext } from "@webda/core";
|
|
2
|
+
import { WebdaApplicationTest } from "@webda/core/lib/test/application.js";
|
|
3
|
+
import { DebugMailer } from "@webda/core/lib/services/debugmailer.service.js";
|
|
4
|
+
/**
|
|
5
|
+
* Base class for @webda/auth specs
|
|
6
|
+
*/
|
|
7
|
+
export declare abstract class AuthTest extends WebdaApplicationTest {
|
|
8
|
+
mailer: DebugMailer;
|
|
9
|
+
/** @override */
|
|
10
|
+
beforeEach(): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* @param body - request body
|
|
13
|
+
* @returns a fresh web context with a session
|
|
14
|
+
*/
|
|
15
|
+
ctx(body?: any): Promise<WebContext>;
|
|
16
|
+
/**
|
|
17
|
+
* Run code inside a context
|
|
18
|
+
* @param ctx - context
|
|
19
|
+
* @param fn - code
|
|
20
|
+
* @returns fn result
|
|
21
|
+
*/
|
|
22
|
+
inContext<T>(ctx: WebContext, fn: () => Promise<T>): Promise<T>;
|
|
23
|
+
/**
|
|
24
|
+
* Call an operation by id and parse its JSON output.
|
|
25
|
+
*
|
|
26
|
+
* Input is passed as the request body: a fresh `WebContext` is created for every call (the
|
|
27
|
+
* input and the output are cached per context) and carries the session of `ctx`. The session
|
|
28
|
+
* is copied back to `ctx` afterwards so a login in one call is visible in the next one.
|
|
29
|
+
* Operations with an input schema receive the body fields as positional arguments, others
|
|
30
|
+
* receive the body object as their single argument.
|
|
31
|
+
* @param operationId - e.g. "Auth.Email.Login"
|
|
32
|
+
* @param input - operation input (request body)
|
|
33
|
+
* @param ctx - context to reuse (keeps the session between calls)
|
|
34
|
+
* @param headers - request headers, a JSON request by default
|
|
35
|
+
* @returns parsed output
|
|
36
|
+
*/
|
|
37
|
+
op<T = any>(operationId: string, input?: any, ctx?: WebContext, headers?: Record<string, string>): Promise<T | undefined>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=authtest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authtest.d.ts","sourceRoot":"","sources":["../../src/test/authtest.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8C,UAAU,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,iDAAiD,CAAC;AAE9E;;GAEG;AACH,8BAAsB,QAAS,SAAQ,oBAAoB;IACzD,MAAM,EAAE,WAAW,CAAC;IAEpB,gBAAgB;IACV,UAAU,kBAIf;IAED;;;OAGG;IACG,GAAG,CAAC,IAAI,GAAE,GAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAI7C;IAED;;;;;OAKG;IACH,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAE9D;IAED;;;;;;;;;;;;;OAaG;IACG,EAAE,CAAC,CAAC,GAAG,GAAG,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,GAAE,GAAQ,EACf,GAAG,CAAC,EAAE,UAAU,EAChB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAA0C,GACvE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAaxB;CACF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { callOperation, HttpContext, runWithContext } from "@webda/core";
|
|
2
|
+
import { WebdaApplicationTest } from "@webda/core/lib/test/application.js";
|
|
3
|
+
/**
|
|
4
|
+
* Base class for @webda/auth specs
|
|
5
|
+
*/
|
|
6
|
+
export class AuthTest extends WebdaApplicationTest {
|
|
7
|
+
/** @override */
|
|
8
|
+
async beforeEach() {
|
|
9
|
+
await super.beforeEach();
|
|
10
|
+
this.mailer = this.getService("DefinedMailer");
|
|
11
|
+
if (this.mailer)
|
|
12
|
+
this.mailer.sent = [];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* @param body - request body
|
|
16
|
+
* @returns a fresh web context with a session
|
|
17
|
+
*/
|
|
18
|
+
async ctx(body = {}) {
|
|
19
|
+
const ctx = await this.newContext(body);
|
|
20
|
+
ctx.newSession();
|
|
21
|
+
return ctx;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Run code inside a context
|
|
25
|
+
* @param ctx - context
|
|
26
|
+
* @param fn - code
|
|
27
|
+
* @returns fn result
|
|
28
|
+
*/
|
|
29
|
+
inContext(ctx, fn) {
|
|
30
|
+
return runWithContext(ctx, fn);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Call an operation by id and parse its JSON output.
|
|
34
|
+
*
|
|
35
|
+
* Input is passed as the request body: a fresh `WebContext` is created for every call (the
|
|
36
|
+
* input and the output are cached per context) and carries the session of `ctx`. The session
|
|
37
|
+
* is copied back to `ctx` afterwards so a login in one call is visible in the next one.
|
|
38
|
+
* Operations with an input schema receive the body fields as positional arguments, others
|
|
39
|
+
* receive the body object as their single argument.
|
|
40
|
+
* @param operationId - e.g. "Auth.Email.Login"
|
|
41
|
+
* @param input - operation input (request body)
|
|
42
|
+
* @param ctx - context to reuse (keeps the session between calls)
|
|
43
|
+
* @param headers - request headers, a JSON request by default
|
|
44
|
+
* @returns parsed output
|
|
45
|
+
*/
|
|
46
|
+
async op(operationId, input = {}, ctx, headers = { "content-type": "application/json" }) {
|
|
47
|
+
ctx ?? (ctx = await this.ctx());
|
|
48
|
+
const http = new HttpContext("test.webda.io", "POST", "/", "http", 80, headers);
|
|
49
|
+
http.setBody(input);
|
|
50
|
+
const call = await this.newWebContext(http);
|
|
51
|
+
call.setSession(ctx.getSession());
|
|
52
|
+
try {
|
|
53
|
+
await runWithContext(call, () => callOperation(call, operationId));
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
ctx.setSession(call.getSession());
|
|
57
|
+
}
|
|
58
|
+
const body = call.getResponseBody();
|
|
59
|
+
return body ? JSON.parse(body.toString()) : undefined;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=authtest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authtest.js","sourceRoot":"","sources":["../../src/test/authtest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAc,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAG3E;;GAEG;AACH,MAAM,OAAgB,QAAS,SAAQ,oBAAoB;IAGzD,gBAAgB;IAChB,KAAK,CAAC,UAAU;QACd,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,CAAM,eAAe,CAAgB,CAAC;QACnE,IAAI,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;IACzC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAG,CAAC,IAAI,GAAQ,EAAE;QACtB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,CAAa,IAAI,CAAC,CAAC;QACpD,GAAG,CAAC,UAAU,EAAE,CAAC;QACjB,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAI,GAAe,EAAE,EAAoB;QAChD,OAAO,cAAc,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACjC,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,EAAE,CACN,WAAmB,EACnB,KAAK,GAAQ,EAAE,EACf,GAAgB,EAChB,OAAO,GAA2B,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAExE,GAAG,KAAH,GAAG,GAAK,MAAM,IAAI,CAAC,GAAG,EAAE,EAAC;QACzB,MAAM,IAAI,GAAG,IAAI,WAAW,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;QAChF,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,aAAa,CAAa,IAAI,CAAC,CAAC;QACxD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;QACrE,CAAC;gBAAS,CAAC;YACT,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QACpC,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxD,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TestApplication } from "@webda/core/lib/test/objects.js";
|
|
2
|
+
import { AuthTest } from "./authtest.js";
|
|
3
|
+
import type { Authentication } from "../authentication.service.js";
|
|
4
|
+
import type { EmailPasswordProvider } from "../email/emailpassword.service.js";
|
|
5
|
+
/**
|
|
6
|
+
* Base class for email/password provider specs, using the full test/config.json
|
|
7
|
+
*/
|
|
8
|
+
export declare abstract class EmailTest extends AuthTest {
|
|
9
|
+
auth: Authentication;
|
|
10
|
+
email: EmailPasswordProvider;
|
|
11
|
+
/** @override */
|
|
12
|
+
tweakApp(app: TestApplication): Promise<void>;
|
|
13
|
+
/** @override */
|
|
14
|
+
beforeEach(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* @returns the url of the last sent email
|
|
17
|
+
*/
|
|
18
|
+
lastMailUrl(): string;
|
|
19
|
+
/**
|
|
20
|
+
* @param url - an emailed link
|
|
21
|
+
* @returns its token query parameter
|
|
22
|
+
*/
|
|
23
|
+
tokenOf(url: string): string;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=emailtest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emailtest.d.ts","sourceRoot":"","sources":["../../src/test/emailtest.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAE/E;;GAEG;AACH,8BAAsB,SAAU,SAAQ,QAAQ;IAC9C,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,qBAAqB,CAAC;IAE7B,gBAAgB;IACV,QAAQ,CAAC,GAAG,EAAE,eAAe,iBAIlC;IAED,gBAAgB;IACV,UAAU,kBASf;IAED;;OAEG;IACH,WAAW,IAAI,MAAM,CAEpB;IAED;;;OAGG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI3B;CACF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useService } from "@webda/core";
|
|
2
|
+
import { AuthTest } from "./authtest.js";
|
|
3
|
+
import { addStubProviders } from "./stubprovider.js";
|
|
4
|
+
/**
|
|
5
|
+
* Base class for email/password provider specs, using the full test/config.json
|
|
6
|
+
*/
|
|
7
|
+
export class EmailTest extends AuthTest {
|
|
8
|
+
/** @override */
|
|
9
|
+
async tweakApp(app) {
|
|
10
|
+
await super.tweakApp(app);
|
|
11
|
+
// test/config.json declares a "google" provider of this type
|
|
12
|
+
addStubProviders(app, "google");
|
|
13
|
+
}
|
|
14
|
+
/** @override */
|
|
15
|
+
async beforeEach() {
|
|
16
|
+
await super.beforeEach();
|
|
17
|
+
this.auth = useService("Authentication");
|
|
18
|
+
this.email = useService("emailAuth");
|
|
19
|
+
const params = this.email.getParameters();
|
|
20
|
+
params.verification = "after";
|
|
21
|
+
params.throttle = { resendDelay: 14400000, failedBeforeDelay: 3, lockout: 900000 };
|
|
22
|
+
params.password = { policy: ".{8,}" };
|
|
23
|
+
this.email.resolve();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* @returns the url of the last sent email
|
|
27
|
+
*/
|
|
28
|
+
lastMailUrl() {
|
|
29
|
+
return this.mailer.sent[this.mailer.sent.length - 1].replacements.url;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* @param url - an emailed link
|
|
33
|
+
* @returns its token query parameter
|
|
34
|
+
*/
|
|
35
|
+
tokenOf(url) {
|
|
36
|
+
const token = new URL(url, "http://localhost").searchParams.get("token");
|
|
37
|
+
if (!token)
|
|
38
|
+
throw new Error("Email link has no token");
|
|
39
|
+
return token;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=emailtest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emailtest.js","sourceRoot":"","sources":["../../src/test/emailtest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAIrD;;GAEG;AACH,MAAM,OAAgB,SAAU,SAAQ,QAAQ;IAI9C,gBAAgB;IAChB,KAAK,CAAC,QAAQ,CAAC,GAAoB;QACjC,MAAM,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC1B,6DAA6D;QAC7D,gBAAgB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED,gBAAgB;IAChB,KAAK,CAAC,UAAU;QACd,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC,gBAAuB,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,WAAkB,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;QAC1C,MAAM,CAAC,YAAY,GAAG,OAAO,CAAC;QAC9B,MAAM,CAAC,QAAQ,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QACnF,MAAM,CAAC,QAAQ,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QACtC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC;IACxE,CAAC;IAED;;;OAGG;IACH,OAAO,CAAC,GAAW;QACjB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACzE,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACvD,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ResolvedIdentity } from "@webda/core";
|
|
2
|
+
import { type OAuthAuthorizationRequest, type OAuthCallbackRequest, OAuthProvider, OAuthProviderParameters, type OAuthTokenRequest } from "../oauth/oauth.service.js";
|
|
3
|
+
/**
|
|
4
|
+
* OAuth provider used by the specs: no network, codes and tokens describe the identity
|
|
5
|
+
*
|
|
6
|
+
* A code (or token) is `<sub>,<email>,<verified 0|1>[,<provider override>]`; `bad` throws TokenInvalid, a value
|
|
7
|
+
* starting with `boom` a plain Error whose message contains the value. Every exchange is recorded in `calls`.
|
|
8
|
+
*/
|
|
9
|
+
export declare class FakeOAuthProvider extends OAuthProvider {
|
|
10
|
+
readonly providerName = "fake";
|
|
11
|
+
/**
|
|
12
|
+
* Registered with addModda (no module metadata): build the parameters like a compiled modda would
|
|
13
|
+
* @param params - raw parameters
|
|
14
|
+
* @returns the loaded parameters
|
|
15
|
+
*/
|
|
16
|
+
static createConfiguration(params: any): OAuthProviderParameters;
|
|
17
|
+
/** Recorded exchanges */
|
|
18
|
+
calls: {
|
|
19
|
+
method: string;
|
|
20
|
+
value: string;
|
|
21
|
+
request?: any;
|
|
22
|
+
}[];
|
|
23
|
+
/**
|
|
24
|
+
* @param request - authorization request
|
|
25
|
+
* @returns the fake authorization url
|
|
26
|
+
*/
|
|
27
|
+
getAuthorizationUrl(request: OAuthAuthorizationRequest): string;
|
|
28
|
+
/**
|
|
29
|
+
* @param value - code or token
|
|
30
|
+
* @param tokens - tokens to attach
|
|
31
|
+
* @returns the identity it describes
|
|
32
|
+
*/
|
|
33
|
+
protected identityOf(value: string, tokens?: any): ResolvedIdentity;
|
|
34
|
+
/**
|
|
35
|
+
* @param request - callback request
|
|
36
|
+
* @returns identity
|
|
37
|
+
*/
|
|
38
|
+
handleCallback(request: OAuthCallbackRequest): Promise<ResolvedIdentity>;
|
|
39
|
+
/**
|
|
40
|
+
* @param request - token request
|
|
41
|
+
* @returns identity
|
|
42
|
+
*/
|
|
43
|
+
handleToken(request: OAuthTokenRequest): Promise<ResolvedIdentity>;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=fakeoauth.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fakeoauth.service.d.ts","sourceRoot":"","sources":["../../src/test/fakeoauth.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,aAAa,EACb,uBAAuB,EACvB,KAAK,iBAAiB,EACvB,MAAM,2BAA2B,CAAC;AAEnC;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,aAAa;IAClD,QAAQ,CAAC,YAAY,UAAU;IAE/B;;;;OAIG;IACH,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,GAAG,GAAG,uBAAuB,CAE/D;IAED,yBAAyB;IACzB,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,GAAG,CAAA;KAAE,EAAE,CAAM;IAE/D;;;OAGG;IACH,mBAAmB,CAAC,OAAO,EAAE,yBAAyB,GAAG,MAAM,CAU9D;IAED;;;;OAIG;IACH,SAAS,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,gBAAgB,CAalE;IAED;;;OAGG;IACG,cAAc,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAG7E;IAED;;;OAGG;IACG,WAAW,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAIvE;CACF"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { TokenInvalid } from "../errors.js";
|
|
2
|
+
import { OAuthProvider, OAuthProviderParameters } from "../oauth/oauth.service.js";
|
|
3
|
+
/**
|
|
4
|
+
* OAuth provider used by the specs: no network, codes and tokens describe the identity
|
|
5
|
+
*
|
|
6
|
+
* A code (or token) is `<sub>,<email>,<verified 0|1>[,<provider override>]`; `bad` throws TokenInvalid, a value
|
|
7
|
+
* starting with `boom` a plain Error whose message contains the value. Every exchange is recorded in `calls`.
|
|
8
|
+
*/
|
|
9
|
+
export class FakeOAuthProvider extends OAuthProvider {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this.providerName = "fake";
|
|
13
|
+
/** Recorded exchanges */
|
|
14
|
+
this.calls = [];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Registered with addModda (no module metadata): build the parameters like a compiled modda would
|
|
18
|
+
* @param params - raw parameters
|
|
19
|
+
* @returns the loaded parameters
|
|
20
|
+
*/
|
|
21
|
+
static createConfiguration(params) {
|
|
22
|
+
return new OAuthProviderParameters().load(params);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* @param request - authorization request
|
|
26
|
+
* @returns the fake authorization url
|
|
27
|
+
*/
|
|
28
|
+
getAuthorizationUrl(request) {
|
|
29
|
+
const url = new URL("https://idp.example/authorize");
|
|
30
|
+
url.searchParams.set("state", request.state);
|
|
31
|
+
url.searchParams.set("redirect_uri", request.redirectUri);
|
|
32
|
+
url.searchParams.set("scope", request.scope.join(" "));
|
|
33
|
+
url.searchParams.set("client_id", this.parameters.client_id);
|
|
34
|
+
url.searchParams.set("code_challenge", request.codeChallenge);
|
|
35
|
+
url.searchParams.set("code_challenge_method", request.codeChallengeMethod);
|
|
36
|
+
url.searchParams.set("nonce", request.nonce);
|
|
37
|
+
return url.toString();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* @param value - code or token
|
|
41
|
+
* @param tokens - tokens to attach
|
|
42
|
+
* @returns the identity it describes
|
|
43
|
+
*/
|
|
44
|
+
identityOf(value, tokens) {
|
|
45
|
+
if (value === "bad")
|
|
46
|
+
throw new TokenInvalid();
|
|
47
|
+
if (value?.startsWith("boom"))
|
|
48
|
+
throw new Error(`secret internal failure: ${value}`);
|
|
49
|
+
const [sub, email, verified, provider] = value.split(",");
|
|
50
|
+
return {
|
|
51
|
+
provider: provider ?? this.providerName,
|
|
52
|
+
providerUid: sub,
|
|
53
|
+
email: email || undefined,
|
|
54
|
+
emailVerified: verified === "1",
|
|
55
|
+
profile: { name: `Fake ${sub}` },
|
|
56
|
+
tokens: tokens ?? { access_token: `at-${sub}` },
|
|
57
|
+
amr: ["oauth"]
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* @param request - callback request
|
|
62
|
+
* @returns identity
|
|
63
|
+
*/
|
|
64
|
+
async handleCallback(request) {
|
|
65
|
+
this.calls.push({ method: "callback", value: request.code, request });
|
|
66
|
+
return this.identityOf(request.code);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* @param request - token request
|
|
70
|
+
* @returns identity
|
|
71
|
+
*/
|
|
72
|
+
async handleToken(request) {
|
|
73
|
+
const value = request.token ?? request.tokens?.id_token;
|
|
74
|
+
this.calls.push({ method: "token", value, request });
|
|
75
|
+
return this.identityOf(value, request.tokens);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=fakeoauth.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fakeoauth.service.js","sourceRoot":"","sources":["../../src/test/fakeoauth.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { MFA } from "@webda/core/lib/models/mfa.model.js";
|
|
2
|
+
import { User } from "@webda/core/lib/models/user.model.js";
|
|
3
|
+
/** User with independent MFA attributes for integration tests.
|
|
4
|
+
* @WebdaIgnore
|
|
5
|
+
*/
|
|
6
|
+
export declare class MfaUser extends User {
|
|
7
|
+
loginMfa: MFA;
|
|
8
|
+
paymentMfa: MFA;
|
|
9
|
+
protected __hydrateBehaviors(rawData?: any): void;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=mfauser.fixture.model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mfauser.fixture.model.d.ts","sourceRoot":"","sources":["../../src/test/mfauser.fixture.model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,qCAAqC,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,sCAAsC,CAAC;AAE5D;;GAEG;AACH,qBAAa,OAAQ,SAAQ,IAAI;IAC/B,QAAQ,EAAE,GAAG,CAAC;IACd,UAAU,EAAE,GAAG,CAAC;IAChB,SAAS,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,GAAG,GAAG,IAAI,CAkChD;CACF"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { WEBDA_STORAGE } from "@webda/models";
|
|
2
|
+
import { MFA } from "@webda/core/lib/models/mfa.model.js";
|
|
3
|
+
import { User } from "@webda/core/lib/models/user.model.js";
|
|
4
|
+
/** User with independent MFA attributes for integration tests.
|
|
5
|
+
* @WebdaIgnore
|
|
6
|
+
*/
|
|
7
|
+
export class MfaUser extends User {
|
|
8
|
+
__hydrateBehaviors(rawData) {
|
|
9
|
+
User.prototype.__hydrateBehaviors?.call(this, rawData);
|
|
10
|
+
{
|
|
11
|
+
let v = this.loginMfa;
|
|
12
|
+
if (rawData !== undefined && rawData !== null && rawData["loginMfa"] !== undefined) {
|
|
13
|
+
v = rawData["loginMfa"];
|
|
14
|
+
}
|
|
15
|
+
if (!(v instanceof MFA)) {
|
|
16
|
+
const inst = new MFA();
|
|
17
|
+
if (v !== undefined && v !== null) {
|
|
18
|
+
Object.assign(inst, v);
|
|
19
|
+
}
|
|
20
|
+
v = inst;
|
|
21
|
+
}
|
|
22
|
+
v[WEBDA_STORAGE] = v[WEBDA_STORAGE] || {};
|
|
23
|
+
v[WEBDA_STORAGE]["__parent__"] = { instance: this, attribute: "loginMfa" };
|
|
24
|
+
this.loginMfa = v;
|
|
25
|
+
}
|
|
26
|
+
{
|
|
27
|
+
let v = this.paymentMfa;
|
|
28
|
+
if (rawData !== undefined && rawData !== null && rawData["paymentMfa"] !== undefined) {
|
|
29
|
+
v = rawData["paymentMfa"];
|
|
30
|
+
}
|
|
31
|
+
if (!(v instanceof MFA)) {
|
|
32
|
+
const inst = new MFA();
|
|
33
|
+
if (v !== undefined && v !== null) {
|
|
34
|
+
Object.assign(inst, v);
|
|
35
|
+
}
|
|
36
|
+
v = inst;
|
|
37
|
+
}
|
|
38
|
+
v[WEBDA_STORAGE] = v[WEBDA_STORAGE] || {};
|
|
39
|
+
v[WEBDA_STORAGE]["__parent__"] = { instance: this, attribute: "paymentMfa" };
|
|
40
|
+
this.paymentMfa = v;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=mfauser.fixture.model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mfauser.fixture.model.js","sourceRoot":"","sources":["../../src/test/mfauser.fixture.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,MAAM,qCAAqC,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,sCAAsC,CAAC;AAE5D;;GAEG;AACH,MAAM,OAAO,OAAQ,SAAQ,IAAI;IAGrB,kBAAkB,CAAC,OAAa;QACvC,IAAI,CAAC,SAAiB,CAAC,kBAAkB,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAChE,CAAC;YACC,IAAI,CAAC,GAAQ,IAAI,CAAC,QAAQ,CAAC;YAC3B,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,SAAS,EAAE,CAAC;gBACnF,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;YAC1B,CAAC;YACD,IAAI,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;gBACvB,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;oBAClC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;gBACzB,CAAC;gBACD,CAAC,GAAG,IAAI,CAAC;YACX,CAAC;YACA,CAAS,CAAC,aAAa,CAAC,GAAI,CAAS,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;YAC3D,CAAS,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;YACpF,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QACpB,CAAC;QACD,CAAC;YACC,IAAI,CAAC,GAAQ,IAAI,CAAC,UAAU,CAAC;YAC7B,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,CAAC,YAAY,CAAC,KAAK,SAAS,EAAE,CAAC;gBACrF,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;YAC5B,CAAC;YACD,IAAI,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;gBACvB,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;oBAClC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;gBACzB,CAAC;gBACD,CAAC,GAAG,IAAI,CAAC;YACX,CAAC;YACA,CAAS,CAAC,aAAa,CAAC,GAAI,CAAS,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;YAC3D,CAAS,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;YACtF,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Service } from "@webda/core";
|
|
2
|
+
import type { TestApplication } from "@webda/core/lib/test/objects.js";
|
|
3
|
+
/**
|
|
4
|
+
* Minimal AuthProvider service: specs call `complete()` on its behalf
|
|
5
|
+
*/
|
|
6
|
+
export declare class StubProvider extends Service {
|
|
7
|
+
readonly providerName: string;
|
|
8
|
+
/**
|
|
9
|
+
* @returns public info
|
|
10
|
+
*/
|
|
11
|
+
getPublicInfo(): {
|
|
12
|
+
name: string;
|
|
13
|
+
type: "oauth";
|
|
14
|
+
startUrl: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* @param name - provider name
|
|
19
|
+
* @returns a StubProvider class whose provider is `name`
|
|
20
|
+
*/
|
|
21
|
+
export declare function stubProvider(name: string): typeof StubProvider;
|
|
22
|
+
/**
|
|
23
|
+
* Register stub providers in a test application: add `<name>: { type: "WebdaTest/Stub_<name>" }` to the services
|
|
24
|
+
* @param app - test application
|
|
25
|
+
* @param names - provider names
|
|
26
|
+
*/
|
|
27
|
+
export declare function addStubProviders(app: TestApplication, ...names: string[]): void;
|
|
28
|
+
/**
|
|
29
|
+
* @param names - provider names
|
|
30
|
+
* @returns the services configuration of the stub providers
|
|
31
|
+
*/
|
|
32
|
+
export declare function stubProvidersConfig(...names: string[]): Record<string, {
|
|
33
|
+
type: string;
|
|
34
|
+
}>;
|
|
35
|
+
//# sourceMappingURL=stubprovider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stubprovider.d.ts","sourceRoot":"","sources":["../../src/test/stubprovider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAEvE;;GAEG;AACH,qBAAa,YAAa,SAAQ,OAAO;IACvC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAM;IAEnC;;OAEG;IACH,aAAa,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAEjE;CACF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,YAAY,CAI9D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAI/E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAExF"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Service } from "@webda/core";
|
|
2
|
+
/**
|
|
3
|
+
* Minimal AuthProvider service: specs call `complete()` on its behalf
|
|
4
|
+
*/
|
|
5
|
+
export class StubProvider extends Service {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(...arguments);
|
|
8
|
+
this.providerName = "";
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* @returns public info
|
|
12
|
+
*/
|
|
13
|
+
getPublicInfo() {
|
|
14
|
+
return { name: this.providerName, type: "oauth", startUrl: `/auth/${this.providerName}` };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* @param name - provider name
|
|
19
|
+
* @returns a StubProvider class whose provider is `name`
|
|
20
|
+
*/
|
|
21
|
+
export function stubProvider(name) {
|
|
22
|
+
return class extends StubProvider {
|
|
23
|
+
constructor() {
|
|
24
|
+
super(...arguments);
|
|
25
|
+
this.providerName = name;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Register stub providers in a test application: add `<name>: { type: "WebdaTest/Stub_<name>" }` to the services
|
|
31
|
+
* @param app - test application
|
|
32
|
+
* @param names - provider names
|
|
33
|
+
*/
|
|
34
|
+
export function addStubProviders(app, ...names) {
|
|
35
|
+
for (const name of names) {
|
|
36
|
+
app.addModda(`WebdaTest/Stub_${name}`, stubProvider(name));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* @param names - provider names
|
|
41
|
+
* @returns the services configuration of the stub providers
|
|
42
|
+
*/
|
|
43
|
+
export function stubProvidersConfig(...names) {
|
|
44
|
+
return Object.fromEntries(names.map(name => [`${name}Stub`, { type: `WebdaTest/Stub_${name}` }]));
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=stubprovider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stubprovider.js","sourceRoot":"","sources":["../../src/test/stubprovider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,OAAO;IAAzC;;QACW,iBAAY,GAAW,EAAE,CAAC;IAQrC,CAAC;IANC;;OAEG;IACH,aAAa;QACX,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;IAC5F,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,KAAM,SAAQ,YAAY;QAA1B;;YACI,iBAAY,GAAG,IAAI,CAAC;QAC/B,CAAC;KAAA,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAoB,EAAE,GAAG,KAAe;IACvE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,GAAG,CAAC,QAAQ,CAAC,kBAAkB,IAAI,EAAE,EAAE,YAAY,CAAC,IAAI,CAAQ,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAG,KAAe;IACpD,OAAO,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,MAAM,EAAE,EAAE,IAAI,EAAE,kBAAkB,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AACpG,CAAC"}
|
package/lib/test/v3.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Writes a raw row into a store's backing storage */
|
|
2
|
+
export type RawWriter = (key: string, row: any) => void;
|
|
3
|
+
/**
|
|
4
|
+
* Seed a v3 email user and its ident RAW (Ruling R1): the v3 layout is written straight into the storage,
|
|
5
|
+
* bypassing model constructors and serializers
|
|
6
|
+
* @param write - raw storage writer (MemoryStore storage map, FileStore folder, ...)
|
|
7
|
+
* @param email - email (normalised)
|
|
8
|
+
* @param opts - options
|
|
9
|
+
* @param opts.validated - whether the v3 ident was validated
|
|
10
|
+
* @param opts.password - clear password hashed into `__password`
|
|
11
|
+
* @param opts.userId - user uuid
|
|
12
|
+
* @returns the user uuid
|
|
13
|
+
*/
|
|
14
|
+
export declare function seedV3(write: RawWriter, email: string, opts: {
|
|
15
|
+
validated: boolean;
|
|
16
|
+
password: string;
|
|
17
|
+
userId?: string;
|
|
18
|
+
}): Promise<string>;
|
|
19
|
+
/**
|
|
20
|
+
* Seed a raw v3 ident `"<uid>_<provider>"`
|
|
21
|
+
* @param write - raw storage writer
|
|
22
|
+
* @param uid - provider uid
|
|
23
|
+
* @param provider - provider
|
|
24
|
+
* @param userId - owner uuid
|
|
25
|
+
* @param extra - extra v3 fields
|
|
26
|
+
* @returns the v3 key
|
|
27
|
+
*/
|
|
28
|
+
export declare function seedV3Ident(write: RawWriter, uid: string, provider: string, userId: string, extra?: any): string;
|
|
29
|
+
//# sourceMappingURL=v3.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v3.d.ts","sourceRoot":"","sources":["../../src/test/v3.ts"],"names":[],"mappings":"AAEA,sDAAsD;AACtD,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;AAExD;;;;;;;;;;GAUG;AACH,wBAAsB,MAAM,CAC1B,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9D,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,GAAQ,GAAG,MAAM,CAIpH"}
|
package/lib/test/v3.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Password } from "@webda/core";
|
|
2
|
+
/**
|
|
3
|
+
* Seed a v3 email user and its ident RAW (Ruling R1): the v3 layout is written straight into the storage,
|
|
4
|
+
* bypassing model constructors and serializers
|
|
5
|
+
* @param write - raw storage writer (MemoryStore storage map, FileStore folder, ...)
|
|
6
|
+
* @param email - email (normalised)
|
|
7
|
+
* @param opts - options
|
|
8
|
+
* @param opts.validated - whether the v3 ident was validated
|
|
9
|
+
* @param opts.password - clear password hashed into `__password`
|
|
10
|
+
* @param opts.userId - user uuid
|
|
11
|
+
* @returns the user uuid
|
|
12
|
+
*/
|
|
13
|
+
export async function seedV3(write, email, opts) {
|
|
14
|
+
const hash = new Password();
|
|
15
|
+
await hash.set(opts.password);
|
|
16
|
+
const userId = opts.userId ?? `v3-${email}`;
|
|
17
|
+
write(userId, {
|
|
18
|
+
uuid: userId,
|
|
19
|
+
__type: "Webda/User",
|
|
20
|
+
email,
|
|
21
|
+
displayName: email,
|
|
22
|
+
__password: hash.__hash,
|
|
23
|
+
_lastPasswordRecovery: 0
|
|
24
|
+
});
|
|
25
|
+
seedV3Ident(write, email, "email", userId, {
|
|
26
|
+
email,
|
|
27
|
+
_failedLogin: 1,
|
|
28
|
+
_lastValidationEmail: 42,
|
|
29
|
+
...(opts.validated ? { _validation: "2020-01-01T00:00:00.000Z" } : {})
|
|
30
|
+
});
|
|
31
|
+
return userId;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Seed a raw v3 ident `"<uid>_<provider>"`
|
|
35
|
+
* @param write - raw storage writer
|
|
36
|
+
* @param uid - provider uid
|
|
37
|
+
* @param provider - provider
|
|
38
|
+
* @param userId - owner uuid
|
|
39
|
+
* @param extra - extra v3 fields
|
|
40
|
+
* @returns the v3 key
|
|
41
|
+
*/
|
|
42
|
+
export function seedV3Ident(write, uid, provider, userId, extra = {}) {
|
|
43
|
+
const key = `${uid}_${provider}`;
|
|
44
|
+
write(key, { uuid: key, __type: "Webda/Ident", _type: provider, _user: userId, ...extra });
|
|
45
|
+
return key;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=v3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v3.js","sourceRoot":"","sources":["../../src/test/v3.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAKvC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,KAAgB,EAChB,KAAa,EACb,IAA+D;IAE/D,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC5B,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,KAAK,EAAE,CAAC;IAC5C,KAAK,CAAC,MAAM,EAAE;QACZ,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,YAAY;QACpB,KAAK;QACL,WAAW,EAAE,KAAK;QAClB,UAAU,EAAE,IAAI,CAAC,MAAM;QACvB,qBAAqB,EAAE,CAAC;KACzB,CAAC,CAAC;IACH,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE;QACzC,KAAK;QACL,YAAY,EAAE,CAAC;QACf,oBAAoB,EAAE,EAAE;QACxB,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,0BAA0B,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvE,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,KAAgB,EAAE,GAAW,EAAE,QAAgB,EAAE,MAAc,EAAE,KAAK,GAAQ,EAAE;IAC1G,MAAM,GAAG,GAAG,GAAG,GAAG,IAAI,QAAQ,EAAE,CAAC;IACjC,KAAK,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IAC3F,OAAO,GAAG,CAAC;AACb,CAAC"}
|