@albirex/platformatic-logto 1.3.5 → 1.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.cjs +474 -0
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.cts +32 -0
- package/lib/index.d.ts +3 -2
- package/lib/index.js +54 -22
- package/lib/index.js.map +1 -1
- package/package.json +11 -5
package/lib/index.cjs
ADDED
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// src/index.ts
|
|
30
|
+
var index_exports = {};
|
|
31
|
+
__export(index_exports, {
|
|
32
|
+
default: () => index_default,
|
|
33
|
+
fastifyLogto: () => import_fastify_logto2.fastifyLogto,
|
|
34
|
+
platformaticLogto: () => platformaticLogto
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
var import_fastify_plugin = __toESM(require("fastify-plugin"), 1);
|
|
38
|
+
var fastifyUser = __toESM(require("fastify-user"), 1);
|
|
39
|
+
|
|
40
|
+
// src/utils/find-rule.ts
|
|
41
|
+
function findRule(rules, roles) {
|
|
42
|
+
let found = null;
|
|
43
|
+
for (const rule of rules) {
|
|
44
|
+
for (const role of roles) {
|
|
45
|
+
if (rule.role === role) {
|
|
46
|
+
found = rule;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (found) {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return found;
|
|
55
|
+
}
|
|
56
|
+
var find_rule_default = findRule;
|
|
57
|
+
|
|
58
|
+
// src/utils/utils.ts
|
|
59
|
+
function getRequestFromContext(ctx) {
|
|
60
|
+
if (ctx && !ctx.reply) {
|
|
61
|
+
throw new Error("Missing reply in context. You should call this function with { ctx: { reply }}");
|
|
62
|
+
}
|
|
63
|
+
return ctx.reply.request;
|
|
64
|
+
}
|
|
65
|
+
function getRoles(request, roleKey, anonymousRole, isRolePath = false) {
|
|
66
|
+
let output = [];
|
|
67
|
+
const user = request.user;
|
|
68
|
+
if (!user) {
|
|
69
|
+
output.push(anonymousRole);
|
|
70
|
+
return output;
|
|
71
|
+
}
|
|
72
|
+
let rolesRaw;
|
|
73
|
+
if (isRolePath) {
|
|
74
|
+
const roleKeys = roleKey.split(".");
|
|
75
|
+
rolesRaw = user;
|
|
76
|
+
for (const key of roleKeys) {
|
|
77
|
+
rolesRaw = rolesRaw[key];
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
rolesRaw = user[roleKey];
|
|
81
|
+
}
|
|
82
|
+
if (typeof rolesRaw === "string") {
|
|
83
|
+
output = rolesRaw.split(",");
|
|
84
|
+
} else if (Array.isArray(rolesRaw)) {
|
|
85
|
+
output = rolesRaw;
|
|
86
|
+
}
|
|
87
|
+
if (output.length === 0) {
|
|
88
|
+
output.push(anonymousRole);
|
|
89
|
+
}
|
|
90
|
+
return output;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/utils/errors.ts
|
|
94
|
+
var import_error = __toESM(require("@fastify/error"), 1);
|
|
95
|
+
var ERROR_PREFIX = "PLT_DB_AUTH";
|
|
96
|
+
var Unauthorized = (0, import_error.default)(`${ERROR_PREFIX}_UNAUTHORIZED`, "operation not allowed", 401);
|
|
97
|
+
var UnauthorizedField = (0, import_error.default)(`${ERROR_PREFIX}_FIELD_UNAUTHORIZED`, "field not allowed: %s", 401);
|
|
98
|
+
var MissingNotNullableError = (0, import_error.default)(`${ERROR_PREFIX}_NOT_NULLABLE_MISSING`, 'missing not nullable field: "%s" in save rule for entity "%s"');
|
|
99
|
+
|
|
100
|
+
// src/index.ts
|
|
101
|
+
var import_fastify_logto = __toESM(require("@albirex/fastify-logto"), 1);
|
|
102
|
+
var import_fastify_logto2 = require("@albirex/fastify-logto");
|
|
103
|
+
var PLT_ADMIN_ROLE = "platformatic-admin";
|
|
104
|
+
var platformaticLogto = (0, import_fastify_plugin.default)(async (app, opts) => {
|
|
105
|
+
app.register(import_fastify_logto.default, {
|
|
106
|
+
endpoint: opts.logtoBaseUrl || "https://auth.example.com",
|
|
107
|
+
appId: opts.logtoAppId || "your-app-id",
|
|
108
|
+
appSecret: opts.logtoAppSecret || "your-app-secret"
|
|
109
|
+
});
|
|
110
|
+
await app.register(fastifyUser, opts.jwtPlugin);
|
|
111
|
+
const adminSecret = opts.adminSecret;
|
|
112
|
+
const roleKey = opts.rolePath || opts.roleKey || "X-PLATFORMATIC-ROLE";
|
|
113
|
+
const userKey = opts.userPath || opts.userKey || "X-PLATFORMATIC-USER-ID";
|
|
114
|
+
const isRolePath = !!opts.rolePath;
|
|
115
|
+
const anonymousRole = opts.anonymousRole || "anonymous";
|
|
116
|
+
async function composeLogToRules() {
|
|
117
|
+
const rolesResp = await app.logto.callAPI("/api/roles?type=User", "GET");
|
|
118
|
+
if (!rolesResp.ok) {
|
|
119
|
+
throw rolesResp;
|
|
120
|
+
}
|
|
121
|
+
const roles = await rolesResp.json();
|
|
122
|
+
const rules = [{
|
|
123
|
+
role: anonymousRole,
|
|
124
|
+
entities: Object.keys(app.platformatic.entities),
|
|
125
|
+
find: opts.allowAnonymous,
|
|
126
|
+
save: opts.allowAnonymous,
|
|
127
|
+
delete: opts.allowAnonymous
|
|
128
|
+
}];
|
|
129
|
+
for (const role of roles) {
|
|
130
|
+
const scopesResp = await app.logto.callAPI(`/api/roles/${role.id}/scopes`, "GET");
|
|
131
|
+
if (!scopesResp.ok) {
|
|
132
|
+
throw scopesResp;
|
|
133
|
+
}
|
|
134
|
+
const scopes = await scopesResp.json();
|
|
135
|
+
for (const scope of scopes) {
|
|
136
|
+
const roleName = role.name;
|
|
137
|
+
let [scopeAction, entity] = scope.name.split(":");
|
|
138
|
+
if (!app.platformatic.entities[entity]) {
|
|
139
|
+
app.log.debug(`Unknown entity '${entity}' in authorization rule`);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
switch (scopeAction) {
|
|
143
|
+
case "create":
|
|
144
|
+
scopeAction = "save";
|
|
145
|
+
break;
|
|
146
|
+
case "read":
|
|
147
|
+
scopeAction = "find";
|
|
148
|
+
break;
|
|
149
|
+
case "update":
|
|
150
|
+
scopeAction = "updateMany";
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
const checkExists = rules.find((r) => r.role === roleName && r.entity === entity);
|
|
154
|
+
if (checkExists) {
|
|
155
|
+
if (opts.checks) {
|
|
156
|
+
checkExists[scopeAction] = {
|
|
157
|
+
checks: {
|
|
158
|
+
userId: userKey
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
} else {
|
|
162
|
+
checkExists[scopeAction] = true;
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
const newRule = {
|
|
166
|
+
role: roleName,
|
|
167
|
+
entity
|
|
168
|
+
};
|
|
169
|
+
if (opts.checks) {
|
|
170
|
+
newRule[scopeAction] = {
|
|
171
|
+
checks: {
|
|
172
|
+
userId: userKey
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
} else {
|
|
176
|
+
newRule[scopeAction] = true;
|
|
177
|
+
}
|
|
178
|
+
if (opts.defaults) {
|
|
179
|
+
newRule.defaults = {
|
|
180
|
+
userId: userKey
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
rules.push(newRule);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const logRules = rules.reduce((prev, curr) => {
|
|
188
|
+
(prev[curr["role"]] ??= []).push(curr);
|
|
189
|
+
return prev;
|
|
190
|
+
}, {});
|
|
191
|
+
for (const key in logRules) {
|
|
192
|
+
app.log.info(`Rules set for role ${key}`);
|
|
193
|
+
for (const element of logRules[key]) {
|
|
194
|
+
const { entity, entities, role, ...other } = element;
|
|
195
|
+
app.log.info(` ${entity ?? entities.join(",")}: ${JSON.stringify(other)}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const missingEntities = Object.keys(app.platformatic.entities).filter((e) => !rules.map((r) => r.entity).includes(e));
|
|
199
|
+
if (missingEntities.length) {
|
|
200
|
+
app.log.warn(`Missing rules for entities: ${missingEntities.join(", ")}`);
|
|
201
|
+
}
|
|
202
|
+
app.log.debug("LogTo calculated rules");
|
|
203
|
+
app.log.debug(rules);
|
|
204
|
+
return rules;
|
|
205
|
+
}
|
|
206
|
+
app.decorateRequest("setupDBAuthorizationUser", setupUser);
|
|
207
|
+
async function setupUser() {
|
|
208
|
+
await this.extractUser();
|
|
209
|
+
let forceAdminRole = false;
|
|
210
|
+
if (adminSecret && this.headers["x-platformatic-admin-secret"] === adminSecret) {
|
|
211
|
+
if (opts.jwtPlugin.jwt) {
|
|
212
|
+
forceAdminRole = true;
|
|
213
|
+
} else {
|
|
214
|
+
this.log.info("admin secret is valid");
|
|
215
|
+
this.user = new Proxy(this.headers, {
|
|
216
|
+
get: (target, key) => {
|
|
217
|
+
let value;
|
|
218
|
+
if (!target[key.toString()]) {
|
|
219
|
+
const newKey = key.toString().toLowerCase();
|
|
220
|
+
value = target[newKey];
|
|
221
|
+
} else {
|
|
222
|
+
value = target[key.toString()];
|
|
223
|
+
}
|
|
224
|
+
if (!value && key.toString().toLowerCase() === roleKey.toLowerCase()) {
|
|
225
|
+
value = PLT_ADMIN_ROLE;
|
|
226
|
+
}
|
|
227
|
+
return value;
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (forceAdminRole) {
|
|
233
|
+
this.user = {
|
|
234
|
+
// ...request.user,
|
|
235
|
+
[roleKey]: PLT_ADMIN_ROLE
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
app.addHook("onReady", async function() {
|
|
240
|
+
const rules = await composeLogToRules();
|
|
241
|
+
const entityRules = {};
|
|
242
|
+
for (let i = 0; i < rules.length; i++) {
|
|
243
|
+
const rule = rules[i];
|
|
244
|
+
let ruleEntities = null;
|
|
245
|
+
if (rule.entity) {
|
|
246
|
+
ruleEntities = [rule.entity];
|
|
247
|
+
} else if (rule.entities) {
|
|
248
|
+
ruleEntities = [...rule.entities];
|
|
249
|
+
} else {
|
|
250
|
+
throw new Error(`Missing entity in authorization rule ${i}`);
|
|
251
|
+
}
|
|
252
|
+
for (const ruleEntity of ruleEntities) {
|
|
253
|
+
const newRule = { ...rule, entity: ruleEntity, entities: void 0 };
|
|
254
|
+
if (!app.platformatic.entities[newRule.entity]) {
|
|
255
|
+
throw new Error(`Unknown entity '${ruleEntity}' in authorization rule ${i}`);
|
|
256
|
+
}
|
|
257
|
+
if (!entityRules[ruleEntity]) {
|
|
258
|
+
entityRules[ruleEntity] = [];
|
|
259
|
+
}
|
|
260
|
+
entityRules[ruleEntity].push(newRule);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
for (const entityKey of Object.keys(app.platformatic.entities)) {
|
|
264
|
+
let useOriginal = function(ctx) {
|
|
265
|
+
return !ctx;
|
|
266
|
+
};
|
|
267
|
+
const rules2 = entityRules[entityKey] || [];
|
|
268
|
+
const type = app.platformatic.entities[entityKey];
|
|
269
|
+
let userPropToFillForPublish;
|
|
270
|
+
const topicsWithoutChecks = false;
|
|
271
|
+
if (userPropToFillForPublish && topicsWithoutChecks) {
|
|
272
|
+
throw new Error(`Subscription for entity "${entityKey}" have conflictling rules across roles`);
|
|
273
|
+
}
|
|
274
|
+
if (adminSecret) {
|
|
275
|
+
rules2.push({
|
|
276
|
+
role: PLT_ADMIN_ROLE,
|
|
277
|
+
find: true,
|
|
278
|
+
save: true,
|
|
279
|
+
delete: true
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
checkSaveMandatoryFieldsInRules(type, rules2);
|
|
283
|
+
app.platformatic.addEntityHooks(entityKey, {
|
|
284
|
+
async find(originalFind, { where, ctx, fields, ...restOpts } = {}) {
|
|
285
|
+
if (useOriginal(ctx)) {
|
|
286
|
+
return originalFind({ ...restOpts, where, ctx, fields });
|
|
287
|
+
}
|
|
288
|
+
const request = getRequestFromContext(ctx);
|
|
289
|
+
const rule = await findRuleForRequestUser(ctx, rules2, roleKey, anonymousRole, isRolePath);
|
|
290
|
+
checkFieldsFromRule(rule.find, fields || Object.keys(app.platformatic.entities[entityKey].fields));
|
|
291
|
+
where = await fromRuleToWhere(ctx, rule.find, where, request.user);
|
|
292
|
+
return originalFind({ ...restOpts, where, ctx, fields });
|
|
293
|
+
},
|
|
294
|
+
async save(originalSave, { input, ctx, fields, ...restOpts }) {
|
|
295
|
+
if (useOriginal(ctx)) {
|
|
296
|
+
return originalSave({ ctx, input, fields, ...restOpts });
|
|
297
|
+
}
|
|
298
|
+
const request = getRequestFromContext(ctx);
|
|
299
|
+
const rule = await findRuleForRequestUser(ctx, rules2, roleKey, anonymousRole, isRolePath);
|
|
300
|
+
if (!rule.save) {
|
|
301
|
+
throw new Unauthorized();
|
|
302
|
+
}
|
|
303
|
+
checkFieldsFromRule(rule.save, fields);
|
|
304
|
+
checkInputFromRuleFields(rule.save, input);
|
|
305
|
+
if (rule.defaults) {
|
|
306
|
+
for (const key of Object.keys(rule.defaults)) {
|
|
307
|
+
const defaults = rule.defaults[key];
|
|
308
|
+
if (typeof defaults === "function") {
|
|
309
|
+
input[key] = await defaults({ user: request.user, ctx, input });
|
|
310
|
+
} else {
|
|
311
|
+
input[key] = request.user[defaults];
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
const hasAllPrimaryKeys = input[type.primaryKey] !== void 0;
|
|
316
|
+
const whereConditions = {};
|
|
317
|
+
whereConditions[type.primaryKey] = { eq: input[type.primaryKey] };
|
|
318
|
+
if (hasAllPrimaryKeys) {
|
|
319
|
+
const where = await fromRuleToWhere(ctx, rule.save, whereConditions, request.user);
|
|
320
|
+
const found = await type.find({
|
|
321
|
+
where,
|
|
322
|
+
ctx,
|
|
323
|
+
fields
|
|
324
|
+
});
|
|
325
|
+
if (found.length === 0) {
|
|
326
|
+
throw new Unauthorized();
|
|
327
|
+
}
|
|
328
|
+
return originalSave({ input, ctx, fields, ...restOpts });
|
|
329
|
+
}
|
|
330
|
+
return originalSave({ input, ctx, fields, ...restOpts });
|
|
331
|
+
},
|
|
332
|
+
async insert(originalInsert, { inputs, ctx, fields, ...restOpts }) {
|
|
333
|
+
if (useOriginal(ctx)) {
|
|
334
|
+
return originalInsert({ inputs, ctx, fields, ...restOpts });
|
|
335
|
+
}
|
|
336
|
+
const request = getRequestFromContext(ctx);
|
|
337
|
+
const rule = await findRuleForRequestUser(ctx, rules2, roleKey, anonymousRole, isRolePath);
|
|
338
|
+
if (!rule.save) {
|
|
339
|
+
throw new Unauthorized();
|
|
340
|
+
}
|
|
341
|
+
checkFieldsFromRule(rule.save, fields);
|
|
342
|
+
checkInputFromRuleFields(rule.save, inputs);
|
|
343
|
+
if (rule.defaults) {
|
|
344
|
+
for (const input of inputs) {
|
|
345
|
+
for (const key of Object.keys(rule.defaults)) {
|
|
346
|
+
const defaults = rule.defaults[key];
|
|
347
|
+
if (typeof defaults === "function") {
|
|
348
|
+
input[key] = await defaults({ user: request.user, ctx, input });
|
|
349
|
+
} else {
|
|
350
|
+
input[key] = request.user[defaults];
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return originalInsert({ inputs, ctx, fields, ...restOpts });
|
|
356
|
+
},
|
|
357
|
+
async delete(originalDelete, { where, ctx, fields, ...restOpts }) {
|
|
358
|
+
if (useOriginal(ctx)) {
|
|
359
|
+
return originalDelete({ where, ctx, fields, ...restOpts });
|
|
360
|
+
}
|
|
361
|
+
const request = getRequestFromContext(ctx);
|
|
362
|
+
const rule = await findRuleForRequestUser(ctx, rules2, roleKey, anonymousRole, isRolePath);
|
|
363
|
+
where = await fromRuleToWhere(ctx, rule.delete, where, request.user);
|
|
364
|
+
return originalDelete({ where, ctx, fields, ...restOpts });
|
|
365
|
+
},
|
|
366
|
+
async updateMany(originalUpdateMany, { where, ctx, fields, ...restOpts }) {
|
|
367
|
+
if (useOriginal(ctx)) {
|
|
368
|
+
return originalUpdateMany({ ...restOpts, where, ctx, fields });
|
|
369
|
+
}
|
|
370
|
+
const request = getRequestFromContext(ctx);
|
|
371
|
+
const rule = await findRuleForRequestUser(ctx, rules2, roleKey, anonymousRole, isRolePath);
|
|
372
|
+
where = await fromRuleToWhere(ctx, rule.updateMany, where, request.user);
|
|
373
|
+
return originalUpdateMany({ ...restOpts, where, ctx, fields });
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
}, { name: "@albirex/platformatic-logto" });
|
|
379
|
+
async function fromRuleToWhere(ctx, rule, where, user) {
|
|
380
|
+
if (!rule) {
|
|
381
|
+
throw new Unauthorized();
|
|
382
|
+
}
|
|
383
|
+
const request = getRequestFromContext(ctx);
|
|
384
|
+
where = where || {};
|
|
385
|
+
if (typeof rule === "object") {
|
|
386
|
+
const { checks } = rule;
|
|
387
|
+
if (checks) {
|
|
388
|
+
for (const key of Object.keys(checks)) {
|
|
389
|
+
const clauses = checks[key];
|
|
390
|
+
if (typeof clauses === "string") {
|
|
391
|
+
where[key] = {
|
|
392
|
+
eq: request.user[clauses]
|
|
393
|
+
};
|
|
394
|
+
} else {
|
|
395
|
+
for (const clauseKey of Object.keys(clauses)) {
|
|
396
|
+
const clause = clauses[clauseKey];
|
|
397
|
+
where[key] = {
|
|
398
|
+
[clauseKey]: request.user[clause]
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
} else if (typeof rule === "function") {
|
|
405
|
+
where = await rule({ user, ctx, where });
|
|
406
|
+
}
|
|
407
|
+
return where;
|
|
408
|
+
}
|
|
409
|
+
async function findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath = false) {
|
|
410
|
+
const request = getRequestFromContext(ctx);
|
|
411
|
+
await request.setupDBAuthorizationUser();
|
|
412
|
+
const roles = getRoles(request, roleKey, anonymousRole, isRolePath);
|
|
413
|
+
const rule = find_rule_default(rules, roles);
|
|
414
|
+
if (!rule) {
|
|
415
|
+
ctx.reply.request.log.warn({ roles, rules }, "no rule for roles");
|
|
416
|
+
throw new Unauthorized();
|
|
417
|
+
}
|
|
418
|
+
ctx.reply.request.log.trace({ roles, rule }, "found rule");
|
|
419
|
+
return rule;
|
|
420
|
+
}
|
|
421
|
+
function checkFieldsFromRule(rule, fields) {
|
|
422
|
+
if (!rule) {
|
|
423
|
+
throw new Unauthorized();
|
|
424
|
+
}
|
|
425
|
+
const { fields: fieldsFromRule } = rule;
|
|
426
|
+
if (fieldsFromRule) {
|
|
427
|
+
for (const field of fields) {
|
|
428
|
+
if (!fieldsFromRule.includes(field)) {
|
|
429
|
+
throw new UnauthorizedField(field);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
var validateInputs = (inputs, fieldsFromRule) => {
|
|
435
|
+
for (const input of inputs) {
|
|
436
|
+
const inputFields = Object.keys(input);
|
|
437
|
+
for (const inputField of inputFields) {
|
|
438
|
+
if (!fieldsFromRule.includes(inputField)) {
|
|
439
|
+
throw new UnauthorizedField(inputField);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
function checkInputFromRuleFields(rule, inputs) {
|
|
445
|
+
const { fields: fieldsFromRule } = rule;
|
|
446
|
+
if (fieldsFromRule) {
|
|
447
|
+
if (!Array.isArray(inputs)) {
|
|
448
|
+
validateInputs([inputs], fieldsFromRule);
|
|
449
|
+
} else {
|
|
450
|
+
validateInputs(inputs, fieldsFromRule);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
function checkSaveMandatoryFieldsInRules(type, rules) {
|
|
455
|
+
const mandatoryFields = Object.values(type.fields).filter((k) => !k.isNullable && !k.primaryKey).map(({ camelcase }) => camelcase);
|
|
456
|
+
for (const rule of rules) {
|
|
457
|
+
const { entity, save } = rule;
|
|
458
|
+
if (save && save.fields) {
|
|
459
|
+
const fields = save.fields;
|
|
460
|
+
for (const mField of mandatoryFields) {
|
|
461
|
+
if (!fields.includes(mField)) {
|
|
462
|
+
throw new MissingNotNullableError(mField, entity);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
var index_default = platformaticLogto;
|
|
469
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
470
|
+
0 && (module.exports = {
|
|
471
|
+
fastifyLogto,
|
|
472
|
+
platformaticLogto
|
|
473
|
+
});
|
|
474
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils/find-rule.ts","../src/utils/utils.ts","../src/utils/errors.ts"],"sourcesContent":["import fp from 'fastify-plugin'\nimport * as fastifyUser from 'fastify-user'\n\nimport findRule from './utils/find-rule.js'\nimport { getRequestFromContext, getRoles } from './utils/utils.js'\nimport { Unauthorized, UnauthorizedField, MissingNotNullableError } from './utils/errors.js'\nimport fastifyLogto from '@albirex/fastify-logto';\nimport { FastifyInstance, FastifyPluginAsync } from 'fastify'\nimport type { FastifyUserPluginOptions } from 'fastify-user';\nimport type { Entity, PlatformaticContext } from '@platformatic/sql-mapper'\nexport { fastifyLogto } from '@albirex/fastify-logto';\n\nconst PLT_ADMIN_ROLE = 'platformatic-admin'\n\nexport type PlatformaticRule = {\n role: string;\n entity?: string;\n entities?: string[];\n defaults?: Record<string, string>;\n checks?: boolean;\n find?: boolean;\n save?: boolean;\n delete?: boolean;\n\n};\n\nexport type PlatformaticLogtoAuthOptions = {\n logtoBaseUrl?: string;\n logtoAppId?: string;\n logtoAppSecret?: string;\n adminSecret?: string;\n rolePath?: string;\n roleKey?: string;\n userPath?: string;\n userKey?: string;\n anonymousRole?: string;\n allowAnonymous?: boolean;\n checks?: boolean;\n defaults?: boolean;\n jwtPlugin: FastifyUserPluginOptions\n};\n\nexport const platformaticLogto: FastifyPluginAsync<PlatformaticLogtoAuthOptions> = fp(async (app: FastifyInstance, opts: PlatformaticLogtoAuthOptions) => {\n app.register(fastifyLogto, {\n endpoint: opts.logtoBaseUrl || 'https://auth.example.com',\n appId: opts.logtoAppId || 'your-app-id',\n appSecret: opts.logtoAppSecret || 'your-app-secret',\n });\n\n await app.register(fastifyUser as unknown as FastifyPluginAsync, opts.jwtPlugin);\n\n const adminSecret = opts.adminSecret\n const roleKey = opts.rolePath || opts.roleKey || 'X-PLATFORMATIC-ROLE'\n const userKey = opts.userPath || opts.userKey || 'X-PLATFORMATIC-USER-ID'\n const isRolePath = !!opts.rolePath // if `true` the role is intepreted as path like `user.role`\n const anonymousRole = opts.anonymousRole || 'anonymous'\n\n async function composeLogToRules() {\n const rolesResp = await app.logto.callAPI('/api/roles?type=User', 'GET');\n\n if (!rolesResp.ok) {\n throw rolesResp;\n }\n\n const roles = await rolesResp.json();\n const rules: PlatformaticRule[] = [{\n role: anonymousRole,\n entities: Object.keys(app.platformatic.entities),\n find: opts.allowAnonymous,\n save: opts.allowAnonymous,\n delete: opts.allowAnonymous,\n }];\n\n for (const role of roles) {\n const scopesResp = await app.logto.callAPI(`/api/roles/${role.id}/scopes`, 'GET');\n\n if (!scopesResp.ok) {\n throw scopesResp;\n }\n\n const scopes = await scopesResp.json();\n\n for (const scope of scopes) {\n const roleName = role.name;\n // eslint-disable-next-line prefer-const\n let [scopeAction, entity] = scope.name.split(':');\n\n if (!app.platformatic.entities[entity]) {\n app.log.debug(`Unknown entity '${entity}' in authorization rule`)\n continue;\n }\n\n switch (scopeAction) {\n case 'create':\n scopeAction = 'save'\n break;\n case 'read':\n scopeAction = 'find'\n break;\n case 'update':\n scopeAction = 'updateMany'\n break;\n }\n\n const checkExists = rules.find(r => r.role === roleName && r.entity === entity);\n if (checkExists) {\n if (opts.checks) {\n checkExists[scopeAction] = {\n checks: {\n userId: userKey\n }\n };\n } else {\n checkExists[scopeAction] = true;\n }\n } else {\n const newRule: PlatformaticRule = {\n role: roleName,\n entity,\n };\n\n if (opts.checks) {\n newRule[scopeAction] = {\n checks: {\n userId: userKey\n }\n };\n } else {\n newRule[scopeAction] = true;\n }\n\n if (opts.defaults) {\n newRule.defaults = {\n userId: userKey\n };\n }\n\n rules.push(newRule);\n }\n }\n }\n\n const logRules = rules.reduce((prev, curr) => {\n (prev[curr['role']] ??= []).push(curr);\n return prev;\n }, {})\n\n for (const key in logRules) {\n app.log.info(`Rules set for role ${key}`);\n\n for (const element of logRules[key]) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { entity, entities, role, ...other } = element;\n app.log.info(`\\t${entity ?? entities.join(',')}: ${JSON.stringify(other)}`);\n }\n }\n\n const missingEntities = Object.keys(app.platformatic.entities).filter((e) => !rules.map((r) => r.entity).includes(e));\n\n if (missingEntities.length) {\n app.log.warn(`Missing rules for entities: ${missingEntities.join(', ')}`);\n }\n\n app.log.debug('LogTo calculated rules');\n app.log.debug(rules);\n return rules;\n }\n\n app.decorateRequest('setupDBAuthorizationUser', setupUser)\n\n async function setupUser() {\n // if (!adminSecret) {\n await this.extractUser()\n // }\n\n let forceAdminRole = false\n if (adminSecret && this.headers['x-platformatic-admin-secret'] === adminSecret) {\n if (opts.jwtPlugin.jwt) {\n forceAdminRole = true\n } else {\n this.log.info('admin secret is valid')\n this.user = new Proxy(this.headers, {\n get: (target, key) => {\n let value;\n if (!target[key.toString()]) {\n const newKey = key.toString().toLowerCase()\n value = target[newKey]\n } else {\n value = target[key.toString()]\n }\n\n if (!value && key.toString().toLowerCase() === roleKey.toLowerCase()) {\n value = PLT_ADMIN_ROLE\n }\n return value\n },\n })\n }\n }\n\n if (forceAdminRole) {\n // We replace just the role in `request.user`, all the rest is untouched\n this.user = {\n // ...request.user,\n [roleKey]: PLT_ADMIN_ROLE,\n }\n }\n }\n\n app.addHook('onReady', async function () {\n const rules = await composeLogToRules();\n\n // TODO validate that there is at most a rule for a given role\n const entityRules = {};\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i]\n\n let ruleEntities = null\n if (rule.entity) {\n ruleEntities = [rule.entity]\n } else if (rule.entities) {\n ruleEntities = [...rule.entities]\n } else {\n throw new Error(`Missing entity in authorization rule ${i}`)\n }\n\n for (const ruleEntity of ruleEntities) {\n const newRule = { ...rule, entity: ruleEntity, entities: undefined }\n if (!app.platformatic.entities[newRule.entity]) {\n throw new Error(`Unknown entity '${ruleEntity}' in authorization rule ${i}`)\n }\n\n if (!entityRules[ruleEntity]) {\n entityRules[ruleEntity] = []\n }\n entityRules[ruleEntity].push(newRule)\n }\n }\n\n for (const entityKey of Object.keys(app.platformatic.entities)) {\n const rules = entityRules[entityKey] || []\n const type = app.platformatic.entities[entityKey]\n\n // We have subscriptions!\n let userPropToFillForPublish\n const topicsWithoutChecks = false\n\n // mqtt\n // if (app.platformatic.mq) {\n // for (const rule of rules) {\n // const checks = rule.find?.checks\n // if (typeof checks !== 'object') {\n // topicsWithoutChecks = !!rule.find\n // continue\n // }\n // const keys = Object.keys(checks)\n // if (keys.length !== 1) {\n // throw new Error(`Subscription requires that the role \"${rule.role}\" has only one check in the find rule for entity \"${rule.entity}\"`)\n // }\n // const key = keys[0]\n\n // const val = typeof checks[key] === 'object' ? checks[key].eq : checks[key]\n // if (userPropToFillForPublish && userPropToFillForPublish.val !== val) {\n // throw new Error('Unable to configure subscriptions and authorization due to multiple check clauses in find')\n // }\n // userPropToFillForPublish = { key, val }\n // }\n // }\n\n if (userPropToFillForPublish && topicsWithoutChecks) {\n throw new Error(`Subscription for entity \"${entityKey}\" have conflictling rules across roles`)\n }\n\n // MUST set this after doing the security checks on the subscriptions\n if (adminSecret) {\n rules.push({\n role: PLT_ADMIN_ROLE,\n find: true,\n save: true,\n delete: true,\n })\n }\n\n // If we have `fields` in save rules, we need to check if all the not-nullable\n // fields are specified\n checkSaveMandatoryFieldsInRules(type, rules)\n\n function useOriginal(ctx: PlatformaticContext) {\n return !ctx\n }\n\n app.platformatic.addEntityHooks(entityKey, {\n async find(originalFind, { where, ctx, fields, ...restOpts } = {}) {\n if (useOriginal(ctx)) {\n return originalFind({ ...restOpts, where, ctx, fields })\n }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n checkFieldsFromRule(rule.find, fields || Object.keys(app.platformatic.entities[entityKey].fields))\n where = await fromRuleToWhere(ctx, rule.find, where, request.user)\n\n return originalFind({ ...restOpts, where, ctx, fields })\n },\n async save(originalSave, { input, ctx, fields, ...restOpts }) {\n if (useOriginal(ctx)) {\n return originalSave({ ctx, input, fields, ...restOpts })\n }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n\n if (!rule.save) {\n throw new Unauthorized()\n }\n checkFieldsFromRule(rule.save, fields)\n checkInputFromRuleFields(rule.save, input)\n\n if (rule.defaults) {\n for (const key of Object.keys(rule.defaults)) {\n const defaults = rule.defaults[key]\n if (typeof defaults === 'function') {\n input[key] = await defaults({ user: request.user, ctx, input })\n } else {\n input[key] = request.user[defaults]\n }\n }\n }\n\n const hasAllPrimaryKeys = input[type.primaryKey] !== undefined;\n const whereConditions = {}\n whereConditions[type.primaryKey] = { eq: input[type.primaryKey] }\n\n if (hasAllPrimaryKeys) {\n const where = await fromRuleToWhere(ctx, rule.save, whereConditions, request.user)\n\n const found = await type.find({\n where,\n ctx,\n fields,\n })\n\n if (found.length === 0) {\n throw new Unauthorized()\n }\n\n return originalSave({ input, ctx, fields, ...restOpts })\n }\n\n return originalSave({ input, ctx, fields, ...restOpts })\n },\n\n async insert(originalInsert, { inputs, ctx, fields, ...restOpts }) {\n if (useOriginal(ctx)) {\n return originalInsert({ inputs, ctx, fields, ...restOpts })\n }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n\n if (!rule.save) {\n throw new Unauthorized()\n }\n\n checkFieldsFromRule(rule.save, fields)\n checkInputFromRuleFields(rule.save, inputs)\n\n /* istanbul ignore else */\n if (rule.defaults) {\n for (const input of inputs) {\n for (const key of Object.keys(rule.defaults)) {\n const defaults = rule.defaults[key]\n if (typeof defaults === 'function') {\n input[key] = await defaults({ user: request.user, ctx, input })\n } else {\n input[key] = request.user[defaults]\n }\n }\n }\n }\n\n return originalInsert({ inputs, ctx, fields, ...restOpts })\n },\n\n async delete(originalDelete, { where, ctx, fields, ...restOpts }) {\n if (useOriginal(ctx)) {\n return originalDelete({ where, ctx, fields, ...restOpts })\n }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n\n where = await fromRuleToWhere(ctx, rule.delete, where, request.user)\n\n return originalDelete({ where, ctx, fields, ...restOpts })\n },\n\n async updateMany(originalUpdateMany, { where, ctx, fields, ...restOpts }) {\n if (useOriginal(ctx)) {\n return originalUpdateMany({ ...restOpts, where, ctx, fields })\n }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n\n where = await fromRuleToWhere(ctx, rule.updateMany, where, request.user)\n\n return originalUpdateMany({ ...restOpts, where, ctx, fields })\n },\n })\n }\n })\n}, { name: '@albirex/platformatic-logto' });\n\nasync function fromRuleToWhere(ctx: PlatformaticContext, rule, where, user) {\n if (!rule) {\n throw new Unauthorized()\n }\n const request = getRequestFromContext(ctx)\n /* istanbul ignore next */\n where = where || {}\n\n if (typeof rule === 'object') {\n const { checks } = rule\n\n /* istanbul ignore else */\n if (checks) {\n for (const key of Object.keys(checks)) {\n const clauses = checks[key]\n if (typeof clauses === 'string') {\n // case: \"userId\": \"X-PLATFORMATIC-USER-ID\"\n where[key] = {\n eq: request.user[clauses],\n }\n } else {\n // case:\n // userId: {\n // eq: 'X-PLATFORMATIC-USER-ID'\n // }\n for (const clauseKey of Object.keys(clauses)) {\n const clause = clauses[clauseKey]\n where[key] = {\n [clauseKey]: request.user[clause],\n }\n }\n }\n }\n }\n } else if (typeof rule === 'function') {\n where = await rule({ user, ctx, where })\n }\n return where\n}\n\nasync function findRuleForRequestUser(ctx: PlatformaticContext, rules: PlatformaticRule[], roleKey: string, anonymousRole: string, isRolePath = false) {\n const request = getRequestFromContext(ctx)\n await request.setupDBAuthorizationUser()\n const roles = getRoles(request, roleKey, anonymousRole, isRolePath)\n const rule = findRule(rules, roles)\n if (!rule) {\n ctx.reply.request.log.warn({ roles, rules }, 'no rule for roles')\n throw new Unauthorized()\n }\n ctx.reply.request.log.trace({ roles, rule }, 'found rule')\n return rule\n}\n\nfunction checkFieldsFromRule(rule, fields) {\n if (!rule) {\n throw new Unauthorized()\n }\n const { fields: fieldsFromRule } = rule\n /* istanbul ignore else */\n if (fieldsFromRule) {\n for (const field of fields) {\n if (!fieldsFromRule.includes(field)) {\n throw new UnauthorizedField(field)\n }\n }\n }\n}\n\nconst validateInputs = (inputs, fieldsFromRule) => {\n for (const input of inputs) {\n const inputFields = Object.keys(input)\n for (const inputField of inputFields) {\n if (!fieldsFromRule.includes(inputField)) {\n throw new UnauthorizedField(inputField)\n }\n }\n }\n}\n\nfunction checkInputFromRuleFields(rule, inputs) {\n const { fields: fieldsFromRule } = rule\n /* istanbul ignore else */\n if (fieldsFromRule) {\n if (!Array.isArray(inputs)) {\n // save\n validateInputs([inputs], fieldsFromRule)\n } else {\n // insert\n validateInputs(inputs, fieldsFromRule)\n }\n }\n}\n\nfunction checkSaveMandatoryFieldsInRules(type: Entity, rules) {\n // List of not nullable, not PKs field to validate save/insert when allowed fields are specified on the rule\n const mandatoryFields =\n Object.values(type.fields)\n .filter(k => (!k.isNullable && !k.primaryKey))\n .map(({ camelcase }) => (camelcase))\n\n for (const rule of rules) {\n const { entity, save } = rule\n if (save && save.fields) {\n const fields = save.fields\n for (const mField of mandatoryFields) {\n if (!fields.includes(mField)) {\n throw new MissingNotNullableError(mField, entity)\n }\n }\n }\n }\n}\n\nexport default platformaticLogto;\n","'use strict'\n\nimport { PlatformaticRule } from '../index.js'\n\nfunction findRule(rules: PlatformaticRule[], roles: string[]) {\n let found = null\n for (const rule of rules) {\n for (const role of roles) {\n if (rule.role === role) {\n found = rule\n break\n }\n }\n if (found) {\n break\n }\n }\n return found\n}\n\nexport default findRule\n","'use strict'\n\nexport function getRequestFromContext (ctx) {\n if (ctx && !ctx.reply) {\n throw new Error('Missing reply in context. You should call this function with { ctx: { reply }}')\n }\n return ctx.reply.request\n}\n\nexport function getRoles (request, roleKey, anonymousRole, isRolePath = false) {\n let output = []\n const user = request.user\n if (!user) {\n output.push(anonymousRole)\n return output\n }\n\n let rolesRaw\n if (isRolePath) {\n const roleKeys = roleKey.split('.')\n rolesRaw = user\n for (const key of roleKeys) {\n rolesRaw = rolesRaw[key]\n }\n } else {\n rolesRaw = user[roleKey]\n }\n\n if (typeof rolesRaw === 'string') {\n output = rolesRaw.split(',')\n } else if (Array.isArray(rolesRaw)) {\n output = rolesRaw\n }\n if (output.length === 0) {\n output.push(anonymousRole)\n }\n\n return output\n}\n","'use strict'\n\nimport createError from '@fastify/error'\n\nconst ERROR_PREFIX = 'PLT_DB_AUTH'\n\nexport const Unauthorized = createError(`${ERROR_PREFIX}_UNAUTHORIZED`, 'operation not allowed', 401)\nexport const UnauthorizedField = createError(`${ERROR_PREFIX}_FIELD_UNAUTHORIZED`, 'field not allowed: %s', 401)\nexport const MissingNotNullableError = createError(`${ERROR_PREFIX}_NOT_NULLABLE_MISSING`, 'missing not nullable field: \"%s\" in save rule for entity \"%s\"')\n"],"mappings":"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","names":["createError","import_fastify_logto","fp","fastifyLogto","rules"]}
|
package/lib/index.d.cts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { FastifyPluginAsync } from 'fastify';
|
|
2
|
+
import { FastifyUserPluginOptions } from 'fastify-user';
|
|
3
|
+
export { fastifyLogto } from '@albirex/fastify-logto';
|
|
4
|
+
|
|
5
|
+
type PlatformaticRule = {
|
|
6
|
+
role: string;
|
|
7
|
+
entity?: string;
|
|
8
|
+
entities?: string[];
|
|
9
|
+
defaults?: Record<string, string>;
|
|
10
|
+
checks?: boolean;
|
|
11
|
+
find?: boolean;
|
|
12
|
+
save?: boolean;
|
|
13
|
+
delete?: boolean;
|
|
14
|
+
};
|
|
15
|
+
type PlatformaticLogtoAuthOptions = {
|
|
16
|
+
logtoBaseUrl?: string;
|
|
17
|
+
logtoAppId?: string;
|
|
18
|
+
logtoAppSecret?: string;
|
|
19
|
+
adminSecret?: string;
|
|
20
|
+
rolePath?: string;
|
|
21
|
+
roleKey?: string;
|
|
22
|
+
userPath?: string;
|
|
23
|
+
userKey?: string;
|
|
24
|
+
anonymousRole?: string;
|
|
25
|
+
allowAnonymous?: boolean;
|
|
26
|
+
checks?: boolean;
|
|
27
|
+
defaults?: boolean;
|
|
28
|
+
jwtPlugin: FastifyUserPluginOptions;
|
|
29
|
+
};
|
|
30
|
+
declare const platformaticLogto: FastifyPluginAsync<PlatformaticLogtoAuthOptions>;
|
|
31
|
+
|
|
32
|
+
export { type PlatformaticLogtoAuthOptions, type PlatformaticRule, platformaticLogto as default, platformaticLogto };
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FastifyPluginAsync } from 'fastify';
|
|
2
2
|
import { FastifyUserPluginOptions } from 'fastify-user';
|
|
3
|
+
export { fastifyLogto } from '@albirex/fastify-logto';
|
|
3
4
|
|
|
4
5
|
type PlatformaticRule = {
|
|
5
6
|
role: string;
|
|
@@ -26,6 +27,6 @@ type PlatformaticLogtoAuthOptions = {
|
|
|
26
27
|
defaults?: boolean;
|
|
27
28
|
jwtPlugin: FastifyUserPluginOptions;
|
|
28
29
|
};
|
|
29
|
-
declare const
|
|
30
|
+
declare const platformaticLogto: FastifyPluginAsync<PlatformaticLogtoAuthOptions>;
|
|
30
31
|
|
|
31
|
-
export { type PlatformaticLogtoAuthOptions, type PlatformaticRule,
|
|
32
|
+
export { type PlatformaticLogtoAuthOptions, type PlatformaticRule, platformaticLogto as default, platformaticLogto };
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import fp from "fastify-plugin";
|
|
3
|
-
import leven from "leven";
|
|
4
3
|
import * as fastifyUser from "fastify-user";
|
|
5
4
|
|
|
6
5
|
// src/utils/find-rule.ts
|
|
@@ -65,8 +64,9 @@ var MissingNotNullableError = createError(`${ERROR_PREFIX}_NOT_NULLABLE_MISSING`
|
|
|
65
64
|
|
|
66
65
|
// src/index.ts
|
|
67
66
|
import fastifyLogto from "@albirex/fastify-logto";
|
|
67
|
+
import { fastifyLogto as fastifyLogto2 } from "@albirex/fastify-logto";
|
|
68
68
|
var PLT_ADMIN_ROLE = "platformatic-admin";
|
|
69
|
-
var
|
|
69
|
+
var platformaticLogto = fp(async (app, opts) => {
|
|
70
70
|
app.register(fastifyLogto, {
|
|
71
71
|
endpoint: opts.logtoBaseUrl || "https://auth.example.com",
|
|
72
72
|
appId: opts.logtoAppId || "your-app-id",
|
|
@@ -99,12 +99,22 @@ var auth = async (app, opts) => {
|
|
|
99
99
|
const scopes = await scopesResp.json();
|
|
100
100
|
for (const scope of scopes) {
|
|
101
101
|
const roleName = role.name;
|
|
102
|
-
|
|
102
|
+
let [scopeAction, entity] = scope.name.split(":");
|
|
103
103
|
if (!app.platformatic.entities[entity]) {
|
|
104
|
-
|
|
105
|
-
app.log.warn(`Unknown entity '${entity}' in authorization rule. Did you mean '${nearest.entity}'?`);
|
|
104
|
+
app.log.debug(`Unknown entity '${entity}' in authorization rule`);
|
|
106
105
|
continue;
|
|
107
106
|
}
|
|
107
|
+
switch (scopeAction) {
|
|
108
|
+
case "create":
|
|
109
|
+
scopeAction = "save";
|
|
110
|
+
break;
|
|
111
|
+
case "read":
|
|
112
|
+
scopeAction = "find";
|
|
113
|
+
break;
|
|
114
|
+
case "update":
|
|
115
|
+
scopeAction = "updateMany";
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
108
118
|
const checkExists = rules.find((r) => r.role === roleName && r.entity === entity);
|
|
109
119
|
if (checkExists) {
|
|
110
120
|
if (opts.checks) {
|
|
@@ -139,6 +149,21 @@ var auth = async (app, opts) => {
|
|
|
139
149
|
}
|
|
140
150
|
}
|
|
141
151
|
}
|
|
152
|
+
const logRules = rules.reduce((prev, curr) => {
|
|
153
|
+
(prev[curr["role"]] ??= []).push(curr);
|
|
154
|
+
return prev;
|
|
155
|
+
}, {});
|
|
156
|
+
for (const key in logRules) {
|
|
157
|
+
app.log.info(`Rules set for role ${key}`);
|
|
158
|
+
for (const element of logRules[key]) {
|
|
159
|
+
const { entity, entities, role, ...other } = element;
|
|
160
|
+
app.log.info(` ${entity ?? entities.join(",")}: ${JSON.stringify(other)}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const missingEntities = Object.keys(app.platformatic.entities).filter((e) => !rules.map((r) => r.entity).includes(e));
|
|
164
|
+
if (missingEntities.length) {
|
|
165
|
+
app.log.warn(`Missing rules for entities: ${missingEntities.join(", ")}`);
|
|
166
|
+
}
|
|
142
167
|
app.log.debug("LogTo calculated rules");
|
|
143
168
|
app.log.debug(rules);
|
|
144
169
|
return rules;
|
|
@@ -176,18 +201,6 @@ var auth = async (app, opts) => {
|
|
|
176
201
|
};
|
|
177
202
|
}
|
|
178
203
|
}
|
|
179
|
-
function findNearestEntity(ruleEntity) {
|
|
180
|
-
const entities = Object.keys(app.platformatic.entities);
|
|
181
|
-
const nearest = entities.reduce((acc, entity) => {
|
|
182
|
-
const distance = leven(ruleEntity, entity);
|
|
183
|
-
if (distance < acc.distance) {
|
|
184
|
-
acc.distance = distance;
|
|
185
|
-
acc.entity = entity;
|
|
186
|
-
}
|
|
187
|
-
return acc;
|
|
188
|
-
}, { distance: Infinity, entity: null });
|
|
189
|
-
return nearest;
|
|
190
|
-
}
|
|
191
204
|
app.addHook("onReady", async function() {
|
|
192
205
|
const rules = await composeLogToRules();
|
|
193
206
|
const entityRules = {};
|
|
@@ -204,8 +217,7 @@ var auth = async (app, opts) => {
|
|
|
204
217
|
for (const ruleEntity of ruleEntities) {
|
|
205
218
|
const newRule = { ...rule, entity: ruleEntity, entities: void 0 };
|
|
206
219
|
if (!app.platformatic.entities[newRule.entity]) {
|
|
207
|
-
|
|
208
|
-
throw new Error(`Unknown entity '${ruleEntity}' in authorization rule ${i}. Did you mean '${nearest.entity}'?`);
|
|
220
|
+
throw new Error(`Unknown entity '${ruleEntity}' in authorization rule ${i}`);
|
|
209
221
|
}
|
|
210
222
|
if (!entityRules[ruleEntity]) {
|
|
211
223
|
entityRules[ruleEntity] = [];
|
|
@@ -214,6 +226,9 @@ var auth = async (app, opts) => {
|
|
|
214
226
|
}
|
|
215
227
|
}
|
|
216
228
|
for (const entityKey of Object.keys(app.platformatic.entities)) {
|
|
229
|
+
let useOriginal = function(ctx) {
|
|
230
|
+
return !ctx;
|
|
231
|
+
};
|
|
217
232
|
const rules2 = entityRules[entityKey] || [];
|
|
218
233
|
const type = app.platformatic.entities[entityKey];
|
|
219
234
|
let userPropToFillForPublish;
|
|
@@ -232,6 +247,9 @@ var auth = async (app, opts) => {
|
|
|
232
247
|
checkSaveMandatoryFieldsInRules(type, rules2);
|
|
233
248
|
app.platformatic.addEntityHooks(entityKey, {
|
|
234
249
|
async find(originalFind, { where, ctx, fields, ...restOpts } = {}) {
|
|
250
|
+
if (useOriginal(ctx)) {
|
|
251
|
+
return originalFind({ ...restOpts, where, ctx, fields });
|
|
252
|
+
}
|
|
235
253
|
const request = getRequestFromContext(ctx);
|
|
236
254
|
const rule = await findRuleForRequestUser(ctx, rules2, roleKey, anonymousRole, isRolePath);
|
|
237
255
|
checkFieldsFromRule(rule.find, fields || Object.keys(app.platformatic.entities[entityKey].fields));
|
|
@@ -239,6 +257,9 @@ var auth = async (app, opts) => {
|
|
|
239
257
|
return originalFind({ ...restOpts, where, ctx, fields });
|
|
240
258
|
},
|
|
241
259
|
async save(originalSave, { input, ctx, fields, ...restOpts }) {
|
|
260
|
+
if (useOriginal(ctx)) {
|
|
261
|
+
return originalSave({ ctx, input, fields, ...restOpts });
|
|
262
|
+
}
|
|
242
263
|
const request = getRequestFromContext(ctx);
|
|
243
264
|
const rule = await findRuleForRequestUser(ctx, rules2, roleKey, anonymousRole, isRolePath);
|
|
244
265
|
if (!rule.save) {
|
|
@@ -274,6 +295,9 @@ var auth = async (app, opts) => {
|
|
|
274
295
|
return originalSave({ input, ctx, fields, ...restOpts });
|
|
275
296
|
},
|
|
276
297
|
async insert(originalInsert, { inputs, ctx, fields, ...restOpts }) {
|
|
298
|
+
if (useOriginal(ctx)) {
|
|
299
|
+
return originalInsert({ inputs, ctx, fields, ...restOpts });
|
|
300
|
+
}
|
|
277
301
|
const request = getRequestFromContext(ctx);
|
|
278
302
|
const rule = await findRuleForRequestUser(ctx, rules2, roleKey, anonymousRole, isRolePath);
|
|
279
303
|
if (!rule.save) {
|
|
@@ -296,12 +320,18 @@ var auth = async (app, opts) => {
|
|
|
296
320
|
return originalInsert({ inputs, ctx, fields, ...restOpts });
|
|
297
321
|
},
|
|
298
322
|
async delete(originalDelete, { where, ctx, fields, ...restOpts }) {
|
|
323
|
+
if (useOriginal(ctx)) {
|
|
324
|
+
return originalDelete({ where, ctx, fields, ...restOpts });
|
|
325
|
+
}
|
|
299
326
|
const request = getRequestFromContext(ctx);
|
|
300
327
|
const rule = await findRuleForRequestUser(ctx, rules2, roleKey, anonymousRole, isRolePath);
|
|
301
328
|
where = await fromRuleToWhere(ctx, rule.delete, where, request.user);
|
|
302
329
|
return originalDelete({ where, ctx, fields, ...restOpts });
|
|
303
330
|
},
|
|
304
331
|
async updateMany(originalUpdateMany, { where, ctx, fields, ...restOpts }) {
|
|
332
|
+
if (useOriginal(ctx)) {
|
|
333
|
+
return originalUpdateMany({ ...restOpts, where, ctx, fields });
|
|
334
|
+
}
|
|
305
335
|
const request = getRequestFromContext(ctx);
|
|
306
336
|
const rule = await findRuleForRequestUser(ctx, rules2, roleKey, anonymousRole, isRolePath);
|
|
307
337
|
where = await fromRuleToWhere(ctx, rule.updateMany, where, request.user);
|
|
@@ -310,7 +340,7 @@ var auth = async (app, opts) => {
|
|
|
310
340
|
});
|
|
311
341
|
}
|
|
312
342
|
});
|
|
313
|
-
};
|
|
343
|
+
}, { name: "@albirex/platformatic-logto" });
|
|
314
344
|
async function fromRuleToWhere(ctx, rule, where, user) {
|
|
315
345
|
if (!rule) {
|
|
316
346
|
throw new Unauthorized();
|
|
@@ -400,8 +430,10 @@ function checkSaveMandatoryFieldsInRules(type, rules) {
|
|
|
400
430
|
}
|
|
401
431
|
}
|
|
402
432
|
}
|
|
403
|
-
var index_default =
|
|
433
|
+
var index_default = platformaticLogto;
|
|
404
434
|
export {
|
|
405
|
-
index_default as default
|
|
435
|
+
index_default as default,
|
|
436
|
+
fastifyLogto2 as fastifyLogto,
|
|
437
|
+
platformaticLogto
|
|
406
438
|
};
|
|
407
439
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/utils/find-rule.ts","../src/utils/utils.ts","../src/utils/errors.ts"],"sourcesContent":["import fp from 'fastify-plugin'\nimport leven from 'leven'\nimport * as fastifyUser from 'fastify-user'\n\nimport findRule from './utils/find-rule.js'\nimport { getRequestFromContext, getRoles } from './utils/utils.js'\nimport { Unauthorized, UnauthorizedField, MissingNotNullableError } from './utils/errors.js'\nimport fastifyLogto from '@albirex/fastify-logto';\nimport { FastifyInstance, FastifyPluginAsync } from 'fastify'\nimport type { FastifyUserPluginOptions } from 'fastify-user';\nimport type { Entity, PlatformaticContext } from '@platformatic/sql-mapper'\n\nconst PLT_ADMIN_ROLE = 'platformatic-admin'\n\nexport type PlatformaticRule = {\n role: string;\n entity?: string;\n entities?: string[];\n defaults?: Record<string, string>;\n checks?: boolean;\n find?: boolean;\n save?: boolean;\n delete?: boolean;\n\n};\n\nexport type PlatformaticLogtoAuthOptions = {\n logtoBaseUrl?: string;\n logtoAppId?: string;\n logtoAppSecret?: string;\n adminSecret?: string;\n rolePath?: string;\n roleKey?: string;\n userPath?: string;\n userKey?: string;\n anonymousRole?: string;\n allowAnonymous?: boolean;\n checks?: boolean;\n defaults?: boolean;\n jwtPlugin: FastifyUserPluginOptions\n};\n\nconst auth: FastifyPluginAsync<PlatformaticLogtoAuthOptions> = async (app: FastifyInstance, opts: PlatformaticLogtoAuthOptions) => {\n app.register(fastifyLogto, {\n endpoint: opts.logtoBaseUrl || 'https://auth.example.com',\n appId: opts.logtoAppId || 'your-app-id',\n appSecret: opts.logtoAppSecret || 'your-app-secret',\n });\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await app.register(fastifyUser as any, opts.jwtPlugin);\n\n const adminSecret = opts.adminSecret\n const roleKey = opts.rolePath || opts.roleKey || 'X-PLATFORMATIC-ROLE'\n const userKey = opts.userPath || opts.userKey || 'X-PLATFORMATIC-USER-ID'\n const isRolePath = !!opts.rolePath // if `true` the role is intepreted as path like `user.role`\n const anonymousRole = opts.anonymousRole || 'anonymous'\n\n async function composeLogToRules() {\n const rolesResp = await app.logto.callAPI('/api/roles?type=User', 'GET');\n\n if (!rolesResp.ok) {\n throw rolesResp;\n }\n\n const roles = await rolesResp.json();\n const rules: PlatformaticRule[] = [{\n role: anonymousRole,\n entities: Object.keys(app.platformatic.entities),\n find: opts.allowAnonymous,\n save: opts.allowAnonymous,\n delete: opts.allowAnonymous,\n }];\n\n for (const role of roles) {\n const scopesResp = await app.logto.callAPI(`/api/roles/${role.id}/scopes`, 'GET');\n\n if (!scopesResp.ok) {\n throw scopesResp;\n }\n\n const scopes = await scopesResp.json();\n\n for (const scope of scopes) {\n const roleName = role.name;\n const [scopeAction, entity] = scope.name.split(':');\n\n if (!app.platformatic.entities[entity]) {\n const nearest = findNearestEntity(entity)\n app.log.warn(`Unknown entity '${entity}' in authorization rule. Did you mean '${nearest.entity}'?`)\n continue;\n }\n\n const checkExists = rules.find(r => r.role === roleName && r.entity === entity);\n if (checkExists) {\n if (opts.checks) {\n checkExists[scopeAction] = {\n checks: {\n userId: userKey\n }\n };\n } else {\n checkExists[scopeAction] = true;\n }\n } else {\n const newRule: PlatformaticRule = {\n role: roleName,\n entity,\n };\n\n if (opts.checks) {\n newRule[scopeAction] = {\n checks: {\n userId: userKey\n }\n };\n } else {\n newRule[scopeAction] = true;\n }\n\n if (opts.defaults) {\n newRule.defaults = {\n userId: userKey\n };\n }\n\n rules.push(newRule);\n }\n }\n }\n\n app.log.debug('LogTo calculated rules');\n app.log.debug(rules);\n return rules;\n }\n\n app.decorateRequest('setupDBAuthorizationUser', setupUser)\n\n async function setupUser() {\n // if (!adminSecret) {\n await this.extractUser()\n // }\n\n let forceAdminRole = false\n if (adminSecret && this.headers['x-platformatic-admin-secret'] === adminSecret) {\n if (opts.jwtPlugin.jwt) {\n forceAdminRole = true\n } else {\n this.log.info('admin secret is valid')\n this.user = new Proxy(this.headers, {\n get: (target, key) => {\n let value;\n if (!target[key.toString()]) {\n const newKey = key.toString().toLowerCase()\n value = target[newKey]\n } else {\n value = target[key.toString()]\n }\n\n if (!value && key.toString().toLowerCase() === roleKey.toLowerCase()) {\n value = PLT_ADMIN_ROLE\n }\n return value\n },\n })\n }\n }\n\n if (forceAdminRole) {\n // We replace just the role in `request.user`, all the rest is untouched\n this.user = {\n // ...request.user,\n [roleKey]: PLT_ADMIN_ROLE,\n }\n }\n }\n\n function findNearestEntity(ruleEntity) {\n // There is an unknown entity. Let's find out the nearest one for a nice error message\n const entities = Object.keys(app.platformatic.entities)\n\n const nearest = entities.reduce((acc, entity) => {\n\n const distance = leven(ruleEntity, entity)\n if (distance < acc.distance) {\n acc.distance = distance\n acc.entity = entity\n }\n return acc\n }, { distance: Infinity, entity: null })\n return nearest\n }\n\n app.addHook('onReady', async function () {\n const rules = await composeLogToRules();\n\n // TODO validate that there is at most a rule for a given role\n const entityRules = {};\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i]\n\n let ruleEntities = null\n if (rule.entity) {\n ruleEntities = [rule.entity]\n } else if (rule.entities) {\n ruleEntities = [...rule.entities]\n } else {\n throw new Error(`Missing entity in authorization rule ${i}`)\n }\n\n for (const ruleEntity of ruleEntities) {\n const newRule = { ...rule, entity: ruleEntity, entities: undefined }\n if (!app.platformatic.entities[newRule.entity]) {\n const nearest = findNearestEntity(ruleEntity)\n throw new Error(`Unknown entity '${ruleEntity}' in authorization rule ${i}. Did you mean '${nearest.entity}'?`)\n }\n\n if (!entityRules[ruleEntity]) {\n entityRules[ruleEntity] = []\n }\n entityRules[ruleEntity].push(newRule)\n }\n }\n\n for (const entityKey of Object.keys(app.platformatic.entities)) {\n const rules = entityRules[entityKey] || []\n const type = app.platformatic.entities[entityKey]\n\n // We have subscriptions!\n let userPropToFillForPublish\n const topicsWithoutChecks = false\n\n // mqtt\n // if (app.platformatic.mq) {\n // for (const rule of rules) {\n // const checks = rule.find?.checks\n // if (typeof checks !== 'object') {\n // topicsWithoutChecks = !!rule.find\n // continue\n // }\n // const keys = Object.keys(checks)\n // if (keys.length !== 1) {\n // throw new Error(`Subscription requires that the role \"${rule.role}\" has only one check in the find rule for entity \"${rule.entity}\"`)\n // }\n // const key = keys[0]\n\n // const val = typeof checks[key] === 'object' ? checks[key].eq : checks[key]\n // if (userPropToFillForPublish && userPropToFillForPublish.val !== val) {\n // throw new Error('Unable to configure subscriptions and authorization due to multiple check clauses in find')\n // }\n // userPropToFillForPublish = { key, val }\n // }\n // }\n\n if (userPropToFillForPublish && topicsWithoutChecks) {\n throw new Error(`Subscription for entity \"${entityKey}\" have conflictling rules across roles`)\n }\n\n // MUST set this after doing the security checks on the subscriptions\n if (adminSecret) {\n rules.push({\n role: PLT_ADMIN_ROLE,\n find: true,\n save: true,\n delete: true,\n })\n }\n\n // If we have `fields` in save rules, we need to check if all the not-nullable\n // fields are specified\n checkSaveMandatoryFieldsInRules(type, rules)\n\n // function useOriginal(skipAuth: boolean, ctx: PlatformaticContext) {\n // if (skipAuth === false && !ctx) {\n // throw new Error('Cannot set skipAuth to `false` without ctx')\n // }\n\n // return skipAuth || !ctx\n // }\n\n app.platformatic.addEntityHooks(entityKey, {\n async find(originalFind, { where, ctx, fields, ...restOpts } = {}) {\n // if (useOriginal(skipAuth, ctx)) {\n // return originalFind({ ...restOpts, where, ctx, fields })\n // }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n checkFieldsFromRule(rule.find, fields || Object.keys(app.platformatic.entities[entityKey].fields))\n where = await fromRuleToWhere(ctx, rule.find, where, request.user)\n\n return originalFind({ ...restOpts, where, ctx, fields })\n },\n async save(originalSave, { input, ctx, fields, ...restOpts }) {\n // if (useOriginal(skipAuth, ctx)) {\n // return originalSave({ ctx, input, fields, ...restOpts })\n // }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n\n if (!rule.save) {\n throw new Unauthorized()\n }\n checkFieldsFromRule(rule.save, fields)\n checkInputFromRuleFields(rule.save, input)\n\n if (rule.defaults) {\n for (const key of Object.keys(rule.defaults)) {\n const defaults = rule.defaults[key]\n if (typeof defaults === 'function') {\n input[key] = await defaults({ user: request.user, ctx, input })\n } else {\n input[key] = request.user[defaults]\n }\n }\n }\n\n const hasAllPrimaryKeys = input[type.primaryKey] !== undefined;\n const whereConditions = {}\n whereConditions[type.primaryKey] = { eq: input[type.primaryKey] }\n\n if (hasAllPrimaryKeys) {\n const where = await fromRuleToWhere(ctx, rule.save, whereConditions, request.user)\n\n const found = await type.find({\n where,\n ctx,\n fields,\n })\n\n if (found.length === 0) {\n throw new Unauthorized()\n }\n\n return originalSave({ input, ctx, fields, ...restOpts })\n }\n\n return originalSave({ input, ctx, fields, ...restOpts })\n },\n\n async insert(originalInsert, { inputs, ctx, fields, ...restOpts }) {\n // if (useOriginal(skipAuth, ctx)) {\n // return originalInsert({ inputs, ctx, fields, ...restOpts })\n // }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n\n if (!rule.save) {\n throw new Unauthorized()\n }\n\n checkFieldsFromRule(rule.save, fields)\n checkInputFromRuleFields(rule.save, inputs)\n\n /* istanbul ignore else */\n if (rule.defaults) {\n for (const input of inputs) {\n for (const key of Object.keys(rule.defaults)) {\n const defaults = rule.defaults[key]\n if (typeof defaults === 'function') {\n input[key] = await defaults({ user: request.user, ctx, input })\n } else {\n input[key] = request.user[defaults]\n }\n }\n }\n }\n\n return originalInsert({ inputs, ctx, fields, ...restOpts })\n },\n\n async delete(originalDelete, { where, ctx, fields, ...restOpts }) {\n // if (useOriginal(skipAuth, ctx)) {\n // return originalDelete({ where, ctx, fields, ...restOpts })\n // }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n\n where = await fromRuleToWhere(ctx, rule.delete, where, request.user)\n\n return originalDelete({ where, ctx, fields, ...restOpts })\n },\n\n async updateMany(originalUpdateMany, { where, ctx, fields, ...restOpts }) {\n // if (useOriginal(skipAuth, ctx)) {\n // return originalUpdateMany({ ...restOpts, where, ctx, fields })\n // }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n\n where = await fromRuleToWhere(ctx, rule.updateMany, where, request.user)\n\n return originalUpdateMany({ ...restOpts, where, ctx, fields })\n },\n })\n }\n })\n}\n\nasync function fromRuleToWhere(ctx: PlatformaticContext, rule, where, user) {\n if (!rule) {\n throw new Unauthorized()\n }\n const request = getRequestFromContext(ctx)\n /* istanbul ignore next */\n where = where || {}\n\n if (typeof rule === 'object') {\n const { checks } = rule\n\n /* istanbul ignore else */\n if (checks) {\n for (const key of Object.keys(checks)) {\n const clauses = checks[key]\n if (typeof clauses === 'string') {\n // case: \"userId\": \"X-PLATFORMATIC-USER-ID\"\n where[key] = {\n eq: request.user[clauses],\n }\n } else {\n // case:\n // userId: {\n // eq: 'X-PLATFORMATIC-USER-ID'\n // }\n for (const clauseKey of Object.keys(clauses)) {\n const clause = clauses[clauseKey]\n where[key] = {\n [clauseKey]: request.user[clause],\n }\n }\n }\n }\n }\n } else if (typeof rule === 'function') {\n where = await rule({ user, ctx, where })\n }\n return where\n}\n\nasync function findRuleForRequestUser(ctx: PlatformaticContext, rules: PlatformaticRule[], roleKey: string, anonymousRole: string, isRolePath = false) {\n const request = getRequestFromContext(ctx)\n await request.setupDBAuthorizationUser()\n const roles = getRoles(request, roleKey, anonymousRole, isRolePath)\n const rule = findRule(rules, roles)\n if (!rule) {\n ctx.reply.request.log.warn({ roles, rules }, 'no rule for roles')\n throw new Unauthorized()\n }\n ctx.reply.request.log.trace({ roles, rule }, 'found rule')\n return rule\n}\n\nfunction checkFieldsFromRule(rule, fields) {\n if (!rule) {\n throw new Unauthorized()\n }\n const { fields: fieldsFromRule } = rule\n /* istanbul ignore else */\n if (fieldsFromRule) {\n for (const field of fields) {\n if (!fieldsFromRule.includes(field)) {\n throw new UnauthorizedField(field)\n }\n }\n }\n}\n\nconst validateInputs = (inputs, fieldsFromRule) => {\n for (const input of inputs) {\n const inputFields = Object.keys(input)\n for (const inputField of inputFields) {\n if (!fieldsFromRule.includes(inputField)) {\n throw new UnauthorizedField(inputField)\n }\n }\n }\n}\n\nfunction checkInputFromRuleFields(rule, inputs) {\n const { fields: fieldsFromRule } = rule\n /* istanbul ignore else */\n if (fieldsFromRule) {\n if (!Array.isArray(inputs)) {\n // save\n validateInputs([inputs], fieldsFromRule)\n } else {\n // insert\n validateInputs(inputs, fieldsFromRule)\n }\n }\n}\n\nfunction checkSaveMandatoryFieldsInRules(type: Entity, rules) {\n // List of not nullable, not PKs field to validate save/insert when allowed fields are specified on the rule\n const mandatoryFields =\n Object.values(type.fields)\n .filter(k => (!k.isNullable && !k.primaryKey))\n .map(({ camelcase }) => (camelcase))\n\n for (const rule of rules) {\n const { entity, save } = rule\n if (save && save.fields) {\n const fields = save.fields\n for (const mField of mandatoryFields) {\n if (!fields.includes(mField)) {\n throw new MissingNotNullableError(mField, entity)\n }\n }\n }\n }\n}\n\nexport default fp(auth, {name: '@albirex/platformatic-logto'})\n","'use strict'\n\nimport { PlatformaticRule } from '../index.js'\n\nfunction findRule(rules: PlatformaticRule[], roles: string[]) {\n let found = null\n for (const rule of rules) {\n for (const role of roles) {\n if (rule.role === role) {\n found = rule\n break\n }\n }\n if (found) {\n break\n }\n }\n return found\n}\n\nexport default findRule\n","'use strict'\n\nexport function getRequestFromContext (ctx) {\n if (ctx && !ctx.reply) {\n throw new Error('Missing reply in context. You should call this function with { ctx: { reply }}')\n }\n return ctx.reply.request\n}\n\nexport function getRoles (request, roleKey, anonymousRole, isRolePath = false) {\n let output = []\n const user = request.user\n if (!user) {\n output.push(anonymousRole)\n return output\n }\n\n let rolesRaw\n if (isRolePath) {\n const roleKeys = roleKey.split('.')\n rolesRaw = user\n for (const key of roleKeys) {\n rolesRaw = rolesRaw[key]\n }\n } else {\n rolesRaw = user[roleKey]\n }\n\n if (typeof rolesRaw === 'string') {\n output = rolesRaw.split(',')\n } else if (Array.isArray(rolesRaw)) {\n output = rolesRaw\n }\n if (output.length === 0) {\n output.push(anonymousRole)\n }\n\n return output\n}\n","'use strict'\n\nimport createError from '@fastify/error'\n\nconst ERROR_PREFIX = 'PLT_DB_AUTH'\n\nexport const Unauthorized = createError(`${ERROR_PREFIX}_UNAUTHORIZED`, 'operation not allowed', 401)\nexport const UnauthorizedField = createError(`${ERROR_PREFIX}_FIELD_UNAUTHORIZED`, 'field not allowed: %s', 401)\nexport const MissingNotNullableError = createError(`${ERROR_PREFIX}_NOT_NULLABLE_MISSING`, 'missing not nullable field: \"%s\" in save rule for entity \"%s\"')\n"],"mappings":"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","names":["rules"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils/find-rule.ts","../src/utils/utils.ts","../src/utils/errors.ts"],"sourcesContent":["import fp from 'fastify-plugin'\nimport * as fastifyUser from 'fastify-user'\n\nimport findRule from './utils/find-rule.js'\nimport { getRequestFromContext, getRoles } from './utils/utils.js'\nimport { Unauthorized, UnauthorizedField, MissingNotNullableError } from './utils/errors.js'\nimport fastifyLogto from '@albirex/fastify-logto';\nimport { FastifyInstance, FastifyPluginAsync } from 'fastify'\nimport type { FastifyUserPluginOptions } from 'fastify-user';\nimport type { Entity, PlatformaticContext } from '@platformatic/sql-mapper'\nexport { fastifyLogto } from '@albirex/fastify-logto';\n\nconst PLT_ADMIN_ROLE = 'platformatic-admin'\n\nexport type PlatformaticRule = {\n role: string;\n entity?: string;\n entities?: string[];\n defaults?: Record<string, string>;\n checks?: boolean;\n find?: boolean;\n save?: boolean;\n delete?: boolean;\n\n};\n\nexport type PlatformaticLogtoAuthOptions = {\n logtoBaseUrl?: string;\n logtoAppId?: string;\n logtoAppSecret?: string;\n adminSecret?: string;\n rolePath?: string;\n roleKey?: string;\n userPath?: string;\n userKey?: string;\n anonymousRole?: string;\n allowAnonymous?: boolean;\n checks?: boolean;\n defaults?: boolean;\n jwtPlugin: FastifyUserPluginOptions\n};\n\nexport const platformaticLogto: FastifyPluginAsync<PlatformaticLogtoAuthOptions> = fp(async (app: FastifyInstance, opts: PlatformaticLogtoAuthOptions) => {\n app.register(fastifyLogto, {\n endpoint: opts.logtoBaseUrl || 'https://auth.example.com',\n appId: opts.logtoAppId || 'your-app-id',\n appSecret: opts.logtoAppSecret || 'your-app-secret',\n });\n\n await app.register(fastifyUser as unknown as FastifyPluginAsync, opts.jwtPlugin);\n\n const adminSecret = opts.adminSecret\n const roleKey = opts.rolePath || opts.roleKey || 'X-PLATFORMATIC-ROLE'\n const userKey = opts.userPath || opts.userKey || 'X-PLATFORMATIC-USER-ID'\n const isRolePath = !!opts.rolePath // if `true` the role is intepreted as path like `user.role`\n const anonymousRole = opts.anonymousRole || 'anonymous'\n\n async function composeLogToRules() {\n const rolesResp = await app.logto.callAPI('/api/roles?type=User', 'GET');\n\n if (!rolesResp.ok) {\n throw rolesResp;\n }\n\n const roles = await rolesResp.json();\n const rules: PlatformaticRule[] = [{\n role: anonymousRole,\n entities: Object.keys(app.platformatic.entities),\n find: opts.allowAnonymous,\n save: opts.allowAnonymous,\n delete: opts.allowAnonymous,\n }];\n\n for (const role of roles) {\n const scopesResp = await app.logto.callAPI(`/api/roles/${role.id}/scopes`, 'GET');\n\n if (!scopesResp.ok) {\n throw scopesResp;\n }\n\n const scopes = await scopesResp.json();\n\n for (const scope of scopes) {\n const roleName = role.name;\n // eslint-disable-next-line prefer-const\n let [scopeAction, entity] = scope.name.split(':');\n\n if (!app.platformatic.entities[entity]) {\n app.log.debug(`Unknown entity '${entity}' in authorization rule`)\n continue;\n }\n\n switch (scopeAction) {\n case 'create':\n scopeAction = 'save'\n break;\n case 'read':\n scopeAction = 'find'\n break;\n case 'update':\n scopeAction = 'updateMany'\n break;\n }\n\n const checkExists = rules.find(r => r.role === roleName && r.entity === entity);\n if (checkExists) {\n if (opts.checks) {\n checkExists[scopeAction] = {\n checks: {\n userId: userKey\n }\n };\n } else {\n checkExists[scopeAction] = true;\n }\n } else {\n const newRule: PlatformaticRule = {\n role: roleName,\n entity,\n };\n\n if (opts.checks) {\n newRule[scopeAction] = {\n checks: {\n userId: userKey\n }\n };\n } else {\n newRule[scopeAction] = true;\n }\n\n if (opts.defaults) {\n newRule.defaults = {\n userId: userKey\n };\n }\n\n rules.push(newRule);\n }\n }\n }\n\n const logRules = rules.reduce((prev, curr) => {\n (prev[curr['role']] ??= []).push(curr);\n return prev;\n }, {})\n\n for (const key in logRules) {\n app.log.info(`Rules set for role ${key}`);\n\n for (const element of logRules[key]) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { entity, entities, role, ...other } = element;\n app.log.info(`\\t${entity ?? entities.join(',')}: ${JSON.stringify(other)}`);\n }\n }\n\n const missingEntities = Object.keys(app.platformatic.entities).filter((e) => !rules.map((r) => r.entity).includes(e));\n\n if (missingEntities.length) {\n app.log.warn(`Missing rules for entities: ${missingEntities.join(', ')}`);\n }\n\n app.log.debug('LogTo calculated rules');\n app.log.debug(rules);\n return rules;\n }\n\n app.decorateRequest('setupDBAuthorizationUser', setupUser)\n\n async function setupUser() {\n // if (!adminSecret) {\n await this.extractUser()\n // }\n\n let forceAdminRole = false\n if (adminSecret && this.headers['x-platformatic-admin-secret'] === adminSecret) {\n if (opts.jwtPlugin.jwt) {\n forceAdminRole = true\n } else {\n this.log.info('admin secret is valid')\n this.user = new Proxy(this.headers, {\n get: (target, key) => {\n let value;\n if (!target[key.toString()]) {\n const newKey = key.toString().toLowerCase()\n value = target[newKey]\n } else {\n value = target[key.toString()]\n }\n\n if (!value && key.toString().toLowerCase() === roleKey.toLowerCase()) {\n value = PLT_ADMIN_ROLE\n }\n return value\n },\n })\n }\n }\n\n if (forceAdminRole) {\n // We replace just the role in `request.user`, all the rest is untouched\n this.user = {\n // ...request.user,\n [roleKey]: PLT_ADMIN_ROLE,\n }\n }\n }\n\n app.addHook('onReady', async function () {\n const rules = await composeLogToRules();\n\n // TODO validate that there is at most a rule for a given role\n const entityRules = {};\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i]\n\n let ruleEntities = null\n if (rule.entity) {\n ruleEntities = [rule.entity]\n } else if (rule.entities) {\n ruleEntities = [...rule.entities]\n } else {\n throw new Error(`Missing entity in authorization rule ${i}`)\n }\n\n for (const ruleEntity of ruleEntities) {\n const newRule = { ...rule, entity: ruleEntity, entities: undefined }\n if (!app.platformatic.entities[newRule.entity]) {\n throw new Error(`Unknown entity '${ruleEntity}' in authorization rule ${i}`)\n }\n\n if (!entityRules[ruleEntity]) {\n entityRules[ruleEntity] = []\n }\n entityRules[ruleEntity].push(newRule)\n }\n }\n\n for (const entityKey of Object.keys(app.platformatic.entities)) {\n const rules = entityRules[entityKey] || []\n const type = app.platformatic.entities[entityKey]\n\n // We have subscriptions!\n let userPropToFillForPublish\n const topicsWithoutChecks = false\n\n // mqtt\n // if (app.platformatic.mq) {\n // for (const rule of rules) {\n // const checks = rule.find?.checks\n // if (typeof checks !== 'object') {\n // topicsWithoutChecks = !!rule.find\n // continue\n // }\n // const keys = Object.keys(checks)\n // if (keys.length !== 1) {\n // throw new Error(`Subscription requires that the role \"${rule.role}\" has only one check in the find rule for entity \"${rule.entity}\"`)\n // }\n // const key = keys[0]\n\n // const val = typeof checks[key] === 'object' ? checks[key].eq : checks[key]\n // if (userPropToFillForPublish && userPropToFillForPublish.val !== val) {\n // throw new Error('Unable to configure subscriptions and authorization due to multiple check clauses in find')\n // }\n // userPropToFillForPublish = { key, val }\n // }\n // }\n\n if (userPropToFillForPublish && topicsWithoutChecks) {\n throw new Error(`Subscription for entity \"${entityKey}\" have conflictling rules across roles`)\n }\n\n // MUST set this after doing the security checks on the subscriptions\n if (adminSecret) {\n rules.push({\n role: PLT_ADMIN_ROLE,\n find: true,\n save: true,\n delete: true,\n })\n }\n\n // If we have `fields` in save rules, we need to check if all the not-nullable\n // fields are specified\n checkSaveMandatoryFieldsInRules(type, rules)\n\n function useOriginal(ctx: PlatformaticContext) {\n return !ctx\n }\n\n app.platformatic.addEntityHooks(entityKey, {\n async find(originalFind, { where, ctx, fields, ...restOpts } = {}) {\n if (useOriginal(ctx)) {\n return originalFind({ ...restOpts, where, ctx, fields })\n }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n checkFieldsFromRule(rule.find, fields || Object.keys(app.platformatic.entities[entityKey].fields))\n where = await fromRuleToWhere(ctx, rule.find, where, request.user)\n\n return originalFind({ ...restOpts, where, ctx, fields })\n },\n async save(originalSave, { input, ctx, fields, ...restOpts }) {\n if (useOriginal(ctx)) {\n return originalSave({ ctx, input, fields, ...restOpts })\n }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n\n if (!rule.save) {\n throw new Unauthorized()\n }\n checkFieldsFromRule(rule.save, fields)\n checkInputFromRuleFields(rule.save, input)\n\n if (rule.defaults) {\n for (const key of Object.keys(rule.defaults)) {\n const defaults = rule.defaults[key]\n if (typeof defaults === 'function') {\n input[key] = await defaults({ user: request.user, ctx, input })\n } else {\n input[key] = request.user[defaults]\n }\n }\n }\n\n const hasAllPrimaryKeys = input[type.primaryKey] !== undefined;\n const whereConditions = {}\n whereConditions[type.primaryKey] = { eq: input[type.primaryKey] }\n\n if (hasAllPrimaryKeys) {\n const where = await fromRuleToWhere(ctx, rule.save, whereConditions, request.user)\n\n const found = await type.find({\n where,\n ctx,\n fields,\n })\n\n if (found.length === 0) {\n throw new Unauthorized()\n }\n\n return originalSave({ input, ctx, fields, ...restOpts })\n }\n\n return originalSave({ input, ctx, fields, ...restOpts })\n },\n\n async insert(originalInsert, { inputs, ctx, fields, ...restOpts }) {\n if (useOriginal(ctx)) {\n return originalInsert({ inputs, ctx, fields, ...restOpts })\n }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n\n if (!rule.save) {\n throw new Unauthorized()\n }\n\n checkFieldsFromRule(rule.save, fields)\n checkInputFromRuleFields(rule.save, inputs)\n\n /* istanbul ignore else */\n if (rule.defaults) {\n for (const input of inputs) {\n for (const key of Object.keys(rule.defaults)) {\n const defaults = rule.defaults[key]\n if (typeof defaults === 'function') {\n input[key] = await defaults({ user: request.user, ctx, input })\n } else {\n input[key] = request.user[defaults]\n }\n }\n }\n }\n\n return originalInsert({ inputs, ctx, fields, ...restOpts })\n },\n\n async delete(originalDelete, { where, ctx, fields, ...restOpts }) {\n if (useOriginal(ctx)) {\n return originalDelete({ where, ctx, fields, ...restOpts })\n }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n\n where = await fromRuleToWhere(ctx, rule.delete, where, request.user)\n\n return originalDelete({ where, ctx, fields, ...restOpts })\n },\n\n async updateMany(originalUpdateMany, { where, ctx, fields, ...restOpts }) {\n if (useOriginal(ctx)) {\n return originalUpdateMany({ ...restOpts, where, ctx, fields })\n }\n const request = getRequestFromContext(ctx)\n const rule = await findRuleForRequestUser(ctx, rules, roleKey, anonymousRole, isRolePath)\n\n where = await fromRuleToWhere(ctx, rule.updateMany, where, request.user)\n\n return originalUpdateMany({ ...restOpts, where, ctx, fields })\n },\n })\n }\n })\n}, { name: '@albirex/platformatic-logto' });\n\nasync function fromRuleToWhere(ctx: PlatformaticContext, rule, where, user) {\n if (!rule) {\n throw new Unauthorized()\n }\n const request = getRequestFromContext(ctx)\n /* istanbul ignore next */\n where = where || {}\n\n if (typeof rule === 'object') {\n const { checks } = rule\n\n /* istanbul ignore else */\n if (checks) {\n for (const key of Object.keys(checks)) {\n const clauses = checks[key]\n if (typeof clauses === 'string') {\n // case: \"userId\": \"X-PLATFORMATIC-USER-ID\"\n where[key] = {\n eq: request.user[clauses],\n }\n } else {\n // case:\n // userId: {\n // eq: 'X-PLATFORMATIC-USER-ID'\n // }\n for (const clauseKey of Object.keys(clauses)) {\n const clause = clauses[clauseKey]\n where[key] = {\n [clauseKey]: request.user[clause],\n }\n }\n }\n }\n }\n } else if (typeof rule === 'function') {\n where = await rule({ user, ctx, where })\n }\n return where\n}\n\nasync function findRuleForRequestUser(ctx: PlatformaticContext, rules: PlatformaticRule[], roleKey: string, anonymousRole: string, isRolePath = false) {\n const request = getRequestFromContext(ctx)\n await request.setupDBAuthorizationUser()\n const roles = getRoles(request, roleKey, anonymousRole, isRolePath)\n const rule = findRule(rules, roles)\n if (!rule) {\n ctx.reply.request.log.warn({ roles, rules }, 'no rule for roles')\n throw new Unauthorized()\n }\n ctx.reply.request.log.trace({ roles, rule }, 'found rule')\n return rule\n}\n\nfunction checkFieldsFromRule(rule, fields) {\n if (!rule) {\n throw new Unauthorized()\n }\n const { fields: fieldsFromRule } = rule\n /* istanbul ignore else */\n if (fieldsFromRule) {\n for (const field of fields) {\n if (!fieldsFromRule.includes(field)) {\n throw new UnauthorizedField(field)\n }\n }\n }\n}\n\nconst validateInputs = (inputs, fieldsFromRule) => {\n for (const input of inputs) {\n const inputFields = Object.keys(input)\n for (const inputField of inputFields) {\n if (!fieldsFromRule.includes(inputField)) {\n throw new UnauthorizedField(inputField)\n }\n }\n }\n}\n\nfunction checkInputFromRuleFields(rule, inputs) {\n const { fields: fieldsFromRule } = rule\n /* istanbul ignore else */\n if (fieldsFromRule) {\n if (!Array.isArray(inputs)) {\n // save\n validateInputs([inputs], fieldsFromRule)\n } else {\n // insert\n validateInputs(inputs, fieldsFromRule)\n }\n }\n}\n\nfunction checkSaveMandatoryFieldsInRules(type: Entity, rules) {\n // List of not nullable, not PKs field to validate save/insert when allowed fields are specified on the rule\n const mandatoryFields =\n Object.values(type.fields)\n .filter(k => (!k.isNullable && !k.primaryKey))\n .map(({ camelcase }) => (camelcase))\n\n for (const rule of rules) {\n const { entity, save } = rule\n if (save && save.fields) {\n const fields = save.fields\n for (const mField of mandatoryFields) {\n if (!fields.includes(mField)) {\n throw new MissingNotNullableError(mField, entity)\n }\n }\n }\n }\n}\n\nexport default platformaticLogto;\n","'use strict'\n\nimport { PlatformaticRule } from '../index.js'\n\nfunction findRule(rules: PlatformaticRule[], roles: string[]) {\n let found = null\n for (const rule of rules) {\n for (const role of roles) {\n if (rule.role === role) {\n found = rule\n break\n }\n }\n if (found) {\n break\n }\n }\n return found\n}\n\nexport default findRule\n","'use strict'\n\nexport function getRequestFromContext (ctx) {\n if (ctx && !ctx.reply) {\n throw new Error('Missing reply in context. You should call this function with { ctx: { reply }}')\n }\n return ctx.reply.request\n}\n\nexport function getRoles (request, roleKey, anonymousRole, isRolePath = false) {\n let output = []\n const user = request.user\n if (!user) {\n output.push(anonymousRole)\n return output\n }\n\n let rolesRaw\n if (isRolePath) {\n const roleKeys = roleKey.split('.')\n rolesRaw = user\n for (const key of roleKeys) {\n rolesRaw = rolesRaw[key]\n }\n } else {\n rolesRaw = user[roleKey]\n }\n\n if (typeof rolesRaw === 'string') {\n output = rolesRaw.split(',')\n } else if (Array.isArray(rolesRaw)) {\n output = rolesRaw\n }\n if (output.length === 0) {\n output.push(anonymousRole)\n }\n\n return output\n}\n","'use strict'\n\nimport createError from '@fastify/error'\n\nconst ERROR_PREFIX = 'PLT_DB_AUTH'\n\nexport const Unauthorized = createError(`${ERROR_PREFIX}_UNAUTHORIZED`, 'operation not allowed', 401)\nexport const UnauthorizedField = createError(`${ERROR_PREFIX}_FIELD_UNAUTHORIZED`, 'field not allowed: %s', 401)\nexport const MissingNotNullableError = createError(`${ERROR_PREFIX}_NOT_NULLABLE_MISSING`, 'missing not nullable field: \"%s\" in save rule for entity \"%s\"')\n"],"mappings":";AAAA,OAAO,QAAQ;AACf,YAAY,iBAAiB;;;ACG7B,SAAS,SAAS,OAA2B,OAAiB;AAC5D,MAAI,QAAQ;AACZ,aAAW,QAAQ,OAAO;AACxB,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,SAAS,MAAM;AACtB,gBAAQ;AACR;AAAA,MACF;AAAA,IACF;AACA,QAAI,OAAO;AACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,IAAO,oBAAQ;;;AClBR,SAAS,sBAAuB,KAAK;AAC1C,MAAI,OAAO,CAAC,IAAI,OAAO;AACrB,UAAM,IAAI,MAAM,gFAAgF;AAAA,EAClG;AACA,SAAO,IAAI,MAAM;AACnB;AAEO,SAAS,SAAU,SAAS,SAAS,eAAe,aAAa,OAAO;AAC7E,MAAI,SAAS,CAAC;AACd,QAAM,OAAO,QAAQ;AACrB,MAAI,CAAC,MAAM;AACT,WAAO,KAAK,aAAa;AACzB,WAAO;AAAA,EACT;AAEA,MAAI;AACJ,MAAI,YAAY;AACd,UAAM,WAAW,QAAQ,MAAM,GAAG;AAClC,eAAW;AACX,eAAW,OAAO,UAAU;AAC1B,iBAAW,SAAS,GAAG;AAAA,IACzB;AAAA,EACF,OAAO;AACL,eAAW,KAAK,OAAO;AAAA,EACzB;AAEA,MAAI,OAAO,aAAa,UAAU;AAChC,aAAS,SAAS,MAAM,GAAG;AAAA,EAC7B,WAAW,MAAM,QAAQ,QAAQ,GAAG;AAClC,aAAS;AAAA,EACX;AACA,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO,KAAK,aAAa;AAAA,EAC3B;AAEA,SAAO;AACT;;;ACpCA,OAAO,iBAAiB;AAExB,IAAM,eAAe;AAEd,IAAM,eAAe,YAAY,GAAG,YAAY,iBAAiB,yBAAyB,GAAG;AAC7F,IAAM,oBAAoB,YAAY,GAAG,YAAY,uBAAuB,yBAAyB,GAAG;AACxG,IAAM,0BAA0B,YAAY,GAAG,YAAY,yBAAyB,+DAA+D;;;AHF1J,OAAO,kBAAkB;AAIzB,SAAS,gBAAAA,qBAAoB;AAE7B,IAAM,iBAAiB;AA8BhB,IAAM,oBAAsE,GAAG,OAAO,KAAsB,SAAuC;AACtJ,MAAI,SAAS,cAAc;AAAA,IACvB,UAAU,KAAK,gBAAgB;AAAA,IAC/B,OAAO,KAAK,cAAc;AAAA,IAC1B,WAAW,KAAK,kBAAkB;AAAA,EACtC,CAAC;AAED,QAAM,IAAI,SAAS,aAA8C,KAAK,SAAS;AAE/E,QAAM,cAAc,KAAK;AACzB,QAAM,UAAU,KAAK,YAAY,KAAK,WAAW;AACjD,QAAM,UAAU,KAAK,YAAY,KAAK,WAAW;AACjD,QAAM,aAAa,CAAC,CAAC,KAAK;AAC1B,QAAM,gBAAgB,KAAK,iBAAiB;AAE5C,iBAAe,oBAAoB;AAC/B,UAAM,YAAY,MAAM,IAAI,MAAM,QAAQ,wBAAwB,KAAK;AAEvE,QAAI,CAAC,UAAU,IAAI;AACf,YAAM;AAAA,IACV;AAEA,UAAM,QAAQ,MAAM,UAAU,KAAK;AACnC,UAAM,QAA4B,CAAC;AAAA,MAC/B,MAAM;AAAA,MACN,UAAU,OAAO,KAAK,IAAI,aAAa,QAAQ;AAAA,MAC/C,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,IACjB,CAAC;AAED,eAAW,QAAQ,OAAO;AACtB,YAAM,aAAa,MAAM,IAAI,MAAM,QAAQ,cAAc,KAAK,EAAE,WAAW,KAAK;AAEhF,UAAI,CAAC,WAAW,IAAI;AAChB,cAAM;AAAA,MACV;AAEA,YAAM,SAAS,MAAM,WAAW,KAAK;AAErC,iBAAW,SAAS,QAAQ;AACxB,cAAM,WAAW,KAAK;AAEtB,YAAI,CAAC,aAAa,MAAM,IAAI,MAAM,KAAK,MAAM,GAAG;AAEhD,YAAI,CAAC,IAAI,aAAa,SAAS,MAAM,GAAG;AACpC,cAAI,IAAI,MAAM,mBAAmB,MAAM,yBAAyB;AAChE;AAAA,QACJ;AAEA,gBAAQ,aAAa;AAAA,UACjB,KAAK;AACD,0BAAc;AACd;AAAA,UACJ,KAAK;AACD,0BAAc;AACd;AAAA,UACJ,KAAK;AACD,0BAAc;AACd;AAAA,QACR;AAEA,cAAM,cAAc,MAAM,KAAK,OAAK,EAAE,SAAS,YAAY,EAAE,WAAW,MAAM;AAC9E,YAAI,aAAa;AACb,cAAI,KAAK,QAAQ;AACb,wBAAY,WAAW,IAAI;AAAA,cACvB,QAAQ;AAAA,gBACJ,QAAQ;AAAA,cACZ;AAAA,YACJ;AAAA,UACJ,OAAO;AACH,wBAAY,WAAW,IAAI;AAAA,UAC/B;AAAA,QACJ,OAAO;AACH,gBAAM,UAA4B;AAAA,YAC9B,MAAM;AAAA,YACN;AAAA,UACJ;AAEA,cAAI,KAAK,QAAQ;AACb,oBAAQ,WAAW,IAAI;AAAA,cACnB,QAAQ;AAAA,gBACJ,QAAQ;AAAA,cACZ;AAAA,YACJ;AAAA,UACJ,OAAO;AACH,oBAAQ,WAAW,IAAI;AAAA,UAC3B;AAEA,cAAI,KAAK,UAAU;AACf,oBAAQ,WAAW;AAAA,cACf,QAAQ;AAAA,YACZ;AAAA,UACJ;AAEA,gBAAM,KAAK,OAAO;AAAA,QACtB;AAAA,MACJ;AAAA,IACJ;AAEA,UAAM,WAAW,MAAM,OAAO,CAAC,MAAM,SAAS;AAC1C,OAAC,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,GAAG,KAAK,IAAI;AACrC,aAAO;AAAA,IACX,GAAG,CAAC,CAAC;AAEL,eAAW,OAAO,UAAU;AACxB,UAAI,IAAI,KAAK,sBAAsB,GAAG,EAAE;AAExC,iBAAW,WAAW,SAAS,GAAG,GAAG;AAEjC,cAAM,EAAE,QAAQ,UAAU,MAAM,GAAG,MAAM,IAAI;AAC7C,YAAI,IAAI,KAAK,IAAK,UAAU,SAAS,KAAK,GAAG,CAAC,KAAK,KAAK,UAAU,KAAK,CAAC,EAAE;AAAA,MAC9E;AAAA,IACJ;AAEA,UAAM,kBAAkB,OAAO,KAAK,IAAI,aAAa,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;AAEpH,QAAI,gBAAgB,QAAQ;AACxB,UAAI,IAAI,KAAK,+BAA+B,gBAAgB,KAAK,IAAI,CAAC,EAAE;AAAA,IAC5E;AAEA,QAAI,IAAI,MAAM,wBAAwB;AACtC,QAAI,IAAI,MAAM,KAAK;AACnB,WAAO;AAAA,EACX;AAEA,MAAI,gBAAgB,4BAA4B,SAAS;AAEzD,iBAAe,YAAY;AAEvB,UAAM,KAAK,YAAY;AAGvB,QAAI,iBAAiB;AACrB,QAAI,eAAe,KAAK,QAAQ,6BAA6B,MAAM,aAAa;AAC5E,UAAI,KAAK,UAAU,KAAK;AACpB,yBAAiB;AAAA,MACrB,OAAO;AACH,aAAK,IAAI,KAAK,uBAAuB;AACrC,aAAK,OAAO,IAAI,MAAM,KAAK,SAAS;AAAA,UAChC,KAAK,CAAC,QAAQ,QAAQ;AAClB,gBAAI;AACJ,gBAAI,CAAC,OAAO,IAAI,SAAS,CAAC,GAAG;AACzB,oBAAM,SAAS,IAAI,SAAS,EAAE,YAAY;AAC1C,sBAAQ,OAAO,MAAM;AAAA,YACzB,OAAO;AACH,sBAAQ,OAAO,IAAI,SAAS,CAAC;AAAA,YACjC;AAEA,gBAAI,CAAC,SAAS,IAAI,SAAS,EAAE,YAAY,MAAM,QAAQ,YAAY,GAAG;AAClE,sBAAQ;AAAA,YACZ;AACA,mBAAO;AAAA,UACX;AAAA,QACJ,CAAC;AAAA,MACL;AAAA,IACJ;AAEA,QAAI,gBAAgB;AAEhB,WAAK,OAAO;AAAA;AAAA,QAER,CAAC,OAAO,GAAG;AAAA,MACf;AAAA,IACJ;AAAA,EACJ;AAEA,MAAI,QAAQ,WAAW,iBAAkB;AACrC,UAAM,QAAQ,MAAM,kBAAkB;AAGtC,UAAM,cAAc,CAAC;AACrB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACnC,YAAM,OAAO,MAAM,CAAC;AAEpB,UAAI,eAAe;AACnB,UAAI,KAAK,QAAQ;AACb,uBAAe,CAAC,KAAK,MAAM;AAAA,MAC/B,WAAW,KAAK,UAAU;AACtB,uBAAe,CAAC,GAAG,KAAK,QAAQ;AAAA,MACpC,OAAO;AACH,cAAM,IAAI,MAAM,wCAAwC,CAAC,EAAE;AAAA,MAC/D;AAEA,iBAAW,cAAc,cAAc;AACnC,cAAM,UAAU,EAAE,GAAG,MAAM,QAAQ,YAAY,UAAU,OAAU;AACnE,YAAI,CAAC,IAAI,aAAa,SAAS,QAAQ,MAAM,GAAG;AAC5C,gBAAM,IAAI,MAAM,mBAAmB,UAAU,2BAA2B,CAAC,EAAE;AAAA,QAC/E;AAEA,YAAI,CAAC,YAAY,UAAU,GAAG;AAC1B,sBAAY,UAAU,IAAI,CAAC;AAAA,QAC/B;AACA,oBAAY,UAAU,EAAE,KAAK,OAAO;AAAA,MACxC;AAAA,IACJ;AAEA,eAAW,aAAa,OAAO,KAAK,IAAI,aAAa,QAAQ,GAAG;AAgD5D,UAAS,cAAT,SAAqB,KAA0B;AAC3C,eAAO,CAAC;AAAA,MACZ;AAjDA,YAAMC,SAAQ,YAAY,SAAS,KAAK,CAAC;AACzC,YAAM,OAAO,IAAI,aAAa,SAAS,SAAS;AAGhD,UAAI;AACJ,YAAM,sBAAsB;AAwB5B,UAAI,4BAA4B,qBAAqB;AACjD,cAAM,IAAI,MAAM,4BAA4B,SAAS,wCAAwC;AAAA,MACjG;AAGA,UAAI,aAAa;AACb,QAAAA,OAAM,KAAK;AAAA,UACP,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,UACN,QAAQ;AAAA,QACZ,CAAC;AAAA,MACL;AAIA,sCAAgC,MAAMA,MAAK;AAM3C,UAAI,aAAa,eAAe,WAAW;AAAA,QACvC,MAAM,KAAK,cAAc,EAAE,OAAO,KAAK,QAAQ,GAAG,SAAS,IAAI,CAAC,GAAG;AAC/D,cAAI,YAAY,GAAG,GAAG;AAClB,mBAAO,aAAa,EAAE,GAAG,UAAU,OAAO,KAAK,OAAO,CAAC;AAAA,UAC3D;AACA,gBAAM,UAAU,sBAAsB,GAAG;AACzC,gBAAM,OAAO,MAAM,uBAAuB,KAAKA,QAAO,SAAS,eAAe,UAAU;AACxF,8BAAoB,KAAK,MAAM,UAAU,OAAO,KAAK,IAAI,aAAa,SAAS,SAAS,EAAE,MAAM,CAAC;AACjG,kBAAQ,MAAM,gBAAgB,KAAK,KAAK,MAAM,OAAO,QAAQ,IAAI;AAEjE,iBAAO,aAAa,EAAE,GAAG,UAAU,OAAO,KAAK,OAAO,CAAC;AAAA,QAC3D;AAAA,QACA,MAAM,KAAK,cAAc,EAAE,OAAO,KAAK,QAAQ,GAAG,SAAS,GAAG;AAC1D,cAAI,YAAY,GAAG,GAAG;AAClB,mBAAO,aAAa,EAAE,KAAK,OAAO,QAAQ,GAAG,SAAS,CAAC;AAAA,UAC3D;AACA,gBAAM,UAAU,sBAAsB,GAAG;AACzC,gBAAM,OAAO,MAAM,uBAAuB,KAAKA,QAAO,SAAS,eAAe,UAAU;AAExF,cAAI,CAAC,KAAK,MAAM;AACZ,kBAAM,IAAI,aAAa;AAAA,UAC3B;AACA,8BAAoB,KAAK,MAAM,MAAM;AACrC,mCAAyB,KAAK,MAAM,KAAK;AAEzC,cAAI,KAAK,UAAU;AACf,uBAAW,OAAO,OAAO,KAAK,KAAK,QAAQ,GAAG;AAC1C,oBAAM,WAAW,KAAK,SAAS,GAAG;AAClC,kBAAI,OAAO,aAAa,YAAY;AAChC,sBAAM,GAAG,IAAI,MAAM,SAAS,EAAE,MAAM,QAAQ,MAAM,KAAK,MAAM,CAAC;AAAA,cAClE,OAAO;AACH,sBAAM,GAAG,IAAI,QAAQ,KAAK,QAAQ;AAAA,cACtC;AAAA,YACJ;AAAA,UACJ;AAEA,gBAAM,oBAAoB,MAAM,KAAK,UAAU,MAAM;AACrD,gBAAM,kBAAkB,CAAC;AACzB,0BAAgB,KAAK,UAAU,IAAI,EAAE,IAAI,MAAM,KAAK,UAAU,EAAE;AAEhE,cAAI,mBAAmB;AACnB,kBAAM,QAAQ,MAAM,gBAAgB,KAAK,KAAK,MAAM,iBAAiB,QAAQ,IAAI;AAEjF,kBAAM,QAAQ,MAAM,KAAK,KAAK;AAAA,cAC1B;AAAA,cACA;AAAA,cACA;AAAA,YACJ,CAAC;AAED,gBAAI,MAAM,WAAW,GAAG;AACpB,oBAAM,IAAI,aAAa;AAAA,YAC3B;AAEA,mBAAO,aAAa,EAAE,OAAO,KAAK,QAAQ,GAAG,SAAS,CAAC;AAAA,UAC3D;AAEA,iBAAO,aAAa,EAAE,OAAO,KAAK,QAAQ,GAAG,SAAS,CAAC;AAAA,QAC3D;AAAA,QAEA,MAAM,OAAO,gBAAgB,EAAE,QAAQ,KAAK,QAAQ,GAAG,SAAS,GAAG;AAC/D,cAAI,YAAY,GAAG,GAAG;AAClB,mBAAO,eAAe,EAAE,QAAQ,KAAK,QAAQ,GAAG,SAAS,CAAC;AAAA,UAC9D;AACA,gBAAM,UAAU,sBAAsB,GAAG;AACzC,gBAAM,OAAO,MAAM,uBAAuB,KAAKA,QAAO,SAAS,eAAe,UAAU;AAExF,cAAI,CAAC,KAAK,MAAM;AACZ,kBAAM,IAAI,aAAa;AAAA,UAC3B;AAEA,8BAAoB,KAAK,MAAM,MAAM;AACrC,mCAAyB,KAAK,MAAM,MAAM;AAG1C,cAAI,KAAK,UAAU;AACf,uBAAW,SAAS,QAAQ;AACxB,yBAAW,OAAO,OAAO,KAAK,KAAK,QAAQ,GAAG;AAC1C,sBAAM,WAAW,KAAK,SAAS,GAAG;AAClC,oBAAI,OAAO,aAAa,YAAY;AAChC,wBAAM,GAAG,IAAI,MAAM,SAAS,EAAE,MAAM,QAAQ,MAAM,KAAK,MAAM,CAAC;AAAA,gBAClE,OAAO;AACH,wBAAM,GAAG,IAAI,QAAQ,KAAK,QAAQ;AAAA,gBACtC;AAAA,cACJ;AAAA,YACJ;AAAA,UACJ;AAEA,iBAAO,eAAe,EAAE,QAAQ,KAAK,QAAQ,GAAG,SAAS,CAAC;AAAA,QAC9D;AAAA,QAEA,MAAM,OAAO,gBAAgB,EAAE,OAAO,KAAK,QAAQ,GAAG,SAAS,GAAG;AAC9D,cAAI,YAAY,GAAG,GAAG;AAClB,mBAAO,eAAe,EAAE,OAAO,KAAK,QAAQ,GAAG,SAAS,CAAC;AAAA,UAC7D;AACA,gBAAM,UAAU,sBAAsB,GAAG;AACzC,gBAAM,OAAO,MAAM,uBAAuB,KAAKA,QAAO,SAAS,eAAe,UAAU;AAExF,kBAAQ,MAAM,gBAAgB,KAAK,KAAK,QAAQ,OAAO,QAAQ,IAAI;AAEnE,iBAAO,eAAe,EAAE,OAAO,KAAK,QAAQ,GAAG,SAAS,CAAC;AAAA,QAC7D;AAAA,QAEA,MAAM,WAAW,oBAAoB,EAAE,OAAO,KAAK,QAAQ,GAAG,SAAS,GAAG;AACtE,cAAI,YAAY,GAAG,GAAG;AAClB,mBAAO,mBAAmB,EAAE,GAAG,UAAU,OAAO,KAAK,OAAO,CAAC;AAAA,UACjE;AACA,gBAAM,UAAU,sBAAsB,GAAG;AACzC,gBAAM,OAAO,MAAM,uBAAuB,KAAKA,QAAO,SAAS,eAAe,UAAU;AAExF,kBAAQ,MAAM,gBAAgB,KAAK,KAAK,YAAY,OAAO,QAAQ,IAAI;AAEvE,iBAAO,mBAAmB,EAAE,GAAG,UAAU,OAAO,KAAK,OAAO,CAAC;AAAA,QACjE;AAAA,MACJ,CAAC;AAAA,IACL;AAAA,EACJ,CAAC;AACL,GAAG,EAAE,MAAM,8BAA8B,CAAC;AAE1C,eAAe,gBAAgB,KAA0B,MAAM,OAAO,MAAM;AACxE,MAAI,CAAC,MAAM;AACP,UAAM,IAAI,aAAa;AAAA,EAC3B;AACA,QAAM,UAAU,sBAAsB,GAAG;AAEzC,UAAQ,SAAS,CAAC;AAElB,MAAI,OAAO,SAAS,UAAU;AAC1B,UAAM,EAAE,OAAO,IAAI;AAGnB,QAAI,QAAQ;AACR,iBAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACnC,cAAM,UAAU,OAAO,GAAG;AAC1B,YAAI,OAAO,YAAY,UAAU;AAE7B,gBAAM,GAAG,IAAI;AAAA,YACT,IAAI,QAAQ,KAAK,OAAO;AAAA,UAC5B;AAAA,QACJ,OAAO;AAKH,qBAAW,aAAa,OAAO,KAAK,OAAO,GAAG;AAC1C,kBAAM,SAAS,QAAQ,SAAS;AAChC,kBAAM,GAAG,IAAI;AAAA,cACT,CAAC,SAAS,GAAG,QAAQ,KAAK,MAAM;AAAA,YACpC;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ,WAAW,OAAO,SAAS,YAAY;AACnC,YAAQ,MAAM,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;AAAA,EAC3C;AACA,SAAO;AACX;AAEA,eAAe,uBAAuB,KAA0B,OAA2B,SAAiB,eAAuB,aAAa,OAAO;AACnJ,QAAM,UAAU,sBAAsB,GAAG;AACzC,QAAM,QAAQ,yBAAyB;AACvC,QAAM,QAAQ,SAAS,SAAS,SAAS,eAAe,UAAU;AAClE,QAAM,OAAO,kBAAS,OAAO,KAAK;AAClC,MAAI,CAAC,MAAM;AACP,QAAI,MAAM,QAAQ,IAAI,KAAK,EAAE,OAAO,MAAM,GAAG,mBAAmB;AAChE,UAAM,IAAI,aAAa;AAAA,EAC3B;AACA,MAAI,MAAM,QAAQ,IAAI,MAAM,EAAE,OAAO,KAAK,GAAG,YAAY;AACzD,SAAO;AACX;AAEA,SAAS,oBAAoB,MAAM,QAAQ;AACvC,MAAI,CAAC,MAAM;AACP,UAAM,IAAI,aAAa;AAAA,EAC3B;AACA,QAAM,EAAE,QAAQ,eAAe,IAAI;AAEnC,MAAI,gBAAgB;AAChB,eAAW,SAAS,QAAQ;AACxB,UAAI,CAAC,eAAe,SAAS,KAAK,GAAG;AACjC,cAAM,IAAI,kBAAkB,KAAK;AAAA,MACrC;AAAA,IACJ;AAAA,EACJ;AACJ;AAEA,IAAM,iBAAiB,CAAC,QAAQ,mBAAmB;AAC/C,aAAW,SAAS,QAAQ;AACxB,UAAM,cAAc,OAAO,KAAK,KAAK;AACrC,eAAW,cAAc,aAAa;AAClC,UAAI,CAAC,eAAe,SAAS,UAAU,GAAG;AACtC,cAAM,IAAI,kBAAkB,UAAU;AAAA,MAC1C;AAAA,IACJ;AAAA,EACJ;AACJ;AAEA,SAAS,yBAAyB,MAAM,QAAQ;AAC5C,QAAM,EAAE,QAAQ,eAAe,IAAI;AAEnC,MAAI,gBAAgB;AAChB,QAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAExB,qBAAe,CAAC,MAAM,GAAG,cAAc;AAAA,IAC3C,OAAO;AAEH,qBAAe,QAAQ,cAAc;AAAA,IACzC;AAAA,EACJ;AACJ;AAEA,SAAS,gCAAgC,MAAc,OAAO;AAE1D,QAAM,kBACF,OAAO,OAAO,KAAK,MAAM,EACpB,OAAO,OAAM,CAAC,EAAE,cAAc,CAAC,EAAE,UAAW,EAC5C,IAAI,CAAC,EAAE,UAAU,MAAO,SAAU;AAE3C,aAAW,QAAQ,OAAO;AACtB,UAAM,EAAE,QAAQ,KAAK,IAAI;AACzB,QAAI,QAAQ,KAAK,QAAQ;AACrB,YAAM,SAAS,KAAK;AACpB,iBAAW,UAAU,iBAAiB;AAClC,YAAI,CAAC,OAAO,SAAS,MAAM,GAAG;AAC1B,gBAAM,IAAI,wBAAwB,QAAQ,MAAM;AAAA,QACpD;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AACJ;AAEA,IAAO,gBAAQ;","names":["fastifyLogto","rules"]}
|
package/package.json
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@albirex/platformatic-logto",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.7",
|
|
4
4
|
"description": "LogTo roles and scopes integrated in Platformatic authorization",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./lib/index.
|
|
6
|
+
"main": "./lib/index.cjs",
|
|
7
7
|
"module": "./lib/index.js",
|
|
8
8
|
"types": "./lib/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./lib/index.d.ts",
|
|
12
|
+
"import": "./lib/index.js",
|
|
13
|
+
"require": "./lib/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
9
16
|
"files": [
|
|
10
17
|
"lib"
|
|
11
18
|
],
|
|
@@ -15,7 +22,7 @@
|
|
|
15
22
|
},
|
|
16
23
|
"peerDependencies": {
|
|
17
24
|
"@platformatic/db": "^2.0.0",
|
|
18
|
-
"fastify": "^5",
|
|
25
|
+
"fastify": "^5.5",
|
|
19
26
|
"platformatic": "^2.0.0"
|
|
20
27
|
},
|
|
21
28
|
"devDependencies": {
|
|
@@ -24,14 +31,13 @@
|
|
|
24
31
|
"@types/node": "^22.10.1",
|
|
25
32
|
"dotenv": "^16.5.0",
|
|
26
33
|
"eslint": "^9.12.0",
|
|
27
|
-
"fastify": "~5.2",
|
|
28
34
|
"tap": "^21.1.0",
|
|
29
35
|
"tsup": "^8.5.0",
|
|
30
36
|
"typescript": "~5.5",
|
|
31
37
|
"typescript-eslint": "^8.16.0"
|
|
32
38
|
},
|
|
33
39
|
"dependencies": {
|
|
34
|
-
"@albirex/fastify-logto": "^1.3.
|
|
40
|
+
"@albirex/fastify-logto": "^1.3.3",
|
|
35
41
|
"@fastify/error": "^4.1.0",
|
|
36
42
|
"@logto/js": "^5.1.1",
|
|
37
43
|
"@logto/node": "^3.1.4",
|