@vsaas/loopback 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +91 -0
  3. package/common/models/README.md +109 -0
  4. package/common/models/access-token.json +37 -0
  5. package/common/models/acl.json +17 -0
  6. package/common/models/application.json +130 -0
  7. package/common/models/change.json +25 -0
  8. package/common/models/checkpoint.json +14 -0
  9. package/common/models/email.json +11 -0
  10. package/common/models/key-value-model.json +4 -0
  11. package/common/models/role-mapping.json +26 -0
  12. package/common/models/role.json +30 -0
  13. package/common/models/scope.json +14 -0
  14. package/common/models/user.json +118 -0
  15. package/dist/_virtual/_rolldown/runtime.cjs +32 -0
  16. package/dist/common/models/access-token.cjs +144 -0
  17. package/dist/common/models/access-token2.cjs +43 -0
  18. package/dist/common/models/acl.cjs +428 -0
  19. package/dist/common/models/acl2.cjs +27 -0
  20. package/dist/common/models/application.cjs +100 -0
  21. package/dist/common/models/application2.cjs +118 -0
  22. package/dist/common/models/change.cjs +404 -0
  23. package/dist/common/models/change2.cjs +25 -0
  24. package/dist/common/models/checkpoint.cjs +43 -0
  25. package/dist/common/models/checkpoint2.cjs +18 -0
  26. package/dist/common/models/email.cjs +18 -0
  27. package/dist/common/models/email2.cjs +30 -0
  28. package/dist/common/models/key-value-model.cjs +140 -0
  29. package/dist/common/models/key-value-model2.cjs +14 -0
  30. package/dist/common/models/role-mapping.cjs +57 -0
  31. package/dist/common/models/role-mapping2.cjs +34 -0
  32. package/dist/common/models/role.cjs +396 -0
  33. package/dist/common/models/role2.cjs +38 -0
  34. package/dist/common/models/scope.cjs +30 -0
  35. package/dist/common/models/scope2.cjs +21 -0
  36. package/dist/common/models/user.cjs +810 -0
  37. package/dist/common/models/user2.cjs +118 -0
  38. package/dist/index.cjs +16 -0
  39. package/dist/lib/access-context.cjs +228 -0
  40. package/dist/lib/application.cjs +450 -0
  41. package/dist/lib/builtin-models.cjs +60 -0
  42. package/dist/lib/configure-shared-methods.cjs +41 -0
  43. package/dist/lib/connectors/base-connector.cjs +23 -0
  44. package/dist/lib/connectors/mail-direct-transport.cjs +375 -0
  45. package/dist/lib/connectors/mail-stub-transport.cjs +86 -0
  46. package/dist/lib/connectors/mail.cjs +128 -0
  47. package/dist/lib/connectors/memory.cjs +19 -0
  48. package/dist/lib/current-context.cjs +22 -0
  49. package/dist/lib/globalize.cjs +29 -0
  50. package/dist/lib/loopback.cjs +313 -0
  51. package/dist/lib/model.cjs +1009 -0
  52. package/dist/lib/persisted-model.cjs +1835 -0
  53. package/dist/lib/registry.cjs +291 -0
  54. package/dist/lib/runtime.cjs +25 -0
  55. package/dist/lib/server-app.cjs +231 -0
  56. package/dist/lib/utils.cjs +154 -0
  57. package/dist/package.cjs +124 -0
  58. package/dist/server/middleware/context.cjs +7 -0
  59. package/dist/server/middleware/error-handler.cjs +6 -0
  60. package/dist/server/middleware/favicon.cjs +13 -0
  61. package/dist/server/middleware/rest.cjs +44 -0
  62. package/dist/server/middleware/static.cjs +14 -0
  63. package/dist/server/middleware/status.cjs +28 -0
  64. package/dist/server/middleware/token.cjs +66 -0
  65. package/dist/server/middleware/url-not-found.cjs +20 -0
  66. package/favicon.ico +0 -0
  67. package/package.json +121 -0
  68. package/templates/reset-form.ejs +3 -0
  69. package/templates/verify.ejs +9 -0
@@ -0,0 +1,32 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
7
+ var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
8
+ var __exportAll = (all, no_symbols) => {
9
+ let target = {};
10
+ for (var name in all) __defProp(target, name, {
11
+ get: all[name],
12
+ enumerable: true
13
+ });
14
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
15
+ return target;
16
+ };
17
+ var __copyProps = (to, from, except, desc) => {
18
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
19
+ key = keys[i];
20
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
21
+ get: ((k) => from[k]).bind(null, key),
22
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
23
+ });
24
+ }
25
+ return to;
26
+ };
27
+ var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ //#endregion
29
+ exports.__commonJSMin = __commonJSMin;
30
+ exports.__esmMin = __esmMin;
31
+ exports.__exportAll = __exportAll;
32
+ exports.__toCommonJS = __toCommonJS;
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ const require_runtime = require("../../_virtual/_rolldown/runtime.cjs");
3
+ const require_lib_globalize = require("../../lib/globalize.cjs");
4
+ const require_lib_utils = require("../../lib/utils.cjs");
5
+ //#region src/common/models/access-token.ts
6
+ var require_access_token = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => {
7
+ const g = require_lib_globalize;
8
+ const utils = require_lib_utils;
9
+ const assert = require("assert");
10
+ const crypto = require("crypto");
11
+ const DEFAULT_TOKEN_LEN = 64;
12
+ function createRandomToken(length, callback) {
13
+ let token = "";
14
+ function appendChunk() {
15
+ const remainingLength = length - token.length;
16
+ if (remainingLength <= 0) {
17
+ callback(null, token);
18
+ return;
19
+ }
20
+ const byteLength = Math.max(1, Math.ceil(remainingLength * 3 / 4));
21
+ crypto.randomBytes(byteLength, function(err, buffer) {
22
+ if (err) {
23
+ callback(err);
24
+ return;
25
+ }
26
+ token += buffer.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
27
+ if (token.length >= length) {
28
+ callback(null, token.slice(0, length));
29
+ return;
30
+ }
31
+ appendChunk();
32
+ });
33
+ }
34
+ appendChunk();
35
+ }
36
+ function configureAccessToken(AccessToken) {
37
+ AccessToken.ANONYMOUS = new AccessToken({ id: "$anonymous" });
38
+ AccessToken.createAccessTokenId = function(fn) {
39
+ createRandomToken(this.settings.accessTokenIdLength || DEFAULT_TOKEN_LEN, fn);
40
+ };
41
+ AccessToken.observe("before save", function(ctx, next) {
42
+ if (!ctx.instance || ctx.instance.id) return next();
43
+ AccessToken.createAccessTokenId(function(err, id) {
44
+ if (err) return next(err);
45
+ ctx.instance.id = id;
46
+ next();
47
+ });
48
+ });
49
+ AccessToken.getIdForRequest = function(req, options) {
50
+ options = options || {};
51
+ let params = options.params || [];
52
+ let headers = options.headers || [];
53
+ let cookies = options.cookies || [];
54
+ let i = 0;
55
+ let length;
56
+ let id;
57
+ if (options.searchDefaultTokenKeys !== false) {
58
+ params = params.concat(["access_token"]);
59
+ headers = headers.concat(["X-Access-Token", "authorization"]);
60
+ cookies = cookies.concat(["access_token", "authorization"]);
61
+ }
62
+ for (length = params.length; i < length; i++) {
63
+ const param = params[i];
64
+ id = req.params && req.params[param] !== void 0 ? req.params[param] : req.body && req.body[param] !== void 0 ? req.body[param] : req.query && req.query[param] !== void 0 ? req.query[param] : void 0;
65
+ if (typeof id === "string") return id;
66
+ }
67
+ for (i = 0, length = headers.length; i < length; i++) {
68
+ id = req.header(headers[i]);
69
+ if (typeof id === "string") {
70
+ if (id === "") continue;
71
+ if (id.indexOf("Bearer ") === 0) {
72
+ id = id.substring(7);
73
+ if (options.bearerTokenBase64Encoded) id = Buffer.from(id, "base64").toString("utf8");
74
+ } else if (/^Basic /i.test(id)) {
75
+ id = id.substring(6);
76
+ id = Buffer.from(id, "base64").toString("utf8");
77
+ const parts = /^([^:]*):(.*)$/.exec(id);
78
+ if (parts) id = parts[2].length > parts[1].length ? parts[2] : parts[1];
79
+ }
80
+ return id;
81
+ }
82
+ }
83
+ if (req.signedCookies) for (i = 0, length = cookies.length; i < length; i++) {
84
+ id = req.signedCookies[cookies[i]];
85
+ if (typeof id === "string") return id;
86
+ }
87
+ return null;
88
+ };
89
+ AccessToken.resolve = function(id, cb) {
90
+ return promiseOrCallback(this.findById(id).then(function(token) {
91
+ if (!token) return null;
92
+ return token.validate().then(function(isValid) {
93
+ if (isValid) return token;
94
+ const e = new Error(g.f("Invalid Access Token"));
95
+ e.status = e.statusCode = 401;
96
+ e.code = "INVALID_TOKEN";
97
+ throw e;
98
+ });
99
+ }), cb);
100
+ };
101
+ AccessToken.findForRequest = function(req, options, cb) {
102
+ if (cb === void 0 && typeof options === "function") {
103
+ cb = options;
104
+ options = {};
105
+ }
106
+ const id = this.getIdForRequest(req, options);
107
+ return promiseOrCallback(id ? utils.invokeWithCallback(this.resolve, this, [id]) : Promise.resolve(null), cb);
108
+ };
109
+ AccessToken.prototype.validate = function(cb) {
110
+ const token = this;
111
+ return promiseOrCallback((async function() {
112
+ assert(token.created && typeof token.created.getTime === "function", "token.created must be a valid Date");
113
+ assert(token.ttl !== 0, "token.ttl must be not be 0");
114
+ assert(token.ttl, "token.ttl must exist");
115
+ assert(token.ttl >= -1, "token.ttl must be >= -1");
116
+ const AccessToken = token.constructor;
117
+ const userRelation = AccessToken.relations.user;
118
+ let User = userRelation && userRelation.modelTo;
119
+ if (token.principalType) {
120
+ User = AccessToken.registry.findModel(token.principalType);
121
+ if (!User) return false;
122
+ }
123
+ const elapsedSeconds = (Date.now() - token.created.getTime()) / 1e3;
124
+ const secondsToLive = token.ttl;
125
+ const eternalTokensAllowed = !!(User && User.settings.allowEternalTokens);
126
+ if (secondsToLive === -1 ? eternalTokensAllowed : elapsedSeconds < secondsToLive) return true;
127
+ await token.destroy();
128
+ return false;
129
+ })(), cb);
130
+ };
131
+ }
132
+ function promiseOrCallback(promise, cb) {
133
+ if (typeof cb === "function") {
134
+ promise.then(function(result) {
135
+ cb(null, result);
136
+ }, cb);
137
+ return;
138
+ }
139
+ return promise;
140
+ }
141
+ module.exports = configureAccessToken;
142
+ }));
143
+ //#endregion
144
+ module.exports = require_access_token();
@@ -0,0 +1,43 @@
1
+ //#region common/models/access-token.json
2
+ var require_access_token = /* @__PURE__ */ require("../../_virtual/_rolldown/runtime.cjs").__commonJSMin(((exports, module) => {
3
+ module.exports = {
4
+ "name": "AccessToken",
5
+ "properties": {
6
+ "id": {
7
+ "type": "string",
8
+ "id": true
9
+ },
10
+ "ttl": {
11
+ "type": "number",
12
+ "ttl": true,
13
+ "default": 1209600,
14
+ "description": "time to live in seconds (2 weeks by default)"
15
+ },
16
+ "scopes": {
17
+ "type": ["string"],
18
+ "description": "Array of scopes granted to this access token."
19
+ },
20
+ "created": {
21
+ "type": "Date",
22
+ "defaultFn": "now"
23
+ }
24
+ },
25
+ "relations": { "user": {
26
+ "type": "belongsTo",
27
+ "model": "User",
28
+ "foreignKey": "userId"
29
+ } },
30
+ "acls": [{
31
+ "principalType": "ROLE",
32
+ "principalId": "$everyone",
33
+ "permission": "DENY"
34
+ }]
35
+ };
36
+ }));
37
+ //#endregion
38
+ Object.defineProperty(exports, "default", {
39
+ enumerable: true,
40
+ get: function() {
41
+ return require_access_token();
42
+ }
43
+ });
@@ -0,0 +1,428 @@
1
+ "use strict";
2
+ const require_runtime$1 = require("../../_virtual/_rolldown/runtime.cjs");
3
+ const require_lib_globalize = require("../../lib/globalize.cjs");
4
+ const require_lib_runtime = require("../../lib/runtime.cjs");
5
+ const require_lib_utils = require("../../lib/utils.cjs");
6
+ const require_lib_access_context = require("../../lib/access-context.cjs");
7
+ //#region src/common/models/acl.ts
8
+ var require_acl = /* @__PURE__ */ require_runtime$1.__commonJSMin(((exports, module) => {
9
+ const g = require_lib_globalize;
10
+ const runtime = require_lib_runtime;
11
+ const utils = require_lib_utils;
12
+ const assert = require("assert");
13
+ const debug = require("debug")("loopback:security:acl");
14
+ const ctx = (require_lib_access_context.init_access_context(), require_runtime$1.__toCommonJS(require_lib_access_context.access_context_exports));
15
+ const AccessContext = ctx.AccessContext;
16
+ const Principal = ctx.Principal;
17
+ const AccessRequest = ctx.AccessRequest;
18
+ module.exports = function(ACL) {
19
+ const Role = runtime.loopback.Role;
20
+ assert(Role, "Role model must be defined before ACL model");
21
+ ACL.ALL = AccessContext.ALL;
22
+ ACL.DEFAULT = AccessContext.DEFAULT;
23
+ ACL.ALLOW = AccessContext.ALLOW;
24
+ ACL.ALARM = AccessContext.ALARM;
25
+ ACL.AUDIT = AccessContext.AUDIT;
26
+ ACL.DENY = AccessContext.DENY;
27
+ ACL.READ = AccessContext.READ;
28
+ ACL.REPLICATE = AccessContext.REPLICATE;
29
+ ACL.WRITE = AccessContext.WRITE;
30
+ ACL.EXECUTE = AccessContext.EXECUTE;
31
+ ACL.USER = Principal.USER;
32
+ ACL.APP = ACL.APPLICATION = Principal.APPLICATION;
33
+ ACL.ROLE = Principal.ROLE;
34
+ ACL.SCOPE = Principal.SCOPE;
35
+ ACL.DEFAULT_SCOPE = ctx.DEFAULT_SCOPES[0];
36
+ ACL.getMatchingScore = function getMatchingScore(rule, req) {
37
+ const props = [
38
+ "model",
39
+ "property",
40
+ "accessType"
41
+ ];
42
+ let score = 0;
43
+ for (let i = 0; i < props.length; i++) {
44
+ score = score * 4;
45
+ const ruleValue = rule[props[i]] || ACL.ALL;
46
+ const requestedValue = req[props[i]] || ACL.ALL;
47
+ const isMatchingMethodName = props[i] === "property" && req.methodNames.indexOf(ruleValue) !== -1;
48
+ let isMatchingAccessType = ruleValue === requestedValue;
49
+ if (props[i] === "accessType" && !isMatchingAccessType) switch (ruleValue) {
50
+ case ACL.EXECUTE:
51
+ isMatchingAccessType = true;
52
+ break;
53
+ case ACL.WRITE:
54
+ isMatchingAccessType = requestedValue === ACL.REPLICATE;
55
+ break;
56
+ }
57
+ if (isMatchingMethodName || isMatchingAccessType) score += 3;
58
+ else if (ruleValue === ACL.ALL) score += 2;
59
+ else if (requestedValue === ACL.ALL) score += 1;
60
+ else return -1;
61
+ }
62
+ score = score * 4;
63
+ switch (rule.principalType) {
64
+ case ACL.USER:
65
+ score += 4;
66
+ break;
67
+ case ACL.APP:
68
+ score += 3;
69
+ break;
70
+ case ACL.ROLE:
71
+ score += 2;
72
+ break;
73
+ default: score += 1;
74
+ }
75
+ score = score * 8;
76
+ if (rule.principalType === ACL.ROLE) switch (rule.principalId) {
77
+ case Role.OWNER:
78
+ score += 4;
79
+ break;
80
+ case Role.RELATED:
81
+ score += 3;
82
+ break;
83
+ case Role.AUTHENTICATED:
84
+ case Role.UNAUTHENTICATED:
85
+ score += 2;
86
+ break;
87
+ case Role.EVERYONE:
88
+ score += 1;
89
+ break;
90
+ default: score += 5;
91
+ }
92
+ score = score * 4;
93
+ score += AccessContext.permissionOrder[rule.permission || ACL.ALLOW] - 1;
94
+ return score;
95
+ };
96
+ ACL.prototype.score = function(req) {
97
+ return this.constructor.getMatchingScore(this, req);
98
+ };
99
+ ACL.resolvePermission = function resolvePermission(acls, req) {
100
+ if (!(req instanceof AccessRequest)) {
101
+ req.registry = this.registry;
102
+ req = new AccessRequest(req);
103
+ }
104
+ const scoredACLs = acls.map(function(acl, index) {
105
+ return {
106
+ acl,
107
+ index,
108
+ score: ACL.getMatchingScore(acl, req)
109
+ };
110
+ }).sort(function(rule1, rule2) {
111
+ return rule2.score - rule1.score || rule1.index - rule2.index;
112
+ });
113
+ let permission = ACL.DEFAULT;
114
+ for (let i = 0; i < scoredACLs.length; i++) {
115
+ const candidate = scoredACLs[i].acl;
116
+ if (scoredACLs[i].score < 0) break;
117
+ if (!req.isWildcard()) {
118
+ permission = candidate.permission;
119
+ break;
120
+ } else {
121
+ if (req.exactlyMatches(candidate)) {
122
+ permission = candidate.permission;
123
+ break;
124
+ }
125
+ if (AccessContext.permissionOrder[candidate.permission] > AccessContext.permissionOrder[permission]) {
126
+ permission = candidate.permission;
127
+ break;
128
+ }
129
+ }
130
+ }
131
+ if (debug.enabled) {
132
+ debug("The following ACLs were searched: ");
133
+ scoredACLs.forEach(function(result) {
134
+ result.acl.debug();
135
+ debug("with score:", result.score);
136
+ });
137
+ }
138
+ const res = new AccessRequest({
139
+ model: req.model,
140
+ property: req.property,
141
+ accessType: req.accessType,
142
+ permission: permission || ACL.DEFAULT,
143
+ registry: this.registry
144
+ });
145
+ res.settleDefaultPermission();
146
+ return res;
147
+ };
148
+ ACL.getStaticACLs = function getStaticACLs(model, property) {
149
+ const modelClass = this.registry.findModel(model);
150
+ const staticACLs = [];
151
+ if (modelClass && modelClass.settings.acls) modelClass.settings.acls.forEach(function(acl) {
152
+ let prop = acl.property;
153
+ if (Array.isArray(prop) && prop.indexOf(property) >= 0) prop = property;
154
+ if (!prop || prop === ACL.ALL || property === prop) staticACLs.push(new ACL({
155
+ model,
156
+ property: prop || ACL.ALL,
157
+ principalType: acl.principalType,
158
+ principalId: acl.principalId,
159
+ accessType: acl.accessType || ACL.ALL,
160
+ permission: acl.permission
161
+ }));
162
+ });
163
+ const prop = modelClass && (modelClass.definition.properties[property] || modelClass._scopeMeta && modelClass._scopeMeta[property] || modelClass[property] || modelClass.prototype[property]);
164
+ if (prop && prop.acls) prop.acls.forEach(function(acl) {
165
+ staticACLs.push(new ACL({
166
+ model: modelClass.modelName,
167
+ property,
168
+ principalType: acl.principalType,
169
+ principalId: acl.principalId,
170
+ accessType: acl.accessType,
171
+ permission: acl.permission
172
+ }));
173
+ });
174
+ return staticACLs;
175
+ };
176
+ ACL.checkPermission = function checkPermission(principalType, principalId, model, property, accessType, callback) {
177
+ if (!callback) callback = utils.createPromiseCallback();
178
+ if (principalId !== null && principalId !== void 0 && typeof principalId !== "string") principalId = principalId.toString();
179
+ property = property || ACL.ALL;
180
+ const propertyQuery = property === ACL.ALL ? void 0 : { inq: [property, ACL.ALL] };
181
+ accessType = accessType || ACL.ALL;
182
+ const accessTypeQuery = accessType === ACL.ALL ? void 0 : { inq: [
183
+ accessType,
184
+ ACL.ALL,
185
+ ACL.EXECUTE
186
+ ] };
187
+ const req = new AccessRequest({
188
+ model,
189
+ property,
190
+ accessType,
191
+ registry: this.registry
192
+ });
193
+ let acls = this.getStaticACLs(model, property);
194
+ let resolved = this.resolvePermission(acls, req);
195
+ if (resolved && resolved.permission === ACL.DENY) {
196
+ debug("Permission denied by statically resolved permission");
197
+ debug(" Resolved Permission: %j", resolved);
198
+ process.nextTick(function() {
199
+ callback(null, resolved);
200
+ });
201
+ return callback.promise;
202
+ }
203
+ this.find({ where: {
204
+ principalType,
205
+ principalId,
206
+ model,
207
+ property: propertyQuery,
208
+ accessType: accessTypeQuery
209
+ } }, (err, dynACLs) => {
210
+ if (err) return callback(err);
211
+ acls = acls.concat(dynACLs);
212
+ resolved = this.resolvePermission(acls, req);
213
+ return callback(null, resolved);
214
+ });
215
+ return callback.promise;
216
+ };
217
+ ACL.prototype.debug = function() {
218
+ if (debug.enabled) {
219
+ debug("---ACL---");
220
+ debug("model %s", this.model);
221
+ debug("property %s", this.property);
222
+ debug("principalType %s", this.principalType);
223
+ debug("principalId %s", this.principalId);
224
+ debug("accessType %s", this.accessType);
225
+ debug("permission %s", this.permission);
226
+ }
227
+ };
228
+ ACL.isAllowed = function(permission, defaultPermission) {
229
+ if (permission === ACL.DEFAULT) permission = defaultPermission || ACL.ALLOW;
230
+ return permission !== ACL.DENY;
231
+ };
232
+ ACL.prototype.isAllowed = function(defaultPermission) {
233
+ return this.constructor.isAllowed(this.permission, defaultPermission);
234
+ };
235
+ ACL.checkAccessForContext = function(context, callback) {
236
+ if (!callback) callback = utils.createPromiseCallback();
237
+ this.resolveRelatedModels();
238
+ const roleModel = this.roleModel;
239
+ if (!(context instanceof AccessContext)) {
240
+ context.registry = this.registry;
241
+ context = new AccessContext(context);
242
+ }
243
+ let authorizedRoles = {};
244
+ const remotingContext = context.remotingContext;
245
+ const model = context.model;
246
+ const modelDefaultPermission = model && model.settings.defaultPermission;
247
+ const property = context.property;
248
+ const accessType = context.accessType;
249
+ const modelName = context.modelName;
250
+ const methodNames = context.methodNames;
251
+ const propertyQuery = property === ACL.ALL ? void 0 : { inq: methodNames.concat([ACL.ALL]) };
252
+ const accessTypeQuery = accessType === ACL.ALL ? void 0 : accessType === ACL.REPLICATE ? { inq: [
253
+ ACL.REPLICATE,
254
+ ACL.WRITE,
255
+ ACL.ALL
256
+ ] } : { inq: [accessType, ACL.ALL] };
257
+ const req = new AccessRequest({
258
+ model: modelName,
259
+ property,
260
+ accessType,
261
+ permission: ACL.DEFAULT,
262
+ methodNames,
263
+ registry: this.registry
264
+ });
265
+ if (!context.isScopeAllowed()) {
266
+ req.permission = ACL.DENY;
267
+ debug("--Denied by scope config--");
268
+ debug("Scopes allowed:", context.accessToken.scopes || ctx.DEFAULT_SCOPES);
269
+ debug("Scope required:", context.getScopes());
270
+ context.debug();
271
+ callback(null, req);
272
+ return callback.promise;
273
+ }
274
+ const effectiveACLs = [];
275
+ const staticACLs = this.getStaticACLs(model.modelName, property);
276
+ const principalLookup = buildPrincipalLookup(context.principals);
277
+ const query = { where: {
278
+ model: { inq: [model.modelName, ACL.ALL] },
279
+ property: propertyQuery,
280
+ accessType: accessTypeQuery
281
+ } };
282
+ this.find(query, (err, acls) => {
283
+ if (err) return callback(err);
284
+ const roleCheckResults = Object.create(null);
285
+ const roleChecks = Object.create(null);
286
+ const inRoleChecks = [];
287
+ const pendingRoleACLs = [];
288
+ for (let i = 0; i < staticACLs.length; i++) acls.push(staticACLs[i]);
289
+ for (let i = 0; i < acls.length; i++) {
290
+ const acl = acls[i];
291
+ if (hasExactPrincipalMatch(principalLookup, acl)) {
292
+ effectiveACLs.push(acl);
293
+ continue;
294
+ }
295
+ if (acl.principalType !== ACL.ROLE) continue;
296
+ pendingRoleACLs.push(acl);
297
+ if (!roleChecks[acl.principalId]) {
298
+ const principalId = acl.principalId;
299
+ roleChecks[principalId] = utils.invokeWithCallback(roleModel.isInRole, roleModel, [principalId, context]).then(function(inRole) {
300
+ roleCheckResults[principalId] = inRole;
301
+ return inRole;
302
+ });
303
+ inRoleChecks.push(roleChecks[principalId]);
304
+ }
305
+ }
306
+ Promise.all(inRoleChecks).then(() => {
307
+ for (let i = 0; i < pendingRoleACLs.length; i++) {
308
+ const acl = pendingRoleACLs[i];
309
+ if (!roleCheckResults[acl.principalId]) continue;
310
+ effectiveACLs.push(acl);
311
+ if (acl.isAllowed(modelDefaultPermission)) authorizedRoles[acl.principalId] = true;
312
+ }
313
+ const resolved = this.resolvePermission(effectiveACLs, req);
314
+ debug("---Resolved---");
315
+ resolved.debug();
316
+ authorizedRoles = resolved.isAllowed() ? authorizedRoles : {};
317
+ saveAuthorizedRolesToRemotingContext(remotingContext, authorizedRoles);
318
+ return callback(null, resolved);
319
+ }).catch(function(error) {
320
+ return callback(error, null);
321
+ });
322
+ });
323
+ return callback.promise;
324
+ };
325
+ function buildPrincipalLookup(principals) {
326
+ const lookup = Object.create(null);
327
+ for (let i = 0; i < principals.length; i++) {
328
+ const principal = principals[i];
329
+ lookup[getPrincipalLookupKey(principal.type, principal.id)] = true;
330
+ }
331
+ return lookup;
332
+ }
333
+ function hasExactPrincipalMatch(principalLookup, acl) {
334
+ return principalLookup[getPrincipalLookupKey(acl.principalType, acl.principalId)] === true;
335
+ }
336
+ function getPrincipalLookupKey(type, id) {
337
+ return String(type) + ":" + String(id);
338
+ }
339
+ function saveAuthorizedRolesToRemotingContext(remotingContext, authorizedRoles) {
340
+ const options = remotingContext && remotingContext.args && remotingContext.args.options;
341
+ if (options && typeof options === "object") options.authorizedRoles = authorizedRoles;
342
+ }
343
+ ACL.checkAccessForToken = function(token, model, modelId, method, callback) {
344
+ assert(token, "Access token is required");
345
+ if (!callback) callback = utils.createPromiseCallback();
346
+ const context = new AccessContext({
347
+ registry: this.registry,
348
+ accessToken: token,
349
+ model,
350
+ property: method,
351
+ method,
352
+ modelId
353
+ });
354
+ this.checkAccessForContext(context, function(err, accessRequest) {
355
+ if (err) callback(err);
356
+ else callback(null, accessRequest.isAllowed());
357
+ });
358
+ return callback.promise;
359
+ };
360
+ ACL.resolveRelatedModels = function() {
361
+ if (!this.roleModel) {
362
+ const reg = this.registry;
363
+ this.roleModel = reg.getModelByType("Role");
364
+ this.roleMappingModel = reg.getModelByType("RoleMapping");
365
+ this.userModel = reg.getModelByType("User");
366
+ this.applicationModel = reg.getModelByType("Application");
367
+ }
368
+ };
369
+ ACL.resolvePrincipal = function(type, id, cb) {
370
+ cb = cb || utils.createPromiseCallback();
371
+ type = type || ACL.ROLE;
372
+ this.resolveRelatedModels();
373
+ switch (type) {
374
+ case ACL.ROLE:
375
+ this.roleModel.findOne({ where: { or: [{ name: id }, { id }] } }, cb);
376
+ break;
377
+ case ACL.USER:
378
+ this.userModel.findOne({ where: { or: [
379
+ { username: id },
380
+ { email: id },
381
+ { id }
382
+ ] } }, cb);
383
+ break;
384
+ case ACL.APP:
385
+ this.applicationModel.findOne({ where: { or: [
386
+ { name: id },
387
+ { email: id },
388
+ { id }
389
+ ] } }, cb);
390
+ break;
391
+ default:
392
+ const userModel = this.registry.findModel(type);
393
+ if (userModel) userModel.findOne({ where: { or: [
394
+ { username: id },
395
+ { email: id },
396
+ { id }
397
+ ] } }, cb);
398
+ else process.nextTick(function() {
399
+ const err = new Error(g.f("Invalid principal type: %s", type));
400
+ err.statusCode = 400;
401
+ err.code = "INVALID_PRINCIPAL_TYPE";
402
+ cb(err);
403
+ });
404
+ }
405
+ return cb.promise;
406
+ };
407
+ ACL.isMappedToRole = function(principalType, principalId, role, cb) {
408
+ cb = cb || utils.createPromiseCallback();
409
+ (async () => {
410
+ const principal = await utils.invokeWithCallback(this.resolvePrincipal, this, [principalType, principalId]);
411
+ if (principal != null) principalId = principal.id;
412
+ principalType = principalType || "ROLE";
413
+ const resolvedRole = await utils.invokeWithCallback(this.resolvePrincipal, this, ["ROLE", role]);
414
+ if (!resolvedRole) return null;
415
+ return utils.invokeWithCallback(this.roleMappingModel.findOne, this.roleMappingModel, [{ where: {
416
+ roleId: resolvedRole.id,
417
+ principalType,
418
+ principalId: String(principalId)
419
+ } }]);
420
+ })().then(function(result) {
421
+ cb(null, !!result);
422
+ }, cb);
423
+ return cb.promise;
424
+ };
425
+ };
426
+ }));
427
+ //#endregion
428
+ module.exports = require_acl();
@@ -0,0 +1,27 @@
1
+ //#region common/models/acl.json
2
+ var require_acl = /* @__PURE__ */ require("../../_virtual/_rolldown/runtime.cjs").__commonJSMin(((exports, module) => {
3
+ module.exports = {
4
+ "name": "ACL",
5
+ "properties": {
6
+ "model": {
7
+ "type": "string",
8
+ "description": "The name of the model"
9
+ },
10
+ "property": {
11
+ "type": "string",
12
+ "description": "The name of the property, method, scope, or relation"
13
+ },
14
+ "accessType": "string",
15
+ "permission": "string",
16
+ "principalType": "string",
17
+ "principalId": "string"
18
+ }
19
+ };
20
+ }));
21
+ //#endregion
22
+ Object.defineProperty(exports, "default", {
23
+ enumerable: true,
24
+ get: function() {
25
+ return require_acl();
26
+ }
27
+ });