@axium/server 0.37.0 → 0.37.1

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/acl.d.ts CHANGED
@@ -19,6 +19,7 @@ export type PermissionsFor<TB extends TableName> = Omit<kysely.Selectable<db.Sch
19
19
  export type Result<TB extends TableName> = AccessControlInternal & PermissionsFor<TB>;
20
20
  export type WithACL<TB extends TargetName> = kysely.Selectable<db.Schema[TB]> & {
21
21
  userId: string;
22
+ parentId?: string | null;
22
23
  acl: Result<`acl.${TB}`>[];
23
24
  };
24
25
  export interface ACLSelectionOptions {
package/dist/auth.d.ts CHANGED
@@ -41,9 +41,9 @@ export interface ItemAuthResult<TB extends acl.TargetName> {
41
41
  user?: UserInternal;
42
42
  session?: SessionInternal;
43
43
  }
44
- export declare function authSessionForItem<const TB extends acl.TargetName>(itemType: TB, itemId: string, permissions: Partial<acl.PermissionsFor<`acl.${TB}`>>, session?: SessionAndUser | null): Promise<ItemAuthResult<TB>>;
44
+ export declare function authSessionForItem<const TB extends acl.TargetName>(itemType: TB, itemId: string, permissions: Partial<acl.PermissionsFor<`acl.${TB}`>>, session?: SessionAndUser | null, recursive?: boolean): Promise<ItemAuthResult<TB>>;
45
45
  /**
46
46
  * Authenticate a request against an "item" which has an ACL table.
47
47
  * This will fetch the item, ACLs, users, and the authenticating session.
48
48
  */
49
- export declare function authRequestForItem<const TB extends acl.TargetName>(request: Request, itemType: TB, itemId: string, permissions: Partial<acl.PermissionsFor<`acl.${TB}`>>): Promise<ItemAuthResult<TB>>;
49
+ export declare function authRequestForItem<const TB extends acl.TargetName>(request: Request, itemType: TB, itemId: string, permissions: Partial<acl.PermissionsFor<`acl.${TB}`>>, recursive?: boolean): Promise<ItemAuthResult<TB>>;
package/dist/auth.js CHANGED
@@ -110,7 +110,7 @@ export async function checkAuthForUser(request, userId, sensitive = false) {
110
110
  error(403, 'This token can not be used for sensitive actions');
111
111
  return Object.assign(session, { accessor: session.user });
112
112
  }
113
- export async function authSessionForItem(itemType, itemId, permissions, session) {
113
+ export async function authSessionForItem(itemType, itemId, permissions, session, recursive = false) {
114
114
  const { userId, user } = session ?? {};
115
115
  // Note: we need to do casting because of TS limitations with generics
116
116
  const item = (await db
@@ -137,21 +137,42 @@ export async function authSessionForItem(itemType, itemId, permissions, session)
137
137
  if (userId == item.userId)
138
138
  return result;
139
139
  result.fromACL = true;
140
- if (!item.acl || !item.acl.length)
141
- error(403, 'Item is not shared with you');
142
- const missing = Array.from(acl.check(item.acl, permissions));
143
- if (missing.length)
144
- error(403, 'Missing permissions: ' + missing.join(', '));
145
- return result;
140
+ let current = item;
141
+ for (let i = 0; i < 25; i++) {
142
+ try {
143
+ if (!current.acl || !current.acl.length)
144
+ error(403, 'Item is not shared with you');
145
+ const missing = Array.from(acl.check(current.acl, permissions));
146
+ if (missing.length)
147
+ error(403, 'Missing permissions: ' + missing.join(', '));
148
+ return result;
149
+ }
150
+ catch (e) {
151
+ if (!current.parentId || !recursive)
152
+ throw e;
153
+ current = (await db
154
+ .selectFrom(itemType)
155
+ .selectAll()
156
+ .where('id', '=', current.parentId)
157
+ .$if(!!userId, eb => eb.select(acl.from(itemType, { user })))
158
+ .executeTakeFirstOrThrow()
159
+ .catch(e => {
160
+ if (e.message.includes('no rows'))
161
+ error(404, itemType + ' not found');
162
+ throw e;
163
+ }));
164
+ }
165
+ }
166
+ error(403, 'You do not have permissions for any of the last 25 parent items');
146
167
  }
147
168
  /**
148
169
  * Authenticate a request against an "item" which has an ACL table.
149
170
  * This will fetch the item, ACLs, users, and the authenticating session.
150
171
  */
151
- export async function authRequestForItem(request, itemType, itemId, permissions) {
172
+ export async function authRequestForItem(request, itemType, itemId, permissions, recursive = false) {
152
173
  const token = getToken(request, false);
153
174
  if (!token)
154
175
  error(401, 'Missing token');
155
176
  const session = await getSessionAndUser(token).catch(() => null);
156
- return await authSessionForItem(itemType, itemId, permissions, session);
177
+ return await authSessionForItem(itemType, itemId, permissions, session, recursive);
157
178
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axium/server",
3
- "version": "0.37.0",
3
+ "version": "0.37.1",
4
4
  "author": "James Prevett <axium@jamespre.dev>",
5
5
  "funding": {
6
6
  "type": "individual",