@vsaas/loopback 12.1.1 → 12.2.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/README.md +6 -0
- package/common/models/rate-limit-state.json +121 -0
- package/common/models/two-factor-challenge.json +112 -0
- package/common/models/two-factor-credential.json +117 -0
- package/common/models/two-factor-recovery-code.json +63 -0
- package/common/models/user.json +30 -0
- package/dist/_virtual/_rolldown/runtime.cjs +9 -2
- package/dist/common/models/access-token.d.cts +3 -0
- package/dist/common/models/acl.cjs +1 -3
- package/dist/common/models/acl.d.cts +1 -0
- package/dist/common/models/application.d.cts +3 -0
- package/dist/common/models/change.cjs +21 -18
- package/dist/common/models/change.d.cts +1 -0
- package/dist/common/models/checkpoint.d.cts +3 -0
- package/dist/common/models/email.d.cts +3 -0
- package/dist/common/models/key-value-model.d.cts +3 -0
- package/dist/common/models/rate-limit-state.cjs +7 -0
- package/dist/common/models/rate-limit-state.d.cts +3 -0
- package/dist/common/models/rate-limit-state2.cjs +109 -0
- package/dist/common/models/role-mapping.d.cts +3 -0
- package/dist/common/models/role.cjs +12 -8
- package/dist/common/models/role.d.cts +1 -0
- package/dist/common/models/scope.d.cts +3 -0
- package/dist/common/models/two-factor-challenge.cjs +7 -0
- package/dist/common/models/two-factor-challenge.d.cts +3 -0
- package/dist/common/models/two-factor-challenge2.cjs +108 -0
- package/dist/common/models/two-factor-credential.cjs +7 -0
- package/dist/common/models/two-factor-credential.d.cts +3 -0
- package/dist/common/models/two-factor-credential2.cjs +103 -0
- package/dist/common/models/two-factor-recovery-code.cjs +7 -0
- package/dist/common/models/two-factor-recovery-code.d.cts +3 -0
- package/dist/common/models/two-factor-recovery-code2.cjs +57 -0
- package/dist/common/models/user.cjs +258 -21
- package/dist/common/models/user.d.cts +3 -0
- package/dist/common/models/user2.cjs +30 -0
- package/dist/index.cjs +2 -0
- package/dist/index.d.cts +3 -0
- package/dist/lib/access-context.d.cts +33 -0
- package/dist/lib/application.d.cts +1 -0
- package/dist/lib/authentication-security-initializer.cjs +351 -0
- package/dist/lib/authentication-security-initializer.d.cts +4 -0
- package/dist/lib/builtin-models.cjs +12 -0
- package/dist/lib/builtin-models.d.cts +3 -0
- package/dist/lib/configure-shared-methods.cjs +7 -4
- package/dist/lib/configure-shared-methods.d.cts +3 -0
- package/dist/lib/connectors/base-connector.d.cts +6 -0
- package/dist/lib/connectors/mail-direct-transport.cjs +26 -23
- package/dist/lib/connectors/mail-direct-transport.d.cts +22 -0
- package/dist/lib/connectors/mail-stub-transport.d.cts +14 -0
- package/dist/lib/connectors/mail.d.cts +7 -0
- package/dist/lib/connectors/memory.d.cts +6 -0
- package/dist/lib/current-context.d.cts +3 -0
- package/dist/lib/globalize.d.cts +10 -0
- package/dist/lib/loopback.cjs +6 -0
- package/dist/lib/loopback.d.cts +1 -0
- package/dist/lib/model.d.cts +1 -0
- package/dist/lib/persisted-model.cjs +7 -12
- package/dist/lib/persisted-model.d.cts +1 -0
- package/dist/lib/rate-limit/algorithms/common.cjs +37 -0
- package/dist/lib/rate-limit/algorithms/failure-lockout.cjs +70 -0
- package/dist/lib/rate-limit/algorithms/fixed-window.cjs +61 -0
- package/dist/lib/rate-limit/algorithms/index.cjs +55 -0
- package/dist/lib/rate-limit/config.cjs +107 -0
- package/dist/lib/rate-limit/errors.cjs +58 -0
- package/dist/lib/rate-limit/index.cjs +15 -0
- package/dist/lib/rate-limit/index.d.cts +1 -0
- package/dist/lib/rate-limit/initializer.cjs +92 -0
- package/dist/lib/rate-limit/initializer.d.cts +4 -0
- package/dist/lib/rate-limit/limiter.cjs +368 -0
- package/dist/lib/rate-limit/registry.cjs +92 -0
- package/dist/lib/rate-limit/remote.cjs +180 -0
- package/dist/lib/rate-limit/remote.d.cts +6 -0
- package/dist/lib/rate-limit/stores/persisted-model.cjs +353 -0
- package/dist/lib/rate-limit/subject.cjs +127 -0
- package/dist/lib/rate-limit/types.cjs +1 -0
- package/dist/lib/rate-limit/types.d.cts +167 -0
- package/dist/lib/registry.d.cts +1 -0
- package/dist/lib/runtime.d.cts +10 -0
- package/dist/lib/server-app.d.cts +3 -0
- package/dist/lib/two-factor/config.cjs +199 -0
- package/dist/lib/two-factor/config.d.cts +55 -0
- package/dist/lib/two-factor/crypto.cjs +68 -0
- package/dist/lib/two-factor/crypto.d.cts +16 -0
- package/dist/lib/two-factor/errors.cjs +58 -0
- package/dist/lib/two-factor/errors.d.cts +18 -0
- package/dist/lib/two-factor/rate-limit.cjs +153 -0
- package/dist/lib/two-factor/rate-limit.d.cts +22 -0
- package/dist/lib/two-factor/recovery-codes.cjs +49 -0
- package/dist/lib/two-factor/recovery-codes.d.cts +16 -0
- package/dist/lib/two-factor/service.cjs +1108 -0
- package/dist/lib/two-factor/service.d.cts +78 -0
- package/dist/lib/two-factor/totp.cjs +50 -0
- package/dist/lib/two-factor/totp.d.cts +14 -0
- package/dist/lib/utils.d.cts +36 -0
- package/dist/package.cjs +46 -10
- package/dist/server/middleware/context.d.cts +3 -0
- package/dist/server/middleware/error-handler.d.cts +3 -0
- package/dist/server/middleware/favicon.d.cts +7 -0
- package/dist/server/middleware/rest.d.cts +6 -0
- package/dist/server/middleware/static.d.cts +3 -0
- package/dist/server/middleware/status.d.cts +19 -0
- package/dist/server/middleware/token.d.cts +3 -0
- package/dist/server/middleware/url-not-found.d.cts +13 -0
- package/docs/api-explorer-details.md +110 -0
- package/docs/application-guide.md +1110 -0
- package/docs/assets/explorer-api.png +0 -0
- package/docs/assets/explorer-endpoint.png +0 -0
- package/docs/assets/explorer-listing.png +0 -0
- package/docs/assets/explorer-req-res.png +0 -0
- package/docs/assets/lb-modules.png +0 -0
- package/docs/assets/loopback-architecture.png +0 -0
- package/docs/assets/loopback-concepts.png +0 -0
- package/docs/assets/loopback_ov.png +0 -0
- package/docs/rate-limiting.md +879 -0
- package/docs/two-factor-authentication.md +611 -0
- package/docs/two-factor-authenticator-loss-runbook.md +117 -0
- package/package.json +56 -20
|
@@ -143,16 +143,17 @@ var require_user = /* @__PURE__ */ require_runtime$1.__commonJSMin(((exports, mo
|
|
|
143
143
|
if (err) {
|
|
144
144
|
debug("An error is reported from User.hasPassword: %j", err);
|
|
145
145
|
fn(defaultError);
|
|
146
|
-
} else if (isMatch)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
146
|
+
} else if (isMatch) {
|
|
147
|
+
if (self.settings.emailVerificationRequired && !user.emailVerified) {
|
|
148
|
+
debug("User email has not been verified");
|
|
149
|
+
err = new Error(g.f("login failed as the email has not been verified"));
|
|
150
|
+
err.statusCode = 401;
|
|
151
|
+
err.code = "LOGIN_FAILED_EMAIL_NOT_VERIFIED";
|
|
152
|
+
err.details = { userId: user.id };
|
|
153
|
+
fn(err);
|
|
154
|
+
} else if (user.createAccessToken.length === 2) user.createAccessToken(credentials.ttl, tokenHandler);
|
|
155
|
+
else user.createAccessToken(credentials.ttl, credentials, tokenHandler);
|
|
156
|
+
} else {
|
|
156
157
|
debug("The password is invalid for user %s", query.email || query.username);
|
|
157
158
|
fn(defaultError);
|
|
158
159
|
}
|
|
@@ -164,6 +165,102 @@ var require_user = /* @__PURE__ */ require_runtime$1.__commonJSMin(((exports, mo
|
|
|
164
165
|
});
|
|
165
166
|
return fn.promise;
|
|
166
167
|
};
|
|
168
|
+
User._legacyLogin = User.login;
|
|
169
|
+
User.login = function(credentials, include, options, fn) {
|
|
170
|
+
if (typeof include === "function") {
|
|
171
|
+
fn = include;
|
|
172
|
+
include = void 0;
|
|
173
|
+
options = void 0;
|
|
174
|
+
} else if (typeof options === "function") {
|
|
175
|
+
fn = options;
|
|
176
|
+
options = void 0;
|
|
177
|
+
}
|
|
178
|
+
if (!(this.settings.twoFactor != null || this.settings.authenticationRateLimit?.enabled === true)) return this._legacyLogin(credentials, include, fn);
|
|
179
|
+
if (!this._authenticationSecurityReady || !this._authenticationSecurity) {
|
|
180
|
+
fn = fn || utils.createPromiseCallback();
|
|
181
|
+
const error = /* @__PURE__ */ new Error("Authentication security is not ready");
|
|
182
|
+
error.statusCode = 503;
|
|
183
|
+
error.code = "AUTHENTICATION_SECURITY_UNAVAILABLE";
|
|
184
|
+
process.nextTick(fn, error);
|
|
185
|
+
return fn.promise;
|
|
186
|
+
}
|
|
187
|
+
return this._authenticationSecurity.login(credentials, include, options || {}, fn);
|
|
188
|
+
};
|
|
189
|
+
User.getTwoFactorPrincipalBindingMaterial = function(user, options, fn) {
|
|
190
|
+
if (typeof options === "function") {
|
|
191
|
+
fn = options;
|
|
192
|
+
options = void 0;
|
|
193
|
+
}
|
|
194
|
+
fn = fn || utils.createPromiseCallback();
|
|
195
|
+
process.nextTick(function() {
|
|
196
|
+
if (!user || typeof user.password !== "string" || !user.password) {
|
|
197
|
+
const error = /* @__PURE__ */ new Error("Two-factor principal binding is unavailable");
|
|
198
|
+
error.code = "AUTHENTICATION_SECURITY_UNAVAILABLE";
|
|
199
|
+
error.statusCode = 503;
|
|
200
|
+
return fn(error);
|
|
201
|
+
}
|
|
202
|
+
fn(null, user.password);
|
|
203
|
+
});
|
|
204
|
+
return fn.promise;
|
|
205
|
+
};
|
|
206
|
+
User.validateTwoFactorLoginPrincipal = function(user, options, fn) {
|
|
207
|
+
if (typeof options === "function") fn = options;
|
|
208
|
+
fn = fn || utils.createPromiseCallback();
|
|
209
|
+
process.nextTick(fn, null, true);
|
|
210
|
+
return fn.promise;
|
|
211
|
+
};
|
|
212
|
+
User.buildTwoFactorLoginContext = function(credentials, options, fn) {
|
|
213
|
+
if (typeof options === "function") fn = options;
|
|
214
|
+
fn = fn || utils.createPromiseCallback();
|
|
215
|
+
process.nextTick(fn, null, { ttl: credentials && credentials.ttl });
|
|
216
|
+
return fn.promise;
|
|
217
|
+
};
|
|
218
|
+
User.resolveAuthenticationRateLimitSource = function(options, fn) {
|
|
219
|
+
fn = fn || utils.createPromiseCallback();
|
|
220
|
+
process.nextTick(fn, null, options && (options.authenticationSource || options.req?.ip || options.req?.socket?.remoteAddress || null));
|
|
221
|
+
return fn.promise;
|
|
222
|
+
};
|
|
223
|
+
User.verifyTwoFactor = function(verification, options, fn) {
|
|
224
|
+
if (typeof options === "function") {
|
|
225
|
+
fn = options;
|
|
226
|
+
options = void 0;
|
|
227
|
+
}
|
|
228
|
+
if (!this._authenticationSecurityReady || !this._authenticationSecurity) {
|
|
229
|
+
fn = fn || utils.createPromiseCallback();
|
|
230
|
+
const error = /* @__PURE__ */ new Error("Two-factor authentication is not configured");
|
|
231
|
+
error.statusCode = this.settings.twoFactor == null ? 404 : 503;
|
|
232
|
+
error.code = this.settings.twoFactor == null ? "TWO_FACTOR_NOT_CONFIGURED" : "AUTHENTICATION_SECURITY_UNAVAILABLE";
|
|
233
|
+
process.nextTick(fn, error);
|
|
234
|
+
return fn.promise;
|
|
235
|
+
}
|
|
236
|
+
return this._authenticationSecurity.verifyTwoFactor(verification, options || {}, fn);
|
|
237
|
+
};
|
|
238
|
+
for (const method of [
|
|
239
|
+
"beginTwoFactorEnrollment",
|
|
240
|
+
"confirmTwoFactorEnrollment",
|
|
241
|
+
"regenerateTwoFactorRecoveryCodes",
|
|
242
|
+
"disableTwoFactor"
|
|
243
|
+
]) User[method] = function(userId, request, options, fn) {
|
|
244
|
+
if (typeof options === "function") {
|
|
245
|
+
fn = options;
|
|
246
|
+
options = void 0;
|
|
247
|
+
}
|
|
248
|
+
if (!this._authenticationSecurityReady || !this._authenticationSecurity) {
|
|
249
|
+
fn = fn || utils.createPromiseCallback();
|
|
250
|
+
const error = /* @__PURE__ */ new Error("Two-factor authentication is not configured");
|
|
251
|
+
error.statusCode = this.settings.twoFactor == null ? 404 : 503;
|
|
252
|
+
error.code = this.settings.twoFactor == null ? "TWO_FACTOR_NOT_CONFIGURED" : "AUTHENTICATION_SECURITY_UNAVAILABLE";
|
|
253
|
+
process.nextTick(fn, error);
|
|
254
|
+
return fn.promise;
|
|
255
|
+
}
|
|
256
|
+
const serviceMethod = {
|
|
257
|
+
beginTwoFactorEnrollment: "beginEnrollment",
|
|
258
|
+
confirmTwoFactorEnrollment: "confirmEnrollment",
|
|
259
|
+
regenerateTwoFactorRecoveryCodes: "regenerateRecoveryCodes",
|
|
260
|
+
disableTwoFactor: "disable"
|
|
261
|
+
}[method];
|
|
262
|
+
return this._authenticationSecurity[serviceMethod](userId, request, options || {}, fn);
|
|
263
|
+
};
|
|
167
264
|
User.logout = function(tokenId, fn) {
|
|
168
265
|
fn = fn || utils.createPromiseCallback();
|
|
169
266
|
let err;
|
|
@@ -184,8 +281,12 @@ var require_user = /* @__PURE__ */ require_runtime$1.__commonJSMin(((exports, mo
|
|
|
184
281
|
return fn.promise;
|
|
185
282
|
};
|
|
186
283
|
User.observe("before delete", function(ctx, next) {
|
|
187
|
-
if (
|
|
188
|
-
|
|
284
|
+
if ((ctx.Model.settings.twoFactor != null || ctx.Model.settings.authenticationRateLimit?.enabled === true) && !ctx.Model._authenticationSecurity) {
|
|
285
|
+
const error = /* @__PURE__ */ new Error("Authentication security is not ready");
|
|
286
|
+
error.statusCode = 503;
|
|
287
|
+
error.code = "AUTHENTICATION_SECURITY_UNAVAILABLE";
|
|
288
|
+
return next(error);
|
|
289
|
+
}
|
|
189
290
|
const pkName = ctx.Model.definition.idName() || "id";
|
|
190
291
|
ctx.Model.find({
|
|
191
292
|
where: ctx.where,
|
|
@@ -196,7 +297,11 @@ var require_user = /* @__PURE__ */ require_runtime$1.__commonJSMin(((exports, mo
|
|
|
196
297
|
for (let i = 0; i < list.length; i++) ids[i] = list[i][pkName];
|
|
197
298
|
ctx.where = {};
|
|
198
299
|
ctx.where[pkName] = { inq: ids };
|
|
199
|
-
|
|
300
|
+
const cleanup = [];
|
|
301
|
+
const AccessToken = ctx.Model.relations.accessTokens?.modelTo;
|
|
302
|
+
if (AccessToken) cleanup.push(AccessToken.destroyAll({ userId: { inq: ids } }));
|
|
303
|
+
if (ctx.Model._authenticationSecurity) cleanup.push(ctx.Model._authenticationSecurity.deletePrincipals(ids));
|
|
304
|
+
Promise.all(cleanup).then(() => next(), next);
|
|
200
305
|
});
|
|
201
306
|
});
|
|
202
307
|
User.prototype.hasPassword = function(plain, fn) {
|
|
@@ -532,24 +637,118 @@ var require_user = /* @__PURE__ */ require_runtime$1.__commonJSMin(((exports, mo
|
|
|
532
637
|
});
|
|
533
638
|
UserModel.remoteMethod("login", {
|
|
534
639
|
description: "Login a user with username/email and password.",
|
|
640
|
+
accepts: [
|
|
641
|
+
{
|
|
642
|
+
arg: "credentials",
|
|
643
|
+
type: "object",
|
|
644
|
+
required: true,
|
|
645
|
+
http: { source: "body" }
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
arg: "include",
|
|
649
|
+
type: ["string"],
|
|
650
|
+
http: { source: "query" },
|
|
651
|
+
description: "Related objects to include in the response. See the description of return value for more details."
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
arg: "options",
|
|
655
|
+
type: "object",
|
|
656
|
+
http: buildAuthenticationOptions
|
|
657
|
+
}
|
|
658
|
+
],
|
|
659
|
+
returns: {
|
|
660
|
+
arg: "accessToken",
|
|
661
|
+
type: "object",
|
|
662
|
+
root: true,
|
|
663
|
+
description: g.f("The response body contains properties of the {{AccessToken}} created on login.\nDepending on the value of `include` parameter, the body may contain additional properties:\n\n - `user` - `U+007BUserU+007D` - Data of the currently logged in user. {{(`include=user`)}}\n\n")
|
|
664
|
+
},
|
|
665
|
+
http: { verb: "post" }
|
|
666
|
+
});
|
|
667
|
+
UserModel.getTwoFactorAuthenticationOptions = buildAuthenticationOptions;
|
|
668
|
+
UserModel.remoteMethod("verifyTwoFactor", {
|
|
669
|
+
description: "Complete login by verifying a second factor.",
|
|
535
670
|
accepts: [{
|
|
536
|
-
arg: "
|
|
671
|
+
arg: "verification",
|
|
537
672
|
type: "object",
|
|
538
673
|
required: true,
|
|
539
674
|
http: { source: "body" }
|
|
540
675
|
}, {
|
|
541
|
-
arg: "
|
|
542
|
-
type:
|
|
543
|
-
http:
|
|
544
|
-
description: "Related objects to include in the response. See the description of return value for more details."
|
|
676
|
+
arg: "options",
|
|
677
|
+
type: "object",
|
|
678
|
+
http: buildAuthenticationOptions
|
|
545
679
|
}],
|
|
546
680
|
returns: {
|
|
547
681
|
arg: "accessToken",
|
|
548
682
|
type: "object",
|
|
549
|
-
root: true
|
|
550
|
-
description: g.f("The response body contains properties of the {{AccessToken}} created on login.\nDepending on the value of `include` parameter, the body may contain additional properties:\n\n - `user` - `U+007BUserU+007D` - Data of the currently logged in user. {{(`include=user`)}}\n\n")
|
|
683
|
+
root: true
|
|
551
684
|
},
|
|
552
|
-
http: {
|
|
685
|
+
http: {
|
|
686
|
+
verb: "post",
|
|
687
|
+
path: "/two-factor/verify"
|
|
688
|
+
}
|
|
689
|
+
});
|
|
690
|
+
function registerTwoFactorManagementMethod(name, path, description) {
|
|
691
|
+
UserModel.remoteMethod(name, {
|
|
692
|
+
description,
|
|
693
|
+
accepts: [
|
|
694
|
+
{
|
|
695
|
+
arg: "userId",
|
|
696
|
+
type: "any",
|
|
697
|
+
http: getUserIdFromRequestContext
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
arg: "request",
|
|
701
|
+
type: "object",
|
|
702
|
+
required: true,
|
|
703
|
+
http: { source: "body" }
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
arg: "options",
|
|
707
|
+
type: "object",
|
|
708
|
+
http: buildAuthenticationOptions
|
|
709
|
+
}
|
|
710
|
+
],
|
|
711
|
+
returns: {
|
|
712
|
+
arg: "result",
|
|
713
|
+
type: "object",
|
|
714
|
+
root: true
|
|
715
|
+
},
|
|
716
|
+
http: {
|
|
717
|
+
verb: "post",
|
|
718
|
+
path
|
|
719
|
+
}
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
registerTwoFactorManagementMethod("beginTwoFactorEnrollment", "/two-factor/setup", "Begin two-factor enrollment.");
|
|
723
|
+
registerTwoFactorManagementMethod("confirmTwoFactorEnrollment", "/two-factor/confirm", "Confirm two-factor enrollment.");
|
|
724
|
+
registerTwoFactorManagementMethod("regenerateTwoFactorRecoveryCodes", "/two-factor/recovery-codes", "Regenerate two-factor recovery codes.");
|
|
725
|
+
registerTwoFactorManagementMethod("disableTwoFactor", "/two-factor/disable", "Disable two-factor authentication.");
|
|
726
|
+
for (const method of [
|
|
727
|
+
"login",
|
|
728
|
+
"verifyTwoFactor",
|
|
729
|
+
"beginTwoFactorEnrollment",
|
|
730
|
+
"confirmTwoFactorEnrollment",
|
|
731
|
+
"regenerateTwoFactorRecoveryCodes",
|
|
732
|
+
"disableTwoFactor"
|
|
733
|
+
]) UserModel.afterRemote(method, function(ctx, result, next) {
|
|
734
|
+
ctx.res.setHeader("Cache-Control", "no-store");
|
|
735
|
+
ctx.res.setHeader("Pragma", "no-cache");
|
|
736
|
+
next();
|
|
737
|
+
});
|
|
738
|
+
for (const method of [
|
|
739
|
+
"login",
|
|
740
|
+
"verifyTwoFactor",
|
|
741
|
+
"beginTwoFactorEnrollment",
|
|
742
|
+
"confirmTwoFactorEnrollment",
|
|
743
|
+
"regenerateTwoFactorRecoveryCodes",
|
|
744
|
+
"disableTwoFactor"
|
|
745
|
+
]) UserModel.afterRemoteError(method, function(ctx, next) {
|
|
746
|
+
if (ctx.error) {
|
|
747
|
+
ctx.res.setHeader("Cache-Control", "no-store");
|
|
748
|
+
ctx.res.setHeader("Pragma", "no-cache");
|
|
749
|
+
}
|
|
750
|
+
if (ctx.error && ctx.error.retryAfter) ctx.res.setHeader("Retry-After", String(ctx.error.retryAfter));
|
|
751
|
+
next();
|
|
553
752
|
});
|
|
554
753
|
UserModel.remoteMethod("logout", {
|
|
555
754
|
description: "Logout a user with access token.",
|
|
@@ -682,6 +881,13 @@ var require_user = /* @__PURE__ */ require_runtime$1.__commonJSMin(((exports, mo
|
|
|
682
881
|
}
|
|
683
882
|
return token.userId;
|
|
684
883
|
}
|
|
884
|
+
function buildAuthenticationOptions(ctx) {
|
|
885
|
+
const req = ctx && ctx.req;
|
|
886
|
+
return {
|
|
887
|
+
accessToken: req && req.accessToken,
|
|
888
|
+
authenticationSource: req && (req.ip || req.socket && req.socket.remoteAddress)
|
|
889
|
+
};
|
|
890
|
+
}
|
|
685
891
|
UserModel.afterRemote("confirm", function(ctx, inst, next) {
|
|
686
892
|
if (ctx.args.redirect !== void 0) {
|
|
687
893
|
if (!ctx.res) return next(new Error(g.f("The transport does not support HTTP redirects.")));
|
|
@@ -780,6 +986,37 @@ var require_user = /* @__PURE__ */ require_runtime$1.__commonJSMin(((exports, mo
|
|
|
780
986
|
}
|
|
781
987
|
ctx.Model._invalidateAccessTokensOfUsers(userIdsToExpire, ctx.options, next);
|
|
782
988
|
});
|
|
989
|
+
User.observe("after save", function invalidateTwoFactorChallenges(ctx, next) {
|
|
990
|
+
if (!ctx.hookState.originalUserData || !(ctx.instance || ctx.data).password) return next();
|
|
991
|
+
const Challenge = ctx.Model.app && ctx.Model.app.models.TwoFactorChallenge;
|
|
992
|
+
if (!Challenge) return next();
|
|
993
|
+
const pkName = ctx.Model.definition.idName() || "id";
|
|
994
|
+
const principalIds = ctx.hookState.originalUserData.map(function(user) {
|
|
995
|
+
return String(user[pkName]);
|
|
996
|
+
});
|
|
997
|
+
Challenge.updateAll({
|
|
998
|
+
principalType: ctx.Model.modelName,
|
|
999
|
+
principalId: { inq: principalIds },
|
|
1000
|
+
status: { inq: ["pending", "verifying"] }
|
|
1001
|
+
}, { status: "expired" }, function(err) {
|
|
1002
|
+
if (err) {
|
|
1003
|
+
debug("Unable to invalidate two-factor challenges: %j", err);
|
|
1004
|
+
const event = {
|
|
1005
|
+
error: err,
|
|
1006
|
+
modelName: ctx.Model.modelName,
|
|
1007
|
+
principalCount: principalIds.length,
|
|
1008
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
1009
|
+
};
|
|
1010
|
+
try {
|
|
1011
|
+
ctx.Model.emit("twoFactorChallengeInvalidationError", event);
|
|
1012
|
+
} catch {}
|
|
1013
|
+
try {
|
|
1014
|
+
ctx.Model.app.emit("authenticationSecurityCleanupError", err);
|
|
1015
|
+
} catch {}
|
|
1016
|
+
}
|
|
1017
|
+
next();
|
|
1018
|
+
});
|
|
1019
|
+
});
|
|
783
1020
|
}
|
|
784
1021
|
function hasMoreThanOneOwnEnumerableKey(object) {
|
|
785
1022
|
let count = 0;
|
|
@@ -42,6 +42,36 @@ var require_user = /* @__PURE__ */ require("../../_virtual/_rolldown/runtime.cjs
|
|
|
42
42
|
"permission": "ALLOW",
|
|
43
43
|
"property": "login"
|
|
44
44
|
},
|
|
45
|
+
{
|
|
46
|
+
"principalType": "ROLE",
|
|
47
|
+
"principalId": "$everyone",
|
|
48
|
+
"permission": "ALLOW",
|
|
49
|
+
"property": "verifyTwoFactor"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"principalType": "ROLE",
|
|
53
|
+
"principalId": "$authenticated",
|
|
54
|
+
"permission": "ALLOW",
|
|
55
|
+
"property": "beginTwoFactorEnrollment"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"principalType": "ROLE",
|
|
59
|
+
"principalId": "$authenticated",
|
|
60
|
+
"permission": "ALLOW",
|
|
61
|
+
"property": "confirmTwoFactorEnrollment"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"principalType": "ROLE",
|
|
65
|
+
"principalId": "$authenticated",
|
|
66
|
+
"permission": "ALLOW",
|
|
67
|
+
"property": "regenerateTwoFactorRecoveryCodes"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"principalType": "ROLE",
|
|
71
|
+
"principalId": "$authenticated",
|
|
72
|
+
"permission": "ALLOW",
|
|
73
|
+
"property": "disableTwoFactor"
|
|
74
|
+
},
|
|
45
75
|
{
|
|
46
76
|
"principalType": "ROLE",
|
|
47
77
|
"principalId": "$everyone",
|
package/dist/index.cjs
CHANGED
|
@@ -2,6 +2,7 @@ const require_lib_loopback = require("./lib/loopback.cjs");
|
|
|
2
2
|
const require_lib_connectors_base_connector = require("./lib/connectors/base-connector.cjs");
|
|
3
3
|
const require_lib_connectors_memory = require("./lib/connectors/memory.cjs");
|
|
4
4
|
const require_lib_connectors_mail = require("./lib/connectors/mail.cjs");
|
|
5
|
+
const require_lib_rate_limit_index = require("./lib/rate-limit/index.cjs");
|
|
5
6
|
//#region src/index.ts
|
|
6
7
|
const loopback = require_lib_loopback;
|
|
7
8
|
require("@vsaas/loopback-datasource-juggler");
|
|
@@ -12,5 +13,6 @@ loopback.Remote = require("@vsaas/loopback-connector-remote");
|
|
|
12
13
|
loopback.GeoPoint = require("@vsaas/loopback-datasource-juggler/geo").GeoPoint;
|
|
13
14
|
loopback.DateString = require("@vsaas/loopback-datasource-juggler/date-string");
|
|
14
15
|
loopback.ValidationError = loopback.Model.ValidationError;
|
|
16
|
+
loopback.rateLimit = require_lib_rate_limit_index;
|
|
15
17
|
module.exports = loopback;
|
|
16
18
|
//#endregion
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//#region src/lib/access-context.d.ts
|
|
2
|
+
declare const DEFAULT_SCOPES: string[];
|
|
3
|
+
declare function AccessContext(context: any): any;
|
|
4
|
+
declare namespace AccessContext {
|
|
5
|
+
var ALL: string;
|
|
6
|
+
var READ: string;
|
|
7
|
+
var REPLICATE: string;
|
|
8
|
+
var WRITE: string;
|
|
9
|
+
var EXECUTE: string;
|
|
10
|
+
var DEFAULT: string;
|
|
11
|
+
var ALLOW: string;
|
|
12
|
+
var ALARM: string;
|
|
13
|
+
var AUDIT: string;
|
|
14
|
+
var DENY: string;
|
|
15
|
+
var permissionOrder: {
|
|
16
|
+
DEFAULT: number;
|
|
17
|
+
ALLOW: number;
|
|
18
|
+
ALARM: number;
|
|
19
|
+
AUDIT: number;
|
|
20
|
+
DENY: number;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
declare function Principal(type: any, id: any, name: any): any;
|
|
24
|
+
declare namespace Principal {
|
|
25
|
+
var USER: string;
|
|
26
|
+
var APP: string;
|
|
27
|
+
var APPLICATION: string;
|
|
28
|
+
var ROLE: string;
|
|
29
|
+
var SCOPE: string;
|
|
30
|
+
}
|
|
31
|
+
declare function AccessRequest(model: any, property: any, accessType: any, permission: any, methodNames: any, registry: any): any;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { AccessContext, AccessRequest, DEFAULT_SCOPES, Principal };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|