@manablox/auth 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +40 -1
- package/dist/index.js +188 -21
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { ALL_PERMISSIONS, AuditActor, AuthConfig, BUILT_IN_ROLES, BuiltInRole, CONTENT_ACTIONS, ContentAction, ContentPermission, ContentPermission as ContentPermission$1, Grant, Manablox, PERMISSION_GROUPS, Permission, Permission as Permission$1, PermissionGroup, SpaceRole, SpaceRole as SpaceRole$1, grantsCover, intersectGrants, isBuiltInRole, normaliseGrants, parseGrant, permissionsFor, typesCoveredBy } from "@manablox/core";
|
|
1
2
|
import { Database, MembershipRow, Repositories, SpaceRow } from "@manablox/db";
|
|
2
|
-
import { ALL_PERMISSIONS, AuthConfig, BUILT_IN_ROLES, BuiltInRole, CONTENT_ACTIONS, ContentAction, ContentPermission, ContentPermission as ContentPermission$1, Grant, Manablox, PERMISSION_GROUPS, Permission, Permission as Permission$1, PermissionGroup, SpaceRole, SpaceRole as SpaceRole$1, grantsCover, intersectGrants, isBuiltInRole, normaliseGrants, parseGrant, permissionsFor, typesCoveredBy } from "@manablox/core";
|
|
3
3
|
//#region src/rbac.d.ts
|
|
4
4
|
export interface Principal {
|
|
5
5
|
userId: string;
|
|
@@ -15,6 +15,9 @@ export interface Principal {
|
|
|
15
15
|
permissions?: Record<string, readonly string[]>;
|
|
16
16
|
/** True when the request authenticated with an API key rather than a session. */
|
|
17
17
|
viaApiKey?: boolean;
|
|
18
|
+
/** The key that authenticated the request, for the audit log. */
|
|
19
|
+
apiKeyId?: string | null;
|
|
20
|
+
apiKeyName?: string | null;
|
|
18
21
|
/**
|
|
19
22
|
* Spaces this principal is confined to, or `null`/absent for no confinement. Set by an
|
|
20
23
|
* API key that was issued with a space restriction: it narrows the key below its
|
|
@@ -28,6 +31,14 @@ export interface Principal {
|
|
|
28
31
|
*/
|
|
29
32
|
allowedGrants?: readonly string[] | null;
|
|
30
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* The principal as the audit log records it: a user, or a user through an API key, with
|
|
36
|
+
* the request's client details beside it. Anonymous requests act as the system.
|
|
37
|
+
*/
|
|
38
|
+
export declare function auditActorFor(principal: Principal | null, request?: {
|
|
39
|
+
headers: Headers;
|
|
40
|
+
requestId?: string | null | undefined;
|
|
41
|
+
}): AuditActor;
|
|
31
42
|
/** The grants a principal's role gives in a space, whatever kind of role it is. */
|
|
32
43
|
export declare function grantsIn(principal: Principal, spaceId: string): readonly string[];
|
|
33
44
|
/**
|
|
@@ -174,12 +185,20 @@ export declare class UserService {
|
|
|
174
185
|
* before the reset does not keep it afterwards.
|
|
175
186
|
*/
|
|
176
187
|
setPassword(userId: string, password: string): Promise<void>;
|
|
188
|
+
/**
|
|
189
|
+
* The account holder changing their own password: the current one must be right, and
|
|
190
|
+
* unlike an administrator's reset the other sessions stay signed in, since the person
|
|
191
|
+
* holding the account is the one making the change.
|
|
192
|
+
*/
|
|
193
|
+
changePassword(userId: string, currentPassword: string, password: string): Promise<void>;
|
|
177
194
|
/** A banned user is signed out everywhere and refused on the next request. */
|
|
178
195
|
ban(actorId: string, userId: string, reason: string | null): Promise<UserSummary>;
|
|
179
196
|
unban(userId: string): Promise<UserSummary>;
|
|
180
197
|
delete(actorId: string, userId: string): Promise<void>;
|
|
181
198
|
/** Signs the user out of every device without touching the account. */
|
|
182
199
|
revokeSessions(userId: string): Promise<void>;
|
|
200
|
+
/** Accounts are instance-wide, so their entries carry no space. */
|
|
201
|
+
private audit;
|
|
183
202
|
private require;
|
|
184
203
|
private assertNotSelf;
|
|
185
204
|
/**
|
|
@@ -202,6 +221,12 @@ export interface AuthCallbacks {
|
|
|
202
221
|
* created by an administrator rather than by whoever finds the login page.
|
|
203
222
|
*/
|
|
204
223
|
allowSignUp?: () => Promise<boolean>;
|
|
224
|
+
/** Runs after a session row is created: a sign-in. */
|
|
225
|
+
onSessionCreated?: (session: {
|
|
226
|
+
userId: string;
|
|
227
|
+
ipAddress?: string | null | undefined;
|
|
228
|
+
userAgent?: string | null | undefined;
|
|
229
|
+
}) => Promise<void>;
|
|
205
230
|
}
|
|
206
231
|
export declare function createAuth(config: AuthConfig, db: Database, callbacks?: AuthCallbacks): import("better-auth").Auth<{
|
|
207
232
|
secret: string;
|
|
@@ -279,6 +304,20 @@ export declare function createAuth(config: AuthConfig, db: Database, callbacks?:
|
|
|
279
304
|
} & Record<string, unknown>) => Promise<void>;
|
|
280
305
|
};
|
|
281
306
|
};
|
|
307
|
+
session: {
|
|
308
|
+
create: {
|
|
309
|
+
after: (session: {
|
|
310
|
+
id: string;
|
|
311
|
+
createdAt: Date;
|
|
312
|
+
updatedAt: Date;
|
|
313
|
+
userId: string;
|
|
314
|
+
expiresAt: Date;
|
|
315
|
+
token: string;
|
|
316
|
+
ipAddress?: string | null | undefined;
|
|
317
|
+
userAgent?: string | null | undefined;
|
|
318
|
+
} & Record<string, unknown>) => Promise<void>;
|
|
319
|
+
};
|
|
320
|
+
};
|
|
282
321
|
};
|
|
283
322
|
advanced: {
|
|
284
323
|
database: {
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { ALL_PERMISSIONS, ALL_PERMISSIONS as ALL_PERMISSIONS$1, BUILT_IN_ROLES, CONTENT_ACTIONS, ManabloxError, PERMISSION_GROUPS, diffRecords, grantsCover, grantsCover as grantsCover$1, intersectGrants, intersectGrants as intersectGrants$1, isBuiltInRole, normaliseGrants, parseGrant, permissionsFor, permissionsFor as permissionsFor$1, systemActor, typesCoveredBy, typesCoveredBy as typesCoveredBy$1 } from "@manablox/core";
|
|
1
2
|
import { rethrowUniqueViolation, schema } from "@manablox/db";
|
|
2
3
|
import { betterAuth } from "better-auth";
|
|
3
4
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
4
5
|
import { APIError } from "better-auth/api";
|
|
5
6
|
import { bearer } from "better-auth/plugins";
|
|
6
7
|
import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
|
|
7
|
-
import { ALL_PERMISSIONS, ALL_PERMISSIONS as ALL_PERMISSIONS$1, BUILT_IN_ROLES, CONTENT_ACTIONS, ManabloxError, PERMISSION_GROUPS, grantsCover, grantsCover as grantsCover$1, intersectGrants, intersectGrants as intersectGrants$1, isBuiltInRole, normaliseGrants, parseGrant, permissionsFor, permissionsFor as permissionsFor$1, typesCoveredBy, typesCoveredBy as typesCoveredBy$1 } from "@manablox/core";
|
|
8
8
|
import { and, eq, sql } from "drizzle-orm";
|
|
9
9
|
//#region src/password.ts
|
|
10
10
|
/**
|
|
@@ -71,6 +71,30 @@ var ApiKeyService = class {
|
|
|
71
71
|
permissions: options.permissions ?? null
|
|
72
72
|
}).returning();
|
|
73
73
|
if (!row) throw new ManabloxError("apiKey.create.failed");
|
|
74
|
+
await this.repos.audit.record({
|
|
75
|
+
action: "apiKey.issue",
|
|
76
|
+
targetKind: "apiKey",
|
|
77
|
+
targetId: row.id,
|
|
78
|
+
targetLabel: name,
|
|
79
|
+
changes: [
|
|
80
|
+
{
|
|
81
|
+
path: "expiresAt",
|
|
82
|
+
from: null,
|
|
83
|
+
to: row.expiresAt
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
path: "spaceIds",
|
|
87
|
+
from: null,
|
|
88
|
+
to: row.spaceIds
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
path: "permissions",
|
|
92
|
+
from: null,
|
|
93
|
+
to: row.permissions
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
meta: { userId }
|
|
97
|
+
});
|
|
74
98
|
return {
|
|
75
99
|
id: row.id,
|
|
76
100
|
name,
|
|
@@ -83,7 +107,19 @@ var ApiKeyService = class {
|
|
|
83
107
|
* or re-enabled, so a disabled row is only a secret digest left lying around.
|
|
84
108
|
*/
|
|
85
109
|
async revoke(id) {
|
|
86
|
-
await this.db.delete(schema.apikeys).where(eq(schema.apikeys.id, id))
|
|
110
|
+
const [row] = await this.db.delete(schema.apikeys).where(eq(schema.apikeys.id, id)).returning({
|
|
111
|
+
id: schema.apikeys.id,
|
|
112
|
+
name: schema.apikeys.name,
|
|
113
|
+
userId: schema.apikeys.userId
|
|
114
|
+
});
|
|
115
|
+
if (!row) return;
|
|
116
|
+
await this.repos.audit.record({
|
|
117
|
+
action: "apiKey.revoke",
|
|
118
|
+
targetKind: "apiKey",
|
|
119
|
+
targetId: row.id,
|
|
120
|
+
targetLabel: row.name,
|
|
121
|
+
meta: { userId: row.userId }
|
|
122
|
+
});
|
|
87
123
|
}
|
|
88
124
|
async list(userId) {
|
|
89
125
|
return this.db.select({
|
|
@@ -129,18 +165,68 @@ var ApiKeyService = class {
|
|
|
129
165
|
spaces,
|
|
130
166
|
permissions,
|
|
131
167
|
viaApiKey: true,
|
|
168
|
+
apiKeyId: row.id,
|
|
169
|
+
apiKeyName: row.name,
|
|
132
170
|
allowedSpaceIds: allowed ? [...allowed] : null,
|
|
133
171
|
allowedGrants: row.permissions
|
|
134
172
|
};
|
|
135
173
|
}
|
|
136
174
|
/** Removes expired keys; scheduled by the jobs package. */
|
|
137
175
|
async pruneExpired() {
|
|
138
|
-
|
|
176
|
+
const deleted = await this.db.delete(schema.apikeys).where(sql`${schema.apikeys.expiresAt} is not null and ${schema.apikeys.expiresAt} < now()`).returning({
|
|
177
|
+
id: schema.apikeys.id,
|
|
178
|
+
name: schema.apikeys.name
|
|
179
|
+
});
|
|
180
|
+
if (deleted.length) await this.repos.audit.record({
|
|
181
|
+
action: "apiKey.prune",
|
|
182
|
+
targetKind: "apiKey",
|
|
183
|
+
meta: { removed: deleted.map((row) => ({
|
|
184
|
+
id: row.id,
|
|
185
|
+
name: row.name
|
|
186
|
+
})) }
|
|
187
|
+
});
|
|
188
|
+
return deleted.length;
|
|
139
189
|
}
|
|
140
190
|
};
|
|
141
191
|
const digest = (secret) => createHash("sha256").update(secret).digest("hex");
|
|
142
192
|
//#endregion
|
|
143
193
|
//#region src/rbac.ts
|
|
194
|
+
/**
|
|
195
|
+
* The principal as the audit log records it: a user, or a user through an API key, with
|
|
196
|
+
* the request's client details beside it. Anonymous requests act as the system.
|
|
197
|
+
*/
|
|
198
|
+
function auditActorFor(principal, request) {
|
|
199
|
+
const detail = {};
|
|
200
|
+
if (request) {
|
|
201
|
+
const ip = request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() || request.headers.get("x-real-ip");
|
|
202
|
+
if (ip) detail.ip = ip;
|
|
203
|
+
const userAgent = request.headers.get("user-agent");
|
|
204
|
+
if (userAgent) detail.userAgent = userAgent.slice(0, 300);
|
|
205
|
+
if (request.requestId) detail.requestId = request.requestId;
|
|
206
|
+
}
|
|
207
|
+
if (!principal) return {
|
|
208
|
+
kind: "system",
|
|
209
|
+
id: null,
|
|
210
|
+
label: "anonymous",
|
|
211
|
+
detail
|
|
212
|
+
};
|
|
213
|
+
if (principal.viaApiKey) {
|
|
214
|
+
detail.apiKeyId = principal.apiKeyId ?? null;
|
|
215
|
+
detail.apiKeyName = principal.apiKeyName ?? null;
|
|
216
|
+
return {
|
|
217
|
+
kind: "apikey",
|
|
218
|
+
id: principal.userId,
|
|
219
|
+
label: principal.email,
|
|
220
|
+
detail
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
kind: "user",
|
|
225
|
+
id: principal.userId,
|
|
226
|
+
label: principal.email,
|
|
227
|
+
detail
|
|
228
|
+
};
|
|
229
|
+
}
|
|
144
230
|
/** The grants a principal's role gives in a space, whatever kind of role it is. */
|
|
145
231
|
function grantsIn(principal, spaceId) {
|
|
146
232
|
const role = principal.spaces[spaceId];
|
|
@@ -237,32 +323,64 @@ var UserService = class {
|
|
|
237
323
|
}
|
|
238
324
|
async create(input) {
|
|
239
325
|
const email = normaliseEmail(input.email);
|
|
240
|
-
|
|
326
|
+
const user = await this.repos.users.create({
|
|
241
327
|
name: input.name.trim(),
|
|
242
328
|
email,
|
|
243
329
|
role: input.role,
|
|
244
330
|
passwordHash: await hashPassword(input.password)
|
|
245
|
-
}).catch(emailConflict(email))
|
|
331
|
+
}).catch(emailConflict(email));
|
|
332
|
+
await this.audit("user.create", user, diffRecords(null, summary(user)));
|
|
333
|
+
return summary(user);
|
|
246
334
|
}
|
|
247
335
|
async update(userId, input) {
|
|
336
|
+
const before = await this.require(userId);
|
|
248
337
|
const data = {};
|
|
249
338
|
if (input.name !== void 0) data.name = input.name.trim();
|
|
250
339
|
if (input.email !== void 0) data.email = normaliseEmail(input.email);
|
|
251
|
-
|
|
340
|
+
const user = await this.repos.users.update(userId, data).catch(emailConflict(data.email));
|
|
341
|
+
await this.audit("user.update", user, diffRecords(summary(before), summary(user)));
|
|
342
|
+
return summary(user);
|
|
252
343
|
}
|
|
253
344
|
/** Changing the instance role; the last superadmin cannot step down. */
|
|
254
345
|
async setRole(userId, role) {
|
|
346
|
+
const before = await this.require(userId);
|
|
255
347
|
if (role !== "superadmin") await this.assertNotLastSuperadmin(userId);
|
|
256
|
-
|
|
348
|
+
const user = await this.repos.users.setRole(userId, role);
|
|
349
|
+
await this.audit("user.setRole", user, [{
|
|
350
|
+
path: "role",
|
|
351
|
+
from: before.role,
|
|
352
|
+
to: user.role
|
|
353
|
+
}]);
|
|
354
|
+
return summary(user);
|
|
257
355
|
}
|
|
258
356
|
/**
|
|
259
357
|
* A new password, and every session gone with the old one: whoever held the account
|
|
260
358
|
* before the reset does not keep it afterwards.
|
|
261
359
|
*/
|
|
262
360
|
async setPassword(userId, password) {
|
|
263
|
-
await this.require(userId);
|
|
361
|
+
const user = await this.require(userId);
|
|
264
362
|
await this.repos.users.setPasswordHash(userId, await hashPassword(password));
|
|
265
363
|
await this.repos.users.revokeSessions(userId);
|
|
364
|
+
await this.audit("user.setPassword", user, []);
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* The account holder changing their own password: the current one must be right, and
|
|
368
|
+
* unlike an administrator's reset the other sessions stay signed in, since the person
|
|
369
|
+
* holding the account is the one making the change.
|
|
370
|
+
*/
|
|
371
|
+
async changePassword(userId, currentPassword, password) {
|
|
372
|
+
const user = await this.require(userId);
|
|
373
|
+
const stored = await this.repos.users.passwordHash(userId);
|
|
374
|
+
if (!stored || !await verifyPassword(stored, currentPassword)) throw ManabloxError.validation([{
|
|
375
|
+
key: "user.password.incorrect",
|
|
376
|
+
path: ["currentPassword"]
|
|
377
|
+
}], "user.validation.failed");
|
|
378
|
+
if (currentPassword === password) throw ManabloxError.validation([{
|
|
379
|
+
key: "user.password.sameAsCurrent",
|
|
380
|
+
path: ["password"]
|
|
381
|
+
}], "user.validation.failed");
|
|
382
|
+
await this.repos.users.setPasswordHash(userId, await hashPassword(password));
|
|
383
|
+
await this.audit("user.changePassword", user, []);
|
|
266
384
|
}
|
|
267
385
|
/** A banned user is signed out everywhere and refused on the next request. */
|
|
268
386
|
async ban(actorId, userId, reason) {
|
|
@@ -270,21 +388,53 @@ var UserService = class {
|
|
|
270
388
|
await this.assertNotLastSuperadmin(userId);
|
|
271
389
|
const user = await this.repos.users.setBanned(userId, true, reason);
|
|
272
390
|
await this.repos.users.revokeSessions(userId);
|
|
391
|
+
await this.audit("user.ban", user, [{
|
|
392
|
+
path: "banned",
|
|
393
|
+
from: false,
|
|
394
|
+
to: true
|
|
395
|
+
}, {
|
|
396
|
+
path: "banReason",
|
|
397
|
+
from: null,
|
|
398
|
+
to: reason
|
|
399
|
+
}]);
|
|
273
400
|
return summary(user);
|
|
274
401
|
}
|
|
275
402
|
async unban(userId) {
|
|
276
|
-
|
|
403
|
+
const before = await this.require(userId);
|
|
404
|
+
const user = await this.repos.users.setBanned(userId, false, null);
|
|
405
|
+
await this.audit("user.unban", user, [{
|
|
406
|
+
path: "banned",
|
|
407
|
+
from: before.banned,
|
|
408
|
+
to: false
|
|
409
|
+
}, {
|
|
410
|
+
path: "banReason",
|
|
411
|
+
from: before.banReason,
|
|
412
|
+
to: null
|
|
413
|
+
}]);
|
|
414
|
+
return summary(user);
|
|
277
415
|
}
|
|
278
416
|
async delete(actorId, userId) {
|
|
279
417
|
this.assertNotSelf(actorId, userId);
|
|
280
|
-
await this.require(userId);
|
|
418
|
+
const user = await this.require(userId);
|
|
281
419
|
await this.assertNotLastSuperadmin(userId);
|
|
282
420
|
await this.repos.users.delete(userId);
|
|
421
|
+
await this.audit("user.delete", user, diffRecords(summary(user), null));
|
|
283
422
|
}
|
|
284
423
|
/** Signs the user out of every device without touching the account. */
|
|
285
424
|
async revokeSessions(userId) {
|
|
286
|
-
await this.require(userId);
|
|
425
|
+
const user = await this.require(userId);
|
|
287
426
|
await this.repos.users.revokeSessions(userId);
|
|
427
|
+
await this.audit("user.revokeSessions", user, []);
|
|
428
|
+
}
|
|
429
|
+
/** Accounts are instance-wide, so their entries carry no space. */
|
|
430
|
+
audit(action, user, changes) {
|
|
431
|
+
return this.repos.audit.record({
|
|
432
|
+
action,
|
|
433
|
+
targetKind: "user",
|
|
434
|
+
targetId: user.id,
|
|
435
|
+
targetLabel: user.email,
|
|
436
|
+
changes
|
|
437
|
+
});
|
|
288
438
|
}
|
|
289
439
|
async require(userId) {
|
|
290
440
|
const user = await this.repos.users.findById(userId);
|
|
@@ -354,15 +504,20 @@ function createAuth(config, db, callbacks = {}) {
|
|
|
354
504
|
}
|
|
355
505
|
},
|
|
356
506
|
plugins: [bearer()],
|
|
357
|
-
databaseHooks: {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
507
|
+
databaseHooks: {
|
|
508
|
+
user: { create: {
|
|
509
|
+
before: async (user) => {
|
|
510
|
+
if (!callbacks.allowSignUp || await callbacks.allowSignUp()) return { data: user };
|
|
511
|
+
throw new APIError("FORBIDDEN", { message: "auth.signUp.closed" });
|
|
512
|
+
},
|
|
513
|
+
after: async (user) => {
|
|
514
|
+
await callbacks.onUserCreated?.(user.id);
|
|
515
|
+
}
|
|
516
|
+
} },
|
|
517
|
+
session: { create: { after: async (session) => {
|
|
518
|
+
await callbacks.onSessionCreated?.(session);
|
|
519
|
+
} } }
|
|
520
|
+
},
|
|
366
521
|
advanced: { database: { generateId: () => crypto.randomUUID() } }
|
|
367
522
|
});
|
|
368
523
|
}
|
|
@@ -401,6 +556,18 @@ async function promoteFirstUser(manablox, repos, userId) {
|
|
|
401
556
|
if (!user || user.role === "superadmin") return;
|
|
402
557
|
await repos.users.setRole(userId, "superadmin");
|
|
403
558
|
for (const space of await repos.spaces.all()) await repos.users.grant(userId, space.id, "owner");
|
|
559
|
+
await repos.audit.record({
|
|
560
|
+
actor: systemActor("first account"),
|
|
561
|
+
action: "user.promote",
|
|
562
|
+
targetKind: "user",
|
|
563
|
+
targetId: user.id,
|
|
564
|
+
targetLabel: user.email,
|
|
565
|
+
changes: [{
|
|
566
|
+
path: "role",
|
|
567
|
+
from: user.role,
|
|
568
|
+
to: "superadmin"
|
|
569
|
+
}]
|
|
570
|
+
});
|
|
404
571
|
manablox.logger.info({ email: user.email }, "first account promoted to superadmin");
|
|
405
572
|
}
|
|
406
573
|
/** Covers an instance whose first account predates this behaviour. */
|
|
@@ -415,4 +582,4 @@ function attachBootstrapOwner(manablox, repos) {
|
|
|
415
582
|
}, { source: "@manablox/auth" });
|
|
416
583
|
}
|
|
417
584
|
//#endregion
|
|
418
|
-
export { ALL_PERMISSIONS, ApiKeyService, BUILT_IN_ROLES, CONTENT_ACTIONS, MIN_PASSWORD_LENGTH, PERMISSION_GROUPS, UserService, actorRoles, allowedTypeIds, assertCan, attachBootstrapOwner, can, createAuth, effectiveGrants, grantsCover, grantsIn, hashPassword, intersectGrants, isBuiltInRole, normaliseGrants, parseApiKey, parseGrant, permissionsFor, promoteFirstUser, resolvePrincipal, typesCoveredBy, verifyPassword };
|
|
585
|
+
export { ALL_PERMISSIONS, ApiKeyService, BUILT_IN_ROLES, CONTENT_ACTIONS, MIN_PASSWORD_LENGTH, PERMISSION_GROUPS, UserService, actorRoles, allowedTypeIds, assertCan, attachBootstrapOwner, auditActorFor, can, createAuth, effectiveGrants, grantsCover, grantsIn, hashPassword, intersectGrants, isBuiltInRole, normaliseGrants, parseApiKey, parseGrant, permissionsFor, promoteFirstUser, resolvePrincipal, typesCoveredBy, verifyPassword };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@manablox/auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
"main": "./dist/index.js",
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@manablox/core": "0.
|
|
15
|
-
"@manablox/db": "0.
|
|
14
|
+
"@manablox/core": "0.4.0",
|
|
15
|
+
"@manablox/db": "0.4.0",
|
|
16
16
|
"better-auth": "^1.7.2",
|
|
17
17
|
"drizzle-orm": "^0.45.2",
|
|
18
18
|
"@node-rs/argon2": "^2.2.0"
|