@rebasepro/server-core 0.2.4 → 0.2.5
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/common/src/collections/default-collections.d.ts +5 -8
- package/dist/index.es.js +150 -169
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +150 -169
- package/dist/index.umd.js.map +1 -1
- package/dist/types/src/controllers/auth.d.ts +2 -2
- package/dist/types/src/controllers/client.d.ts +25 -40
- package/dist/types/src/controllers/data.d.ts +4 -0
- package/dist/types/src/controllers/data_driver.d.ts +5 -0
- package/dist/types/src/types/auth_adapter.d.ts +3 -56
- package/dist/types/src/types/backend.d.ts +2 -2
- package/dist/types/src/types/backend_hooks.d.ts +2 -17
- package/dist/types/src/types/properties.d.ts +7 -5
- package/dist/types/src/types/user_management_delegate.d.ts +16 -53
- package/dist/types/src/users/index.d.ts +0 -1
- package/dist/types/src/users/user.d.ts +0 -1
- package/package.json +5 -5
- package/src/auth/admin-routes.ts +2 -91
- package/src/auth/builtin-auth-adapter.ts +5 -55
- package/src/auth/custom-auth-adapter.ts +1 -1
- package/src/init.ts +19 -1
- package/test/admin-routes.test.ts +0 -169
- package/test/backend-hooks-admin.test.ts +0 -25
- package/test/custom-auth-adapter.test.ts +2 -10
- package/dist/types/src/users/roles.d.ts +0 -14
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import { PostgresCollection } from "@rebasepro/types";
|
|
1
|
+
import type { PostgresCollection } from "@rebasepro/types";
|
|
2
2
|
/**
|
|
3
|
-
* Default users collection
|
|
3
|
+
* Default users collection.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* (Map keyed by slug, last-write-wins) so that developer-defined
|
|
9
|
-
* collections with the same slug override this default — no hardcoded
|
|
10
|
-
* string checks required.
|
|
5
|
+
* Prepended to the developer's collections array by the admin and server.
|
|
6
|
+
* Slug-based dedup (Map keyed by slug, last-write-wins) lets developers
|
|
7
|
+
* override by defining their own collection with `slug: "users"`.
|
|
11
8
|
*/
|
|
12
9
|
export declare const defaultUsersCollection: PostgresCollection;
|
package/dist/index.es.js
CHANGED
|
@@ -2547,6 +2547,142 @@ class CollectionRegistry {
|
|
|
2547
2547
|
};
|
|
2548
2548
|
}
|
|
2549
2549
|
}
|
|
2550
|
+
const defaultUsersCollection = {
|
|
2551
|
+
name: "Users",
|
|
2552
|
+
singularName: "User",
|
|
2553
|
+
slug: "users",
|
|
2554
|
+
table: "users",
|
|
2555
|
+
schema: "rebase",
|
|
2556
|
+
icon: "Users",
|
|
2557
|
+
group: "Settings",
|
|
2558
|
+
openEntityMode: "dialog",
|
|
2559
|
+
disableDefaultActions: ["copy"],
|
|
2560
|
+
sort: ["createdAt", "desc"],
|
|
2561
|
+
properties: {
|
|
2562
|
+
id: {
|
|
2563
|
+
name: "ID",
|
|
2564
|
+
type: "string",
|
|
2565
|
+
isId: "uuid",
|
|
2566
|
+
ui: {
|
|
2567
|
+
readOnly: true
|
|
2568
|
+
}
|
|
2569
|
+
},
|
|
2570
|
+
email: {
|
|
2571
|
+
name: "Email",
|
|
2572
|
+
type: "string",
|
|
2573
|
+
validation: {
|
|
2574
|
+
required: true,
|
|
2575
|
+
unique: true
|
|
2576
|
+
}
|
|
2577
|
+
},
|
|
2578
|
+
displayName: {
|
|
2579
|
+
name: "Name",
|
|
2580
|
+
type: "string",
|
|
2581
|
+
columnName: "display_name",
|
|
2582
|
+
validation: {
|
|
2583
|
+
required: true
|
|
2584
|
+
}
|
|
2585
|
+
},
|
|
2586
|
+
photoURL: {
|
|
2587
|
+
name: "Photo URL",
|
|
2588
|
+
type: "string",
|
|
2589
|
+
columnName: "photo_url",
|
|
2590
|
+
url: "image"
|
|
2591
|
+
},
|
|
2592
|
+
roles: {
|
|
2593
|
+
name: "Roles",
|
|
2594
|
+
type: "array",
|
|
2595
|
+
columnType: "text[]",
|
|
2596
|
+
of: {
|
|
2597
|
+
name: "Role",
|
|
2598
|
+
type: "string",
|
|
2599
|
+
enum: {
|
|
2600
|
+
admin: "Admin",
|
|
2601
|
+
editor: "Editor",
|
|
2602
|
+
viewer: "Viewer"
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
},
|
|
2606
|
+
passwordHash: {
|
|
2607
|
+
name: "Password Hash",
|
|
2608
|
+
type: "string",
|
|
2609
|
+
columnName: "password_hash",
|
|
2610
|
+
ui: {
|
|
2611
|
+
hideFromCollection: true,
|
|
2612
|
+
disabled: {
|
|
2613
|
+
hidden: true
|
|
2614
|
+
}
|
|
2615
|
+
}
|
|
2616
|
+
},
|
|
2617
|
+
emailVerified: {
|
|
2618
|
+
name: "Email Verified",
|
|
2619
|
+
type: "boolean",
|
|
2620
|
+
columnName: "email_verified",
|
|
2621
|
+
defaultValue: false,
|
|
2622
|
+
ui: {
|
|
2623
|
+
hideFromCollection: true,
|
|
2624
|
+
disabled: {
|
|
2625
|
+
hidden: true
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
},
|
|
2629
|
+
emailVerificationToken: {
|
|
2630
|
+
name: "Email Verification Token",
|
|
2631
|
+
type: "string",
|
|
2632
|
+
columnName: "email_verification_token",
|
|
2633
|
+
ui: {
|
|
2634
|
+
hideFromCollection: true,
|
|
2635
|
+
disabled: {
|
|
2636
|
+
hidden: true
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
},
|
|
2640
|
+
emailVerificationSentAt: {
|
|
2641
|
+
name: "Email Verification Sent At",
|
|
2642
|
+
type: "date",
|
|
2643
|
+
columnName: "email_verification_sent_at",
|
|
2644
|
+
ui: {
|
|
2645
|
+
hideFromCollection: true,
|
|
2646
|
+
disabled: {
|
|
2647
|
+
hidden: true
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
},
|
|
2651
|
+
metadata: {
|
|
2652
|
+
name: "Metadata",
|
|
2653
|
+
type: "map",
|
|
2654
|
+
defaultValue: {},
|
|
2655
|
+
ui: {
|
|
2656
|
+
hideFromCollection: true,
|
|
2657
|
+
disabled: {
|
|
2658
|
+
hidden: true
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
},
|
|
2662
|
+
createdAt: {
|
|
2663
|
+
name: "Created At",
|
|
2664
|
+
type: "date",
|
|
2665
|
+
columnName: "created_at",
|
|
2666
|
+
ui: {
|
|
2667
|
+
readOnly: true
|
|
2668
|
+
}
|
|
2669
|
+
},
|
|
2670
|
+
updatedAt: {
|
|
2671
|
+
name: "Updated At",
|
|
2672
|
+
type: "date",
|
|
2673
|
+
columnName: "updated_at",
|
|
2674
|
+
autoValue: "on_update",
|
|
2675
|
+
ui: {
|
|
2676
|
+
hideFromCollection: true,
|
|
2677
|
+
disabled: {
|
|
2678
|
+
hidden: true
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
},
|
|
2683
|
+
listProperties: ["displayName", "email", "roles", "createdAt"],
|
|
2684
|
+
propertiesOrder: ["id", "email", "displayName", "roles", "createdAt"]
|
|
2685
|
+
};
|
|
2550
2686
|
function mapOperator$1(op) {
|
|
2551
2687
|
switch (op) {
|
|
2552
2688
|
case "==":
|
|
@@ -13035,11 +13171,6 @@ function createAdminRoutes(config) {
|
|
|
13035
13171
|
const results = await Promise.all(users.map((u) => applyUserAfterRead(u, ctx)));
|
|
13036
13172
|
return results.filter((u) => u !== null);
|
|
13037
13173
|
}
|
|
13038
|
-
async function applyRoleAfterReadBatch(roles, ctx) {
|
|
13039
|
-
if (!hooks?.roles?.afterRead) return roles;
|
|
13040
|
-
const results = await Promise.all(roles.map((r) => hooks.roles.afterRead(r, ctx)));
|
|
13041
|
-
return results.filter((r) => r !== null);
|
|
13042
|
-
}
|
|
13043
13174
|
function toAdminUser(u, roles) {
|
|
13044
13175
|
return {
|
|
13045
13176
|
uid: u.id,
|
|
@@ -13398,90 +13529,6 @@ function createAdminRoutes(config) {
|
|
|
13398
13529
|
success: true
|
|
13399
13530
|
});
|
|
13400
13531
|
});
|
|
13401
|
-
router.get("/roles", requireAdmin, async (c) => {
|
|
13402
|
-
const roles = await authRepo.listRoles();
|
|
13403
|
-
const hookCtx = buildHookContext(c, "GET");
|
|
13404
|
-
let adminRoles = roles.map((r) => ({
|
|
13405
|
-
id: r.id,
|
|
13406
|
-
name: r.name,
|
|
13407
|
-
isAdmin: r.isAdmin,
|
|
13408
|
-
defaultPermissions: r.defaultPermissions
|
|
13409
|
-
}));
|
|
13410
|
-
adminRoles = await applyRoleAfterReadBatch(adminRoles, hookCtx);
|
|
13411
|
-
return c.json({
|
|
13412
|
-
roles: adminRoles
|
|
13413
|
-
});
|
|
13414
|
-
});
|
|
13415
|
-
router.get("/roles/:roleId", requireAdmin, async (c) => {
|
|
13416
|
-
const roleId = c.req.param("roleId");
|
|
13417
|
-
const role = await authRepo.getRoleById(roleId);
|
|
13418
|
-
if (!role) {
|
|
13419
|
-
throw ApiError.notFound("Role not found");
|
|
13420
|
-
}
|
|
13421
|
-
return c.json({
|
|
13422
|
-
role
|
|
13423
|
-
});
|
|
13424
|
-
});
|
|
13425
|
-
router.post("/roles", requireAdmin, async (c) => {
|
|
13426
|
-
const body = await c.req.json();
|
|
13427
|
-
const {
|
|
13428
|
-
id,
|
|
13429
|
-
name: name2,
|
|
13430
|
-
isAdmin,
|
|
13431
|
-
defaultPermissions
|
|
13432
|
-
} = body;
|
|
13433
|
-
if (!id || !name2) {
|
|
13434
|
-
throw ApiError.badRequest("Role ID and name are required", "INVALID_INPUT");
|
|
13435
|
-
}
|
|
13436
|
-
const existing = await authRepo.getRoleById(id);
|
|
13437
|
-
if (existing) {
|
|
13438
|
-
throw ApiError.conflict("Role already exists", "ROLE_EXISTS");
|
|
13439
|
-
}
|
|
13440
|
-
const role = await authRepo.createRole({
|
|
13441
|
-
id,
|
|
13442
|
-
name: name2,
|
|
13443
|
-
isAdmin: isAdmin ?? false,
|
|
13444
|
-
defaultPermissions: defaultPermissions ?? null
|
|
13445
|
-
});
|
|
13446
|
-
return c.json({
|
|
13447
|
-
role
|
|
13448
|
-
}, 201);
|
|
13449
|
-
});
|
|
13450
|
-
router.put("/roles/:roleId", requireAdmin, async (c) => {
|
|
13451
|
-
const roleId = c.req.param("roleId");
|
|
13452
|
-
const body = await c.req.json();
|
|
13453
|
-
const {
|
|
13454
|
-
name: name2,
|
|
13455
|
-
isAdmin,
|
|
13456
|
-
defaultPermissions
|
|
13457
|
-
} = body;
|
|
13458
|
-
const existing = await authRepo.getRoleById(roleId);
|
|
13459
|
-
if (!existing) {
|
|
13460
|
-
throw ApiError.notFound("Role not found");
|
|
13461
|
-
}
|
|
13462
|
-
const role = await authRepo.updateRole(roleId, {
|
|
13463
|
-
name: name2,
|
|
13464
|
-
isAdmin,
|
|
13465
|
-
defaultPermissions
|
|
13466
|
-
});
|
|
13467
|
-
return c.json({
|
|
13468
|
-
role
|
|
13469
|
-
});
|
|
13470
|
-
});
|
|
13471
|
-
router.delete("/roles/:roleId", requireAdmin, async (c) => {
|
|
13472
|
-
const roleId = c.req.param("roleId");
|
|
13473
|
-
if (["admin", "editor", "viewer"].includes(roleId)) {
|
|
13474
|
-
throw ApiError.badRequest("Cannot delete built-in roles", "BUILTIN_ROLE");
|
|
13475
|
-
}
|
|
13476
|
-
const existing = await authRepo.getRoleById(roleId);
|
|
13477
|
-
if (!existing) {
|
|
13478
|
-
throw ApiError.notFound("Role not found");
|
|
13479
|
-
}
|
|
13480
|
-
await authRepo.deleteRole(roleId);
|
|
13481
|
-
return c.json({
|
|
13482
|
-
success: true
|
|
13483
|
-
});
|
|
13484
|
-
});
|
|
13485
13532
|
return router;
|
|
13486
13533
|
}
|
|
13487
13534
|
function createBuiltinAuthAdapter(config) {
|
|
@@ -13525,8 +13572,7 @@ function createBuiltinAuthAdapter(config) {
|
|
|
13525
13572
|
const extendedPayload = payload;
|
|
13526
13573
|
let roles = payload.roles || [];
|
|
13527
13574
|
try {
|
|
13528
|
-
|
|
13529
|
-
roles = userRoles.map((r) => r.id);
|
|
13575
|
+
roles = await authRepository.getUserRoleIds(payload.userId);
|
|
13530
13576
|
} catch {
|
|
13531
13577
|
}
|
|
13532
13578
|
const isAdmin = roles.some((r) => r === "admin" || r === "schema-admin");
|
|
@@ -13556,8 +13602,7 @@ function createBuiltinAuthAdapter(config) {
|
|
|
13556
13602
|
const extendedPayload = payload;
|
|
13557
13603
|
let roles = payload.roles || [];
|
|
13558
13604
|
try {
|
|
13559
|
-
|
|
13560
|
-
roles = userRoles.map((r) => r.id);
|
|
13605
|
+
roles = await authRepository.getUserRoleIds(payload.userId);
|
|
13561
13606
|
} catch {
|
|
13562
13607
|
}
|
|
13563
13608
|
const isAdmin = roles.some((r) => r === "admin" || r === "schema-admin");
|
|
@@ -13571,7 +13616,6 @@ function createBuiltinAuthAdapter(config) {
|
|
|
13571
13616
|
};
|
|
13572
13617
|
},
|
|
13573
13618
|
userManagement: createUserManagementFromRepo(authRepository, resolvedOps, authHooks),
|
|
13574
|
-
roleManagement: createRoleManagementFromRepo(authRepository),
|
|
13575
13619
|
createAuthRoutes() {
|
|
13576
13620
|
return createAuthRoutes({
|
|
13577
13621
|
authRepo: authRepository,
|
|
@@ -13687,43 +13731,13 @@ function createUserManagementFromRepo(repo, resolvedOps, authHooks) {
|
|
|
13687
13731
|
}
|
|
13688
13732
|
},
|
|
13689
13733
|
async getUserRoles(userId) {
|
|
13690
|
-
|
|
13691
|
-
return roles.map(toAuthRoleData);
|
|
13734
|
+
return repo.getUserRoleIds(userId);
|
|
13692
13735
|
},
|
|
13693
13736
|
async setUserRoles(userId, roleIds) {
|
|
13694
13737
|
await repo.setUserRoles(userId, roleIds);
|
|
13695
13738
|
}
|
|
13696
13739
|
};
|
|
13697
13740
|
}
|
|
13698
|
-
function createRoleManagementFromRepo(repo) {
|
|
13699
|
-
return {
|
|
13700
|
-
async listRoles() {
|
|
13701
|
-
const roles = await repo.listRoles();
|
|
13702
|
-
return roles.map(toAuthRoleData);
|
|
13703
|
-
},
|
|
13704
|
-
async getRoleById(id) {
|
|
13705
|
-
const role = await repo.getRoleById(id);
|
|
13706
|
-
return role ? toAuthRoleData(role) : null;
|
|
13707
|
-
},
|
|
13708
|
-
async createRole(data) {
|
|
13709
|
-
const role = await repo.createRole({
|
|
13710
|
-
id: data.id,
|
|
13711
|
-
name: data.name,
|
|
13712
|
-
isAdmin: data.isAdmin,
|
|
13713
|
-
defaultPermissions: data.defaultPermissions,
|
|
13714
|
-
collectionPermissions: data.collectionPermissions
|
|
13715
|
-
});
|
|
13716
|
-
return toAuthRoleData(role);
|
|
13717
|
-
},
|
|
13718
|
-
async updateRole(id, data) {
|
|
13719
|
-
const role = await repo.updateRole(id, data);
|
|
13720
|
-
return role ? toAuthRoleData(role) : null;
|
|
13721
|
-
},
|
|
13722
|
-
async deleteRole(id) {
|
|
13723
|
-
await repo.deleteRole(id);
|
|
13724
|
-
}
|
|
13725
|
-
};
|
|
13726
|
-
}
|
|
13727
13741
|
function toAuthUserData(user) {
|
|
13728
13742
|
return {
|
|
13729
13743
|
id: user.id,
|
|
@@ -13736,15 +13750,6 @@ function toAuthUserData(user) {
|
|
|
13736
13750
|
updatedAt: user.updatedAt
|
|
13737
13751
|
};
|
|
13738
13752
|
}
|
|
13739
|
-
function toAuthRoleData(role) {
|
|
13740
|
-
return {
|
|
13741
|
-
id: role.id,
|
|
13742
|
-
name: role.name,
|
|
13743
|
-
isAdmin: role.isAdmin,
|
|
13744
|
-
defaultPermissions: role.defaultPermissions,
|
|
13745
|
-
collectionPermissions: role.collectionPermissions
|
|
13746
|
-
};
|
|
13747
|
-
}
|
|
13748
13753
|
function configureLogLevel(logLevel) {
|
|
13749
13754
|
const LOG_LEVEL = logLevel || process.env.LOG_LEVEL || "info";
|
|
13750
13755
|
const logLevels = {
|
|
@@ -24927,7 +24932,6 @@ function createCustomAuthAdapter(options2) {
|
|
|
24927
24932
|
verifyRequest: options2.verifyRequest,
|
|
24928
24933
|
verifyToken: resolvedVerifyToken,
|
|
24929
24934
|
userManagement: options2.userManagement,
|
|
24930
|
-
roleManagement: options2.roleManagement,
|
|
24931
24935
|
getCapabilities() {
|
|
24932
24936
|
return defaultCapabilities;
|
|
24933
24937
|
}
|
|
@@ -26927,33 +26931,6 @@ function createAdmin(transport, options2) {
|
|
|
26927
26931
|
method: "DELETE"
|
|
26928
26932
|
});
|
|
26929
26933
|
}
|
|
26930
|
-
async function listRoles() {
|
|
26931
|
-
return transport.request(adminPath + "/roles", {
|
|
26932
|
-
method: "GET"
|
|
26933
|
-
});
|
|
26934
|
-
}
|
|
26935
|
-
async function getRole(roleId) {
|
|
26936
|
-
return transport.request(adminPath + "/roles/" + encodeURIComponent(roleId), {
|
|
26937
|
-
method: "GET"
|
|
26938
|
-
});
|
|
26939
|
-
}
|
|
26940
|
-
async function createRole(data) {
|
|
26941
|
-
return transport.request(adminPath + "/roles", {
|
|
26942
|
-
method: "POST",
|
|
26943
|
-
body: JSON.stringify(data)
|
|
26944
|
-
});
|
|
26945
|
-
}
|
|
26946
|
-
async function updateRole(roleId, data) {
|
|
26947
|
-
return transport.request(adminPath + "/roles/" + encodeURIComponent(roleId), {
|
|
26948
|
-
method: "PUT",
|
|
26949
|
-
body: JSON.stringify(data)
|
|
26950
|
-
});
|
|
26951
|
-
}
|
|
26952
|
-
async function deleteRole(roleId) {
|
|
26953
|
-
return transport.request(adminPath + "/roles/" + encodeURIComponent(roleId), {
|
|
26954
|
-
method: "DELETE"
|
|
26955
|
-
});
|
|
26956
|
-
}
|
|
26957
26934
|
async function bootstrap() {
|
|
26958
26935
|
return transport.request(adminPath + "/bootstrap", {
|
|
26959
26936
|
method: "POST"
|
|
@@ -26966,11 +26943,6 @@ function createAdmin(transport, options2) {
|
|
|
26966
26943
|
createUser,
|
|
26967
26944
|
updateUser,
|
|
26968
26945
|
deleteUser,
|
|
26969
|
-
listRoles,
|
|
26970
|
-
getRole,
|
|
26971
|
-
createRole,
|
|
26972
|
-
updateRole,
|
|
26973
|
-
deleteRole,
|
|
26974
26946
|
bootstrap
|
|
26975
26947
|
};
|
|
26976
26948
|
}
|
|
@@ -38515,6 +38487,9 @@ async function _initializeRebaseBackend(config) {
|
|
|
38515
38487
|
dir: config.collectionsDir
|
|
38516
38488
|
});
|
|
38517
38489
|
}
|
|
38490
|
+
if (config.auth) {
|
|
38491
|
+
activeCollections = Array.from(new Map([defaultUsersCollection, ...activeCollections].map((c) => [c.slug, c])).values());
|
|
38492
|
+
}
|
|
38518
38493
|
const realtimeServices = {};
|
|
38519
38494
|
const delegates = {};
|
|
38520
38495
|
let bootstrappers = config.bootstrappers || [];
|
|
@@ -38583,8 +38558,7 @@ async function _initializeRebaseBackend(config) {
|
|
|
38583
38558
|
id: authAdapter.id
|
|
38584
38559
|
});
|
|
38585
38560
|
authConfigResult = {
|
|
38586
|
-
userService: authAdapter.userManagement ?? {}
|
|
38587
|
-
roleService: authAdapter.roleManagement ?? {}
|
|
38561
|
+
userService: authAdapter.userManagement ?? {}
|
|
38588
38562
|
};
|
|
38589
38563
|
} else {
|
|
38590
38564
|
const safeAuthConfig = config.auth;
|
|
@@ -38930,6 +38904,13 @@ async function _initializeRebaseBackend(config) {
|
|
|
38930
38904
|
configured: emailService.isConfigured()
|
|
38931
38905
|
});
|
|
38932
38906
|
}
|
|
38907
|
+
const driverAdmin = defaultBootstrapper.getAdmin?.(defaultDriverResult);
|
|
38908
|
+
if (isSQLAdmin(driverAdmin)) {
|
|
38909
|
+
Object.assign(serverClient, {
|
|
38910
|
+
sql: (query, options2) => driverAdmin.executeSql(query, options2)
|
|
38911
|
+
});
|
|
38912
|
+
logger.info("SQL capability attached to singleton");
|
|
38913
|
+
}
|
|
38933
38914
|
_initRebase(serverClient);
|
|
38934
38915
|
logger.info("Rebase singleton initialized");
|
|
38935
38916
|
if (defaultDriverResult.internals) {
|