@commonpub/server 2.88.0 → 2.90.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/admin/admin.d.ts +9 -0
- package/dist/admin/admin.d.ts.map +1 -1
- package/dist/admin/admin.js +50 -13
- package/dist/admin/admin.js.map +1 -1
- package/dist/content/content.d.ts +0 -5
- package/dist/content/content.d.ts.map +1 -1
- package/dist/content/content.js +118 -122
- package/dist/content/content.js.map +1 -1
- package/dist/content/index.d.ts +1 -1
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +1 -1
- package/dist/content/index.js.map +1 -1
- package/dist/contest/contest.d.ts +7 -300
- package/dist/contest/contest.d.ts.map +1 -1
- package/dist/contest/contest.js +99 -882
- package/dist/contest/contest.js.map +1 -1
- package/dist/contest/entries.d.ts +41 -0
- package/dist/contest/entries.d.ts.map +1 -0
- package/dist/contest/entries.js +285 -0
- package/dist/contest/entries.js.map +1 -0
- package/dist/contest/export.d.ts +20 -0
- package/dist/contest/export.d.ts.map +1 -0
- package/dist/contest/export.js +131 -0
- package/dist/contest/export.js.map +1 -0
- package/dist/contest/index.d.ts +12 -3
- package/dist/contest/index.d.ts.map +1 -1
- package/dist/contest/index.js +9 -2
- package/dist/contest/index.js.map +1 -1
- package/dist/contest/judges.js +9 -8
- package/dist/contest/judges.js.map +1 -1
- package/dist/contest/judging.d.ts +38 -0
- package/dist/contest/judging.d.ts.map +1 -0
- package/dist/contest/judging.js +274 -0
- package/dist/contest/judging.js.map +1 -0
- package/dist/contest/read.d.ts +44 -0
- package/dist/contest/read.d.ts.map +1 -0
- package/dist/contest/read.js +164 -0
- package/dist/contest/read.js.map +1 -0
- package/dist/contest/stages.d.ts +28 -0
- package/dist/contest/stages.d.ts.map +1 -0
- package/dist/contest/stages.js +52 -0
- package/dist/contest/stages.js.map +1 -0
- package/dist/contest/stakeholders.d.ts +32 -7
- package/dist/contest/stakeholders.d.ts.map +1 -1
- package/dist/contest/stakeholders.js +55 -14
- package/dist/contest/stakeholders.js.map +1 -1
- package/dist/contest/submissions.d.ts +90 -0
- package/dist/contest/submissions.d.ts.map +1 -0
- package/dist/contest/submissions.js +275 -0
- package/dist/contest/submissions.js.map +1 -0
- package/dist/contest/types.d.ts +197 -0
- package/dist/contest/types.d.ts.map +1 -0
- package/dist/contest/types.js +2 -0
- package/dist/contest/types.js.map +1 -0
- package/dist/contest/validation.d.ts +32 -0
- package/dist/contest/validation.d.ts.map +1 -0
- package/dist/contest/validation.js +132 -0
- package/dist/contest/validation.js.map +1 -0
- package/dist/docs/docs.d.ts +9 -3
- package/dist/docs/docs.d.ts.map +1 -1
- package/dist/docs/docs.js +16 -6
- package/dist/docs/docs.js.map +1 -1
- package/dist/events/events.d.ts.map +1 -1
- package/dist/events/events.js +12 -6
- package/dist/events/events.js.map +1 -1
- package/dist/federation/activityDedup.d.ts +14 -0
- package/dist/federation/activityDedup.d.ts.map +1 -0
- package/dist/federation/activityDedup.js +34 -0
- package/dist/federation/activityDedup.js.map +1 -0
- package/dist/federation/assertPublicHost.d.ts +14 -0
- package/dist/federation/assertPublicHost.d.ts.map +1 -0
- package/dist/federation/assertPublicHost.js +62 -0
- package/dist/federation/assertPublicHost.js.map +1 -0
- package/dist/federation/delivery.d.ts.map +1 -1
- package/dist/federation/delivery.js +37 -51
- package/dist/federation/delivery.js.map +1 -1
- package/dist/federation/federation.d.ts.map +1 -1
- package/dist/federation/federation.js +11 -7
- package/dist/federation/federation.js.map +1 -1
- package/dist/federation/hubMirroring.d.ts.map +1 -1
- package/dist/federation/hubMirroring.js +85 -66
- package/dist/federation/hubMirroring.js.map +1 -1
- package/dist/federation/inboxHandlers.d.ts.map +1 -1
- package/dist/federation/inboxHandlers.js +84 -73
- package/dist/federation/inboxHandlers.js.map +1 -1
- package/dist/federation/inboxParsing.d.ts +28 -0
- package/dist/federation/inboxParsing.d.ts.map +1 -0
- package/dist/federation/inboxParsing.js +71 -0
- package/dist/federation/inboxParsing.js.map +1 -0
- package/dist/federation/index.d.ts +2 -0
- package/dist/federation/index.d.ts.map +1 -1
- package/dist/federation/index.js +2 -0
- package/dist/federation/index.js.map +1 -1
- package/dist/federation/mastodonLogin.d.ts.map +1 -1
- package/dist/federation/mastodonLogin.js +19 -0
- package/dist/federation/mastodonLogin.js.map +1 -1
- package/dist/federation/outboxQueries.js +1 -1
- package/dist/federation/outboxQueries.js.map +1 -1
- package/dist/federation/timeline.d.ts +11 -0
- package/dist/federation/timeline.d.ts.map +1 -1
- package/dist/federation/timeline.js +101 -69
- package/dist/federation/timeline.js.map +1 -1
- package/dist/hub/hub.d.ts.map +1 -1
- package/dist/hub/hub.js +41 -3
- package/dist/hub/hub.js.map +1 -1
- package/dist/hub/index.d.ts +1 -1
- package/dist/hub/index.d.ts.map +1 -1
- package/dist/hub/index.js +1 -1
- package/dist/hub/index.js.map +1 -1
- package/dist/hub/members.d.ts +19 -0
- package/dist/hub/members.d.ts.map +1 -1
- package/dist/hub/members.js +158 -13
- package/dist/hub/members.js.map +1 -1
- package/dist/hub/moderation.d.ts +1 -1
- package/dist/hub/moderation.d.ts.map +1 -1
- package/dist/hub/moderation.js +25 -11
- package/dist/hub/moderation.js.map +1 -1
- package/dist/hub/posts.d.ts.map +1 -1
- package/dist/hub/posts.js +18 -10
- package/dist/hub/posts.js.map +1 -1
- package/dist/hub/resources.js +2 -2
- package/dist/hub/resources.js.map +1 -1
- package/dist/identity/mastodonFactory.d.ts.map +1 -1
- package/dist/identity/mastodonFactory.js +7 -0
- package/dist/identity/mastodonFactory.js.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/learning/learning.d.ts.map +1 -1
- package/dist/learning/learning.js +42 -22
- package/dist/learning/learning.js.map +1 -1
- package/dist/messaging/messaging.d.ts.map +1 -1
- package/dist/messaging/messaging.js +3 -3
- package/dist/messaging/messaging.js.map +1 -1
- package/dist/notification/notification.d.ts.map +1 -1
- package/dist/notification/notification.js +4 -2
- package/dist/notification/notification.js.map +1 -1
- package/dist/product/product.d.ts.map +1 -1
- package/dist/product/product.js +75 -37
- package/dist/product/product.js.map +1 -1
- package/dist/profile/index.d.ts +2 -1
- package/dist/profile/index.d.ts.map +1 -1
- package/dist/profile/index.js +1 -1
- package/dist/profile/index.js.map +1 -1
- package/dist/profile/profile.d.ts +24 -2
- package/dist/profile/profile.d.ts.map +1 -1
- package/dist/profile/profile.js +34 -8
- package/dist/profile/profile.js.map +1 -1
- package/dist/query.d.ts +18 -2
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +24 -6
- package/dist/query.js.map +1 -1
- package/dist/rbac/admin.d.ts +43 -0
- package/dist/rbac/admin.d.ts.map +1 -0
- package/dist/rbac/admin.js +172 -0
- package/dist/rbac/admin.js.map +1 -0
- package/dist/rbac/index.d.ts +4 -0
- package/dist/rbac/index.d.ts.map +1 -1
- package/dist/rbac/index.js +2 -0
- package/dist/rbac/index.js.map +1 -1
- package/dist/rbac/seed.d.ts +30 -0
- package/dist/rbac/seed.d.ts.map +1 -0
- package/dist/rbac/seed.js +75 -0
- package/dist/rbac/seed.js.map +1 -0
- package/dist/search/contentSearch.d.ts +1 -1
- package/dist/search/contentSearch.d.ts.map +1 -1
- package/dist/search/contentSearch.js +22 -12
- package/dist/search/contentSearch.js.map +1 -1
- package/dist/social/social.d.ts +4 -2
- package/dist/social/social.d.ts.map +1 -1
- package/dist/social/social.js +25 -8
- package/dist/social/social.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/video/video.d.ts +3 -0
- package/dist/video/video.d.ts.map +1 -1
- package/dist/video/video.js +17 -13
- package/dist/video/video.js.map +1 -1
- package/dist/voting/voting.d.ts.map +1 -1
- package/dist/voting/voting.js +39 -1
- package/dist/voting/voting.js.map +1 -1
- package/package.json +9 -7
package/dist/profile/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/profile/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/profile/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEjG,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import type { ContentType } from '@commonpub/schema';
|
|
2
2
|
import type { DB, ContentListItem, UserProfile } from '../types.js';
|
|
3
|
+
export interface UserSearchResult {
|
|
4
|
+
id: string;
|
|
5
|
+
username: string;
|
|
6
|
+
displayName: string | null;
|
|
7
|
+
avatarUrl: string | null;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Minimal user lookup by username/display name for invite pickers (contest
|
|
11
|
+
* judges/reviewers, etc.). Returns PUBLIC fields only — never email/role — so it
|
|
12
|
+
* is safe to expose to non-admin contest managers, unlike the admin user list.
|
|
13
|
+
* Soft-deleted users are excluded; LIKE metacharacters in the query are escaped.
|
|
14
|
+
*/
|
|
15
|
+
export declare function searchUsers(db: DB, query: string, limit?: number): Promise<UserSearchResult[]>;
|
|
3
16
|
export declare function getUserByUsername(db: DB, username: string): Promise<UserProfile | null>;
|
|
4
17
|
export declare function updateUserProfile(db: DB, userId: string, input: {
|
|
5
18
|
displayName?: string;
|
|
@@ -28,8 +41,17 @@ export declare function updateUserProfile(db: DB, userId: string, input: {
|
|
|
28
41
|
mentions?: boolean;
|
|
29
42
|
};
|
|
30
43
|
}): Promise<UserProfile | null>;
|
|
31
|
-
export
|
|
44
|
+
export interface GetUserContentOptions {
|
|
45
|
+
type?: ContentType;
|
|
46
|
+
cursor?: string | null;
|
|
47
|
+
limit?: number;
|
|
48
|
+
/** Caller's intent to view unpublished work — honoured ONLY for the owner. */
|
|
49
|
+
drafts?: boolean;
|
|
50
|
+
/** The authenticated viewer's id (resolved server-side, never a client param). */
|
|
51
|
+
viewerId?: string;
|
|
52
|
+
}
|
|
53
|
+
export declare function getUserContent(db: DB, profileUserId: string, opts?: GetUserContentOptions): Promise<{
|
|
32
54
|
items: ContentListItem[];
|
|
33
|
-
|
|
55
|
+
nextCursor: string | null;
|
|
34
56
|
}>;
|
|
35
57
|
//# sourceMappingURL=profile.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../src/profile/profile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,EAAE,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGpE,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA4E7F;AAED,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,EAAE,EACN,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACjD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,KAAK,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE;QACnB,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;QACrC,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,CAAC;CACH,GACA,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAkC7B;AAED,wBAAsB,cAAc,CAClC,EAAE,EAAE,EAAE,EACN,
|
|
1
|
+
{"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../src/profile/profile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,EAAE,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGpE,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAYhG;AAED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA4E7F;AAED,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,EAAE,EACN,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACjD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,KAAK,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE;QACnB,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;QACrC,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,CAAC;CACH,GACA,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAkC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,cAAc,CAClC,EAAE,EAAE,EAAE,EACN,aAAa,EAAE,MAAM,EACrB,IAAI,GAAE,qBAA0B,GAC/B,OAAO,CAAC;IAAE,KAAK,EAAE,eAAe,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAclE"}
|
package/dist/profile/profile.js
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
|
-
import { eq, and, sql, isNull } from 'drizzle-orm';
|
|
1
|
+
import { eq, and, or, sql, ilike, isNull } from 'drizzle-orm';
|
|
2
2
|
import { contentItems, users, follows } from '@commonpub/schema';
|
|
3
|
-
import {
|
|
3
|
+
import { listContentKeyset } from '../content/content.js';
|
|
4
|
+
/**
|
|
5
|
+
* Minimal user lookup by username/display name for invite pickers (contest
|
|
6
|
+
* judges/reviewers, etc.). Returns PUBLIC fields only — never email/role — so it
|
|
7
|
+
* is safe to expose to non-admin contest managers, unlike the admin user list.
|
|
8
|
+
* Soft-deleted users are excluded; LIKE metacharacters in the query are escaped.
|
|
9
|
+
*/
|
|
10
|
+
export async function searchUsers(db, query, limit = 10) {
|
|
11
|
+
const q = query.trim();
|
|
12
|
+
if (q.length < 2)
|
|
13
|
+
return [];
|
|
14
|
+
// Escape %, _ and \ so they match literally (backslash is PG LIKE's default escape).
|
|
15
|
+
const term = `%${q.replace(/[\\%_]/g, '\\$&')}%`;
|
|
16
|
+
const capped = Math.min(Math.max(1, Math.trunc(limit) || 1), 25);
|
|
17
|
+
return db
|
|
18
|
+
.select({ id: users.id, username: users.username, displayName: users.displayName, avatarUrl: users.avatarUrl })
|
|
19
|
+
.from(users)
|
|
20
|
+
.where(and(isNull(users.deletedAt), or(ilike(users.username, term), ilike(users.displayName, term))))
|
|
21
|
+
.orderBy(users.username)
|
|
22
|
+
.limit(capped);
|
|
23
|
+
}
|
|
4
24
|
export async function getUserByUsername(db, username) {
|
|
5
25
|
const rows = await db
|
|
6
26
|
.select()
|
|
@@ -115,12 +135,18 @@ export async function updateUserProfile(db, userId, input) {
|
|
|
115
135
|
.limit(1);
|
|
116
136
|
return getUserByUsername(db, user[0].username);
|
|
117
137
|
}
|
|
118
|
-
export async function getUserContent(db,
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
138
|
+
export async function getUserContent(db, profileUserId, opts = {}) {
|
|
139
|
+
// Draft visibility is decided HERE from the authenticated viewer — never from a
|
|
140
|
+
// client-supplied status — so only the profile owner can see their own drafts.
|
|
141
|
+
// A non-owner (or anonymous) requesting drafts silently falls back to published.
|
|
142
|
+
const isOwner = !!opts.viewerId && opts.viewerId === profileUserId;
|
|
143
|
+
const status = opts.drafts && isOwner ? 'draft' : 'published';
|
|
144
|
+
return listContentKeyset(db, {
|
|
145
|
+
authorId: profileUserId,
|
|
146
|
+
status,
|
|
147
|
+
type: opts.type,
|
|
148
|
+
cursor: opts.cursor ?? undefined,
|
|
149
|
+
limit: opts.limit ?? 20,
|
|
124
150
|
});
|
|
125
151
|
}
|
|
126
152
|
//# sourceMappingURL=profile.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/profile/profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/profile/profile.ts"],"names":[],"mappings":"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"}
|
package/dist/query.d.ts
CHANGED
|
@@ -355,8 +355,24 @@ export interface PaginationOpts {
|
|
|
355
355
|
limit?: number;
|
|
356
356
|
offset?: number;
|
|
357
357
|
}
|
|
358
|
-
/**
|
|
359
|
-
|
|
358
|
+
/**
|
|
359
|
+
* Normalize pagination options to safe values.
|
|
360
|
+
*
|
|
361
|
+
* Guards non-finite input: routes pass `Number(query.limit)`, so `?limit=abc` yields NaN.
|
|
362
|
+
* `??` does NOT catch NaN, and `Math.min(NaN, 100)` is NaN → `LIMIT NaN` → an
|
|
363
|
+
* unauthenticated 500 on public list endpoints (audit session 203). Clamp limit to
|
|
364
|
+
* [1, maxLimit] and offset to >= 0, falling back to the default when not a finite number.
|
|
365
|
+
*
|
|
366
|
+
* `defaults.limit` sets the page size used when `opts.limit` is absent/invalid (each
|
|
367
|
+
* list endpoint has its own default, e.g. 20/24/50); `defaults.maxLimit` caps the
|
|
368
|
+
* upper bound (default 100). The single source of truth for pagination clamping —
|
|
369
|
+
* prefer this over a hand-rolled `Math.min(opts.limit ?? N, 100)`, which mishandles
|
|
370
|
+
* NaN, zero, and negative input.
|
|
371
|
+
*/
|
|
372
|
+
export declare function normalizePagination(opts: PaginationOpts, defaults?: {
|
|
373
|
+
limit?: number;
|
|
374
|
+
maxLimit?: number;
|
|
375
|
+
}): {
|
|
360
376
|
limit: number;
|
|
361
377
|
offset: number;
|
|
362
378
|
};
|
package/dist/query.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAIrC;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAErF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpG;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1E;AAID,4EAA4E;AAC5E,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKlB,CAAC;AAEX,2EAA2E;AAC3E,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAG3B,CAAC;AAEX,oEAAoE;AACpE,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKhC,CAAC;AAIX;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,EAAE,EACN,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,QAAQ,EACf,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,EACtB,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,KAAK,CAAC;IAAE,GAAG,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAClD,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAID,qFAAqF;AACrF,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
package/dist/query.js
CHANGED
|
@@ -101,12 +101,30 @@ export async function ensureUniqueSlugFor(db, table, slugCol, idCol, slug, fallb
|
|
|
101
101
|
return slug;
|
|
102
102
|
return `${slug}-${Date.now()}`;
|
|
103
103
|
}
|
|
104
|
-
/**
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Normalize pagination options to safe values.
|
|
106
|
+
*
|
|
107
|
+
* Guards non-finite input: routes pass `Number(query.limit)`, so `?limit=abc` yields NaN.
|
|
108
|
+
* `??` does NOT catch NaN, and `Math.min(NaN, 100)` is NaN → `LIMIT NaN` → an
|
|
109
|
+
* unauthenticated 500 on public list endpoints (audit session 203). Clamp limit to
|
|
110
|
+
* [1, maxLimit] and offset to >= 0, falling back to the default when not a finite number.
|
|
111
|
+
*
|
|
112
|
+
* `defaults.limit` sets the page size used when `opts.limit` is absent/invalid (each
|
|
113
|
+
* list endpoint has its own default, e.g. 20/24/50); `defaults.maxLimit` caps the
|
|
114
|
+
* upper bound (default 100). The single source of truth for pagination clamping —
|
|
115
|
+
* prefer this over a hand-rolled `Math.min(opts.limit ?? N, 100)`, which mishandles
|
|
116
|
+
* NaN, zero, and negative input.
|
|
117
|
+
*/
|
|
118
|
+
export function normalizePagination(opts, defaults = {}) {
|
|
119
|
+
const maxLimit = defaults.maxLimit ?? 100;
|
|
120
|
+
const fallback = Math.min(Math.max(Math.trunc(defaults.limit ?? 20), 1), maxLimit);
|
|
121
|
+
const limit = Number.isFinite(opts.limit)
|
|
122
|
+
? Math.min(Math.max(Math.trunc(opts.limit), 1), maxLimit)
|
|
123
|
+
: fallback;
|
|
124
|
+
const offset = Number.isFinite(opts.offset)
|
|
125
|
+
? Math.max(Math.trunc(opts.offset), 0)
|
|
126
|
+
: 0;
|
|
127
|
+
return { limit, offset };
|
|
110
128
|
}
|
|
111
129
|
/**
|
|
112
130
|
* Execute a count query. Returns 0 if no results.
|
package/dist/query.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { DB } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* RBAC role administration (Phase 3). Operator-facing CRUD over the `roles`
|
|
4
|
+
* data tables + per-user custom-role assignment. PERMISSIONS remain a code
|
|
5
|
+
* constant; grants are validated against the catalog (`isPermissionGrant`).
|
|
6
|
+
* The caller (Nitro route) invalidates the permission cache after each write.
|
|
7
|
+
*/
|
|
8
|
+
export interface RoleWithPermissions {
|
|
9
|
+
id: string;
|
|
10
|
+
key: string;
|
|
11
|
+
name: string;
|
|
12
|
+
description: string | null;
|
|
13
|
+
isSystem: boolean;
|
|
14
|
+
priority: number | null;
|
|
15
|
+
permissions: string[];
|
|
16
|
+
memberCount: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function listRolesWithPermissions(db: DB): Promise<RoleWithPermissions[]>;
|
|
19
|
+
export interface CreateRoleInput {
|
|
20
|
+
key: string;
|
|
21
|
+
name: string;
|
|
22
|
+
description?: string | null;
|
|
23
|
+
permissions?: readonly string[];
|
|
24
|
+
}
|
|
25
|
+
export declare function createRole(db: DB, input: CreateRoleInput, actorId: string): Promise<{
|
|
26
|
+
id: string;
|
|
27
|
+
}>;
|
|
28
|
+
export interface UpdateRoleInput {
|
|
29
|
+
name?: string;
|
|
30
|
+
description?: string | null;
|
|
31
|
+
permissions?: readonly string[];
|
|
32
|
+
}
|
|
33
|
+
export declare function updateRole(db: DB, roleId: string, input: UpdateRoleInput, actorId: string): Promise<void>;
|
|
34
|
+
export declare function deleteRole(db: DB, roleId: string, actorId: string): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Replace a user's CUSTOM (non-system) role assignments with `roleIds`. The
|
|
37
|
+
* user's system role (from `users.role`) is managed by `updateUserRole` and is
|
|
38
|
+
* never touched here — system roleIds in the input are ignored.
|
|
39
|
+
*/
|
|
40
|
+
export declare function setUserCustomRoles(db: DB, userId: string, roleIds: string[], grantedBy: string): Promise<void>;
|
|
41
|
+
/** The role IDs (custom + system) a user currently holds — for the admin UI. */
|
|
42
|
+
export declare function getUserRoleIds(db: DB, userId: string): Promise<string[]>;
|
|
43
|
+
//# sourceMappingURL=admin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../src/rbac/admin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAQtC;;;;;GAKG;AAEH,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,wBAAwB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CA4BrF;AAyBD,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;AAED,wBAAsB,UAAU,CAC9B,EAAE,EAAE,EAAE,EACN,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,CA0BzB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;AAED,wBAAsB,UAAU,CAC9B,EAAE,EAAE,EAAE,EACN,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED,wBAAsB,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAevF;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,EAAE,EACN,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAoCf;AAED,gFAAgF;AAChF,wBAAsB,cAAc,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAG9E"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { eq, and, inArray, sql } from 'drizzle-orm';
|
|
2
|
+
import { roles, rolePermissions, userRoles, isPermissionGrant, filterKnownPermissions } from '@commonpub/schema';
|
|
3
|
+
import { createAuditEntry } from '../admin/admin.js';
|
|
4
|
+
import { SYSTEM_ROLE_SEEDS } from './seed.js';
|
|
5
|
+
/** System role keys are reserved — custom roles may not reuse them (a custom
|
|
6
|
+
* role keyed 'admin' would otherwise slip the `*` wildcard past sanitizeGrants). */
|
|
7
|
+
const RESERVED_ROLE_KEYS = new Set(SYSTEM_ROLE_SEEDS.map((s) => s.key));
|
|
8
|
+
export async function listRolesWithPermissions(db) {
|
|
9
|
+
const roleRows = await db.select().from(roles);
|
|
10
|
+
const permRows = await db.select().from(rolePermissions);
|
|
11
|
+
const counts = await db
|
|
12
|
+
.select({ roleId: userRoles.roleId, n: sql `count(*)::int` })
|
|
13
|
+
.from(userRoles)
|
|
14
|
+
.groupBy(userRoles.roleId);
|
|
15
|
+
const permByRole = new Map();
|
|
16
|
+
for (const p of permRows) {
|
|
17
|
+
const list = permByRole.get(p.roleId) ?? [];
|
|
18
|
+
list.push(p.permissionKey);
|
|
19
|
+
permByRole.set(p.roleId, list);
|
|
20
|
+
}
|
|
21
|
+
const countByRole = new Map(counts.map((c) => [c.roleId, c.n]));
|
|
22
|
+
return roleRows
|
|
23
|
+
.map((r) => ({
|
|
24
|
+
id: r.id,
|
|
25
|
+
key: r.key,
|
|
26
|
+
name: r.name,
|
|
27
|
+
description: r.description,
|
|
28
|
+
isSystem: r.isSystem,
|
|
29
|
+
priority: r.priority,
|
|
30
|
+
permissions: (permByRole.get(r.id) ?? []).sort(),
|
|
31
|
+
memberCount: countByRole.get(r.id) ?? 0,
|
|
32
|
+
}))
|
|
33
|
+
.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0) || a.name.localeCompare(b.name));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Grants that confer the admin bypass. `hasPermissionPure` expands the
|
|
37
|
+
* `admin.*` segment wildcard to cover `admin.access`, so stripping only the
|
|
38
|
+
* literal `*` is NOT enough — `admin.*` (and `admin.access` itself) must also be
|
|
39
|
+
* denied on non-admin roles, or a custom role granted `admin.*` silently becomes
|
|
40
|
+
* admin-equivalent (and can then self-promote via users.manage). Only the `admin`
|
|
41
|
+
* system role may hold these.
|
|
42
|
+
*/
|
|
43
|
+
const ADMIN_BYPASS_GRANTS = new Set(['*', 'admin.access', 'admin.*']);
|
|
44
|
+
/**
|
|
45
|
+
* Validate + filter a grant list. Only the `admin` system role keeps the admin
|
|
46
|
+
* bypass; every other role gets those grants stripped. `createRole` rejects the
|
|
47
|
+
* reserved key `admin`, so the only role reaching the `roleKey === 'admin'`
|
|
48
|
+
* branch is the seeded system admin.
|
|
49
|
+
*/
|
|
50
|
+
function sanitizeGrants(grants, roleKey) {
|
|
51
|
+
const known = filterKnownPermissions(grants.filter((g) => isPermissionGrant(g)));
|
|
52
|
+
const deduped = [...new Set(known)];
|
|
53
|
+
if (roleKey === 'admin')
|
|
54
|
+
return deduped;
|
|
55
|
+
return deduped.filter((g) => !ADMIN_BYPASS_GRANTS.has(g));
|
|
56
|
+
}
|
|
57
|
+
export async function createRole(db, input, actorId) {
|
|
58
|
+
const key = input.key.trim().toLowerCase();
|
|
59
|
+
// Reserved system keys can never be (re)created as custom roles — this also
|
|
60
|
+
// closes the `*`-via-key='admin' escalation in sanitizeGrants.
|
|
61
|
+
if (RESERVED_ROLE_KEYS.has(key))
|
|
62
|
+
throw new Error('ROLE_KEY_RESERVED');
|
|
63
|
+
const [existing] = await db.select({ id: roles.id }).from(roles).where(eq(roles.key, key)).limit(1);
|
|
64
|
+
if (existing)
|
|
65
|
+
throw new Error('ROLE_KEY_TAKEN');
|
|
66
|
+
const [role] = await db
|
|
67
|
+
.insert(roles)
|
|
68
|
+
.values({ key, name: input.name.trim(), description: input.description ?? null, isSystem: false, priority: null })
|
|
69
|
+
.returning({ id: roles.id });
|
|
70
|
+
const grants = sanitizeGrants(input.permissions ?? [], key);
|
|
71
|
+
if (grants.length) {
|
|
72
|
+
await db.insert(rolePermissions).values(grants.map((permissionKey) => ({ roleId: role.id, permissionKey })));
|
|
73
|
+
}
|
|
74
|
+
await createAuditEntry(db, {
|
|
75
|
+
userId: actorId,
|
|
76
|
+
action: 'role.created',
|
|
77
|
+
targetType: 'role',
|
|
78
|
+
targetId: role.id,
|
|
79
|
+
metadata: { key, permissions: grants },
|
|
80
|
+
});
|
|
81
|
+
return { id: role.id };
|
|
82
|
+
}
|
|
83
|
+
export async function updateRole(db, roleId, input, actorId) {
|
|
84
|
+
const [role] = await db.select().from(roles).where(eq(roles.id, roleId)).limit(1);
|
|
85
|
+
if (!role)
|
|
86
|
+
throw new Error('ROLE_NOT_FOUND');
|
|
87
|
+
const set = {};
|
|
88
|
+
if (input.name !== undefined)
|
|
89
|
+
set.name = input.name.trim();
|
|
90
|
+
if (input.description !== undefined)
|
|
91
|
+
set.description = input.description;
|
|
92
|
+
if (Object.keys(set).length)
|
|
93
|
+
await db.update(roles).set(set).where(eq(roles.id, roleId));
|
|
94
|
+
if (input.permissions !== undefined) {
|
|
95
|
+
let grants = sanitizeGrants(input.permissions, role.key);
|
|
96
|
+
// The admin role must always retain its full bypass — never let an edit
|
|
97
|
+
// strip `*` and accidentally lock the instance out of admin capabilities.
|
|
98
|
+
if (role.key === 'admin' && !grants.includes('*'))
|
|
99
|
+
grants = ['*', ...grants];
|
|
100
|
+
await db.delete(rolePermissions).where(eq(rolePermissions.roleId, roleId));
|
|
101
|
+
if (grants.length) {
|
|
102
|
+
await db.insert(rolePermissions).values(grants.map((permissionKey) => ({ roleId, permissionKey })));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
await createAuditEntry(db, {
|
|
106
|
+
userId: actorId,
|
|
107
|
+
action: 'role.updated',
|
|
108
|
+
targetType: 'role',
|
|
109
|
+
targetId: roleId,
|
|
110
|
+
metadata: { key: role.key, ...(input.permissions !== undefined ? { permissions: sanitizeGrants(input.permissions, role.key) } : {}) },
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
export async function deleteRole(db, roleId, actorId) {
|
|
114
|
+
const [role] = await db.select().from(roles).where(eq(roles.id, roleId)).limit(1);
|
|
115
|
+
if (!role)
|
|
116
|
+
throw new Error('ROLE_NOT_FOUND');
|
|
117
|
+
if (role.isSystem)
|
|
118
|
+
throw new Error('ROLE_IS_SYSTEM');
|
|
119
|
+
// user_roles + role_permissions cascade on the FK (ON DELETE cascade).
|
|
120
|
+
await db.delete(roles).where(eq(roles.id, roleId));
|
|
121
|
+
await createAuditEntry(db, {
|
|
122
|
+
userId: actorId,
|
|
123
|
+
action: 'role.deleted',
|
|
124
|
+
targetType: 'role',
|
|
125
|
+
targetId: roleId,
|
|
126
|
+
metadata: { key: role.key },
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Replace a user's CUSTOM (non-system) role assignments with `roleIds`. The
|
|
131
|
+
* user's system role (from `users.role`) is managed by `updateUserRole` and is
|
|
132
|
+
* never touched here — system roleIds in the input are ignored.
|
|
133
|
+
*/
|
|
134
|
+
export async function setUserCustomRoles(db, userId, roleIds, grantedBy) {
|
|
135
|
+
// Resolve which of the requested roles are custom (non-system).
|
|
136
|
+
const requested = roleIds.length
|
|
137
|
+
? await db.select({ id: roles.id }).from(roles).where(and(inArray(roles.id, roleIds), eq(roles.isSystem, false)))
|
|
138
|
+
: [];
|
|
139
|
+
const customIds = new Set(requested.map((r) => r.id));
|
|
140
|
+
// ATOMIC read-modify-write: compute the diff and apply both the remove and add
|
|
141
|
+
// inside one transaction so a partial failure can't leave the user with a
|
|
142
|
+
// half-applied assignment set (and concurrent edits don't interleave).
|
|
143
|
+
await db.transaction(async (tx) => {
|
|
144
|
+
const current = await tx
|
|
145
|
+
.select({ roleId: userRoles.roleId })
|
|
146
|
+
.from(userRoles)
|
|
147
|
+
.innerJoin(roles, eq(userRoles.roleId, roles.id))
|
|
148
|
+
.where(and(eq(userRoles.userId, userId), eq(roles.isSystem, false)));
|
|
149
|
+
const currentIds = new Set(current.map((r) => r.roleId));
|
|
150
|
+
const toAdd = [...customIds].filter((id) => !currentIds.has(id));
|
|
151
|
+
const toRemove = [...currentIds].filter((id) => !customIds.has(id));
|
|
152
|
+
if (toRemove.length) {
|
|
153
|
+
await tx.delete(userRoles).where(and(eq(userRoles.userId, userId), inArray(userRoles.roleId, toRemove)));
|
|
154
|
+
}
|
|
155
|
+
if (toAdd.length) {
|
|
156
|
+
await tx.insert(userRoles).values(toAdd.map((roleId) => ({ userId, roleId, grantedBy }))).onConflictDoNothing();
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
await createAuditEntry(db, {
|
|
160
|
+
userId: grantedBy,
|
|
161
|
+
action: 'user.roles_changed',
|
|
162
|
+
targetType: 'user',
|
|
163
|
+
targetId: userId,
|
|
164
|
+
metadata: { customRoleIds: [...customIds] },
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
/** The role IDs (custom + system) a user currently holds — for the admin UI. */
|
|
168
|
+
export async function getUserRoleIds(db, userId) {
|
|
169
|
+
const rows = await db.select({ roleId: userRoles.roleId }).from(userRoles).where(eq(userRoles.userId, userId));
|
|
170
|
+
return rows.map((r) => r.roleId);
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=admin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../../src/rbac/admin.ts"],"names":[],"mappings":"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"}
|
package/dist/rbac/index.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
export { resolveUserPermissions } from './resolver.js';
|
|
2
2
|
export type { ResolvedPermissions } from './resolver.js';
|
|
3
|
+
export { seedRbac, SYSTEM_ROLE_SEEDS, STAFF_PERMISSION_SET } from './seed.js';
|
|
4
|
+
export type { SystemRoleSeed } from './seed.js';
|
|
5
|
+
export { listRolesWithPermissions, createRole, updateRole, deleteRole, setUserCustomRoles, getUserRoleIds, } from './admin.js';
|
|
6
|
+
export type { RoleWithPermissions, CreateRoleInput, UpdateRoleInput } from './admin.js';
|
|
3
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/rbac/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rbac/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,YAAY,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rbac/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,YAAY,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAC9E,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EACL,wBAAwB,EACxB,UAAU,EACV,UAAU,EACV,UAAU,EACV,kBAAkB,EAClB,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/rbac/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
// Global RBAC (session 175). Pure resolution core; the cached Nitro wrapper +
|
|
2
2
|
// server gate live in layers/base/server/utils/. See docs/plans/rbac.md.
|
|
3
3
|
export { resolveUserPermissions } from './resolver.js';
|
|
4
|
+
export { seedRbac, SYSTEM_ROLE_SEEDS, STAFF_PERMISSION_SET } from './seed.js';
|
|
5
|
+
export { listRolesWithPermissions, createRole, updateRole, deleteRole, setUserCustomRoles, getUserRoleIds, } from './admin.js';
|
|
4
6
|
//# sourceMappingURL=index.js.map
|
package/dist/rbac/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rbac/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,yEAAyE;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rbac/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,yEAAyE;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAE9E,OAAO,EACL,wBAAwB,EACxB,UAAU,EACV,UAAU,EACV,UAAU,EACV,kBAAkB,EAClB,cAAc,GACf,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { DB } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* RBAC system-role seed (session 201, Phase 2). The machinery shipped in Phase 0/1
|
|
4
|
+
* but the seed + backfill were never run, so the `roles`/`role_permissions`/
|
|
5
|
+
* `user_roles` tables were empty — flipping `features.rbac` was a no-op. This seeds
|
|
6
|
+
* the five system roles, their permission sets, and backfills `user_roles` from the
|
|
7
|
+
* denormalized `users.role`.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors the SQL appended to migration 0025 (the deploy path, run once via
|
|
10
|
+
* db-migrate.mjs). This TS version is for fresh installs + PGlite tests. Both are
|
|
11
|
+
* ADDITIVE / idempotent (`ON CONFLICT DO NOTHING`) so re-running never clobbers an
|
|
12
|
+
* operator's later edits to a system role's permission set.
|
|
13
|
+
*/
|
|
14
|
+
/** The moderator capability set granted to `staff` (NOT `admin.access`). */
|
|
15
|
+
export declare const STAFF_PERMISSION_SET: readonly ["content.read", "content.moderate", "content.editorial", "reports.review", "contest.create", "contest.manage", "contest.pii", "event.create", "event.manage", "audit.read", "users.read"];
|
|
16
|
+
export interface SystemRoleSeed {
|
|
17
|
+
key: string;
|
|
18
|
+
name: string;
|
|
19
|
+
description: string;
|
|
20
|
+
priority: number;
|
|
21
|
+
permissions: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
/** The five system roles, priority mirrors the legacy roleGuard hierarchy. */
|
|
24
|
+
export declare const SYSTEM_ROLE_SEEDS: readonly SystemRoleSeed[];
|
|
25
|
+
/**
|
|
26
|
+
* Idempotently seed the system roles + permissions and backfill `user_roles`.
|
|
27
|
+
* Safe to run repeatedly; never deletes (so operator edits survive a redeploy).
|
|
28
|
+
*/
|
|
29
|
+
export declare function seedRbac(db: DB): Promise<void>;
|
|
30
|
+
//# sourceMappingURL=seed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../../src/rbac/seed.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAEtC;;;;;;;;;;;GAWG;AAEH,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,qMAYvB,CAAC;AAEX,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,8EAA8E;AAC9E,eAAO,MAAM,iBAAiB,EAAE,SAAS,cAAc,EAYtD,CAAC;AAEF;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BpD"}
|