@axium/server 0.17.0 → 0.18.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.
Files changed (86) hide show
  1. package/build/client/_app/immutable/chunks/{BQEW-soH.js → BKTxLcVa.js} +1 -1
  2. package/build/client/_app/immutable/chunks/BKTxLcVa.js.br +0 -0
  3. package/build/client/_app/immutable/chunks/BKTxLcVa.js.gz +0 -0
  4. package/build/client/_app/immutable/chunks/{DQ-d8a5w.js → Bhc2cIbs.js} +2 -2
  5. package/build/client/_app/immutable/chunks/Bhc2cIbs.js.br +0 -0
  6. package/build/client/_app/immutable/chunks/Bhc2cIbs.js.gz +0 -0
  7. package/build/client/_app/immutable/chunks/{ClV-nJVy.js → DecEAa7H.js} +1 -1
  8. package/build/client/_app/immutable/chunks/DecEAa7H.js.br +0 -0
  9. package/build/client/_app/immutable/chunks/{ClV-nJVy.js.gz → DecEAa7H.js.gz} +0 -0
  10. package/build/client/_app/immutable/chunks/{BIqJFsZ3.js → uGVpjdha.js} +1 -1
  11. package/build/client/_app/immutable/chunks/uGVpjdha.js.br +0 -0
  12. package/build/client/_app/immutable/chunks/uGVpjdha.js.gz +0 -0
  13. package/build/client/_app/immutable/entry/{app.Bexu3pho.js → app.J50e72uV.js} +2 -2
  14. package/build/client/_app/immutable/entry/app.J50e72uV.js.br +0 -0
  15. package/build/client/_app/immutable/entry/app.J50e72uV.js.gz +0 -0
  16. package/build/client/_app/immutable/entry/start.CpRP1d0a.js +1 -0
  17. package/build/client/_app/immutable/entry/start.CpRP1d0a.js.br +2 -0
  18. package/build/client/_app/immutable/entry/start.CpRP1d0a.js.gz +0 -0
  19. package/build/client/_app/immutable/nodes/{1.Di0t29Xx.js → 1.rTsuaAPg.js} +1 -1
  20. package/build/client/_app/immutable/nodes/1.rTsuaAPg.js.br +0 -0
  21. package/build/client/_app/immutable/nodes/1.rTsuaAPg.js.gz +0 -0
  22. package/build/client/_app/immutable/nodes/{3.dB5xKZIR.js → 3.BYti3cIq.js} +1 -1
  23. package/build/client/_app/immutable/nodes/3.BYti3cIq.js.br +0 -0
  24. package/build/client/_app/immutable/nodes/3.BYti3cIq.js.gz +0 -0
  25. package/build/client/_app/immutable/nodes/{4.DC1TCp7U.js → 4.CBowWWW9.js} +1 -1
  26. package/build/client/_app/immutable/nodes/4.CBowWWW9.js.br +0 -0
  27. package/build/client/_app/immutable/nodes/4.CBowWWW9.js.gz +0 -0
  28. package/build/client/_app/immutable/nodes/5.BpAkygAb.js +1 -0
  29. package/build/client/_app/immutable/nodes/5.BpAkygAb.js.br +0 -0
  30. package/build/client/_app/immutable/nodes/5.BpAkygAb.js.gz +0 -0
  31. package/build/client/_app/immutable/nodes/{6.WTfzqOhT.js → 6.CdqSI5TW.js} +1 -1
  32. package/build/client/_app/immutable/nodes/6.CdqSI5TW.js.br +0 -0
  33. package/build/client/_app/immutable/nodes/6.CdqSI5TW.js.gz +0 -0
  34. package/build/client/_app/version.json +1 -1
  35. package/build/client/_app/version.json.br +0 -0
  36. package/build/client/_app/version.json.gz +0 -0
  37. package/build/server/chunks/{1-Db3AncWW.js → 1-Bg_TotRw.js} +2 -2
  38. package/build/server/chunks/{1-Db3AncWW.js.map → 1-Bg_TotRw.js.map} +1 -1
  39. package/build/server/chunks/{3-BzEpIldk.js → 3-BjeVNwGc.js} +2 -2
  40. package/build/server/chunks/{3-BzEpIldk.js.map → 3-BjeVNwGc.js.map} +1 -1
  41. package/build/server/chunks/{4-J7bxt5HT.js → 4-B_CUNdkn.js} +2 -2
  42. package/build/server/chunks/{4-J7bxt5HT.js.map → 4-B_CUNdkn.js.map} +1 -1
  43. package/build/server/chunks/{5-uwjgYAk8.js → 5-DTv8qrfa.js} +2 -2
  44. package/build/server/chunks/{5-uwjgYAk8.js.map → 5-DTv8qrfa.js.map} +1 -1
  45. package/build/server/chunks/{6-Cj4cg3MT.js → 6-Cvu6ZsHJ.js} +2 -2
  46. package/build/server/chunks/{6-Cj4cg3MT.js.map → 6-Cvu6ZsHJ.js.map} +1 -1
  47. package/build/server/index.js +1 -1
  48. package/build/server/index.js.map +1 -1
  49. package/build/server/manifest.js +6 -6
  50. package/build/server/manifest.js.map +1 -1
  51. package/dist/acl.d.ts +14 -13
  52. package/dist/acl.js +11 -9
  53. package/dist/api/acl.js +2 -2
  54. package/dist/api/passkeys.js +5 -5
  55. package/dist/api/session.js +6 -5
  56. package/dist/api/users.js +14 -14
  57. package/dist/auth.d.ts +15 -2
  58. package/dist/auth.js +55 -6
  59. package/dist/database.d.ts +7 -6
  60. package/dist/database.js +0 -1
  61. package/dist/requests.d.ts +1 -6
  62. package/dist/requests.js +0 -17
  63. package/package.json +1 -1
  64. package/build/client/_app/immutable/chunks/BIqJFsZ3.js.br +0 -0
  65. package/build/client/_app/immutable/chunks/BIqJFsZ3.js.gz +0 -0
  66. package/build/client/_app/immutable/chunks/BQEW-soH.js.br +0 -0
  67. package/build/client/_app/immutable/chunks/BQEW-soH.js.gz +0 -0
  68. package/build/client/_app/immutable/chunks/ClV-nJVy.js.br +0 -0
  69. package/build/client/_app/immutable/chunks/DQ-d8a5w.js.br +0 -0
  70. package/build/client/_app/immutable/chunks/DQ-d8a5w.js.gz +0 -0
  71. package/build/client/_app/immutable/entry/app.Bexu3pho.js.br +0 -0
  72. package/build/client/_app/immutable/entry/app.Bexu3pho.js.gz +0 -0
  73. package/build/client/_app/immutable/entry/start.CkXOtoPI.js +0 -1
  74. package/build/client/_app/immutable/entry/start.CkXOtoPI.js.br +0 -2
  75. package/build/client/_app/immutable/entry/start.CkXOtoPI.js.gz +0 -0
  76. package/build/client/_app/immutable/nodes/1.Di0t29Xx.js.br +0 -0
  77. package/build/client/_app/immutable/nodes/1.Di0t29Xx.js.gz +0 -0
  78. package/build/client/_app/immutable/nodes/3.dB5xKZIR.js.br +0 -0
  79. package/build/client/_app/immutable/nodes/3.dB5xKZIR.js.gz +0 -0
  80. package/build/client/_app/immutable/nodes/4.DC1TCp7U.js.br +0 -0
  81. package/build/client/_app/immutable/nodes/4.DC1TCp7U.js.gz +0 -0
  82. package/build/client/_app/immutable/nodes/5.DGB0QJIF.js +0 -1
  83. package/build/client/_app/immutable/nodes/5.DGB0QJIF.js.br +0 -0
  84. package/build/client/_app/immutable/nodes/5.DGB0QJIF.js.gz +0 -0
  85. package/build/client/_app/immutable/nodes/6.WTfzqOhT.js.br +0 -0
  86. package/build/client/_app/immutable/nodes/6.WTfzqOhT.js.gz +0 -0
@@ -10,15 +10,15 @@ return {
10
10
  assets: new Set(["icons/brands.svg","icons/light.svg","icons/regular.svg","icons/solid.svg","styles.css"]),
11
11
  mimeTypes: {".svg":"image/svg+xml",".css":"text/css"},
12
12
  _: {
13
- client: {start:"_app/immutable/entry/start.CkXOtoPI.js",app:"_app/immutable/entry/app.Bexu3pho.js",imports:["_app/immutable/entry/start.CkXOtoPI.js","_app/immutable/chunks/DQ-d8a5w.js","_app/immutable/chunks/D5lcOOwR.js","_app/immutable/chunks/B3bf7yrh.js","_app/immutable/chunks/DCs3KlJy.js","_app/immutable/entry/app.Bexu3pho.js","_app/immutable/chunks/B3bf7yrh.js","_app/immutable/chunks/D5lcOOwR.js","_app/immutable/chunks/DCs3KlJy.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/ct9jA5hl.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},
13
+ client: {start:"_app/immutable/entry/start.CpRP1d0a.js",app:"_app/immutable/entry/app.J50e72uV.js",imports:["_app/immutable/entry/start.CpRP1d0a.js","_app/immutable/chunks/Bhc2cIbs.js","_app/immutable/chunks/D5lcOOwR.js","_app/immutable/chunks/B3bf7yrh.js","_app/immutable/chunks/DCs3KlJy.js","_app/immutable/entry/app.J50e72uV.js","_app/immutable/chunks/B3bf7yrh.js","_app/immutable/chunks/D5lcOOwR.js","_app/immutable/chunks/DCs3KlJy.js","_app/immutable/chunks/DsnmJJEf.js","_app/immutable/chunks/ct9jA5hl.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},
14
14
  nodes: [
15
15
  __memo(() => import('./chunks/0-CUfr8UwD.js')),
16
- __memo(() => import('./chunks/1-Db3AncWW.js')),
16
+ __memo(() => import('./chunks/1-Bg_TotRw.js')),
17
17
  __memo(() => import('./chunks/2-c1bljkMr.js')),
18
- __memo(() => import('./chunks/3-BzEpIldk.js')),
19
- __memo(() => import('./chunks/4-J7bxt5HT.js')),
20
- __memo(() => import('./chunks/5-uwjgYAk8.js')),
21
- __memo(() => import('./chunks/6-Cj4cg3MT.js'))
18
+ __memo(() => import('./chunks/3-BjeVNwGc.js')),
19
+ __memo(() => import('./chunks/4-B_CUNdkn.js')),
20
+ __memo(() => import('./chunks/5-DTv8qrfa.js')),
21
+ __memo(() => import('./chunks/6-Cvu6ZsHJ.js'))
22
22
  ],
23
23
  routes: [
24
24
  {
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sources":["../../.svelte-kit/adapter-node/manifest.js"],"sourcesContent":["export const manifest = (() => {\nfunction __memo(fn) {\n\tlet value;\n\treturn () => value ??= (value = fn());\n}\n\nreturn {\n\tappDir: \"_app\",\n\tappPath: \"_app\",\n\tassets: new Set([\"icons/brands.svg\",\"icons/light.svg\",\"icons/regular.svg\",\"icons/solid.svg\",\"styles.css\"]),\n\tmimeTypes: {\".svg\":\"image/svg+xml\",\".css\":\"text/css\"},\n\t_: {\n\t\tclient: {start:\"_app/immutable/entry/start.CkXOtoPI.js\",app:\"_app/immutable/entry/app.Bexu3pho.js\",imports:[\"_app/immutable/entry/start.CkXOtoPI.js\",\"_app/immutable/chunks/DQ-d8a5w.js\",\"_app/immutable/chunks/D5lcOOwR.js\",\"_app/immutable/chunks/B3bf7yrh.js\",\"_app/immutable/chunks/DCs3KlJy.js\",\"_app/immutable/entry/app.Bexu3pho.js\",\"_app/immutable/chunks/B3bf7yrh.js\",\"_app/immutable/chunks/D5lcOOwR.js\",\"_app/immutable/chunks/DCs3KlJy.js\",\"_app/immutable/chunks/DsnmJJEf.js\",\"_app/immutable/chunks/ct9jA5hl.js\"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},\n\t\tnodes: [\n\t\t\t__memo(() => import('./nodes/0.js')),\n\t\t\t__memo(() => import('./nodes/1.js')),\n\t\t\t__memo(() => import('./nodes/2.js')),\n\t\t\t__memo(() => import('./nodes/3.js')),\n\t\t\t__memo(() => import('./nodes/4.js')),\n\t\t\t__memo(() => import('./nodes/5.js')),\n\t\t\t__memo(() => import('./nodes/6.js'))\n\t\t],\n\t\troutes: [\n\t\t\t{\n\t\t\t\tid: \"/_axium/default\",\n\t\t\t\tpattern: /^\\/_axium\\/default\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 2 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/account\",\n\t\t\t\tpattern: /^\\/account\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 3 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/login\",\n\t\t\t\tpattern: /^\\/login\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 4 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/logout\",\n\t\t\t\tpattern: /^\\/logout\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 5 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/register\",\n\t\t\t\tpattern: /^\\/register\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 6 },\n\t\t\t\tendpoint: null\n\t\t\t}\n\t\t],\n\t\tprerendered_routes: new Set([]),\n\t\tmatchers: async () => {\n\t\t\t\n\t\t\treturn { };\n\t\t},\n\t\tserver_assets: {}\n\t}\n}\n})();\n\nexport const prerendered = new Set([]);\n\nexport const base = \"\";"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manifest.js","sources":["../../.svelte-kit/adapter-node/manifest.js"],"sourcesContent":["export const manifest = (() => {\nfunction __memo(fn) {\n\tlet value;\n\treturn () => value ??= (value = fn());\n}\n\nreturn {\n\tappDir: \"_app\",\n\tappPath: \"_app\",\n\tassets: new Set([\"icons/brands.svg\",\"icons/light.svg\",\"icons/regular.svg\",\"icons/solid.svg\",\"styles.css\"]),\n\tmimeTypes: {\".svg\":\"image/svg+xml\",\".css\":\"text/css\"},\n\t_: {\n\t\tclient: {start:\"_app/immutable/entry/start.CpRP1d0a.js\",app:\"_app/immutable/entry/app.J50e72uV.js\",imports:[\"_app/immutable/entry/start.CpRP1d0a.js\",\"_app/immutable/chunks/Bhc2cIbs.js\",\"_app/immutable/chunks/D5lcOOwR.js\",\"_app/immutable/chunks/B3bf7yrh.js\",\"_app/immutable/chunks/DCs3KlJy.js\",\"_app/immutable/entry/app.J50e72uV.js\",\"_app/immutable/chunks/B3bf7yrh.js\",\"_app/immutable/chunks/D5lcOOwR.js\",\"_app/immutable/chunks/DCs3KlJy.js\",\"_app/immutable/chunks/DsnmJJEf.js\",\"_app/immutable/chunks/ct9jA5hl.js\"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},\n\t\tnodes: [\n\t\t\t__memo(() => import('./nodes/0.js')),\n\t\t\t__memo(() => import('./nodes/1.js')),\n\t\t\t__memo(() => import('./nodes/2.js')),\n\t\t\t__memo(() => import('./nodes/3.js')),\n\t\t\t__memo(() => import('./nodes/4.js')),\n\t\t\t__memo(() => import('./nodes/5.js')),\n\t\t\t__memo(() => import('./nodes/6.js'))\n\t\t],\n\t\troutes: [\n\t\t\t{\n\t\t\t\tid: \"/_axium/default\",\n\t\t\t\tpattern: /^\\/_axium\\/default\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 2 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/account\",\n\t\t\t\tpattern: /^\\/account\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 3 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/login\",\n\t\t\t\tpattern: /^\\/login\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 4 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/logout\",\n\t\t\t\tpattern: /^\\/logout\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 5 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/register\",\n\t\t\t\tpattern: /^\\/register\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 6 },\n\t\t\t\tendpoint: null\n\t\t\t}\n\t\t],\n\t\tprerendered_routes: new Set([]),\n\t\tmatchers: async () => {\n\t\t\t\n\t\t\treturn { };\n\t\t},\n\t\tserver_assets: {}\n\t}\n}\n})();\n\nexport const prerendered = new Set([]);\n\nexport const base = \"\";"],"names":[],"mappings":"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"}
package/dist/acl.d.ts CHANGED
@@ -1,23 +1,23 @@
1
1
  import type { AccessControl, Permission } from '@axium/core';
2
- import type { ExpressionBuilder } from 'kysely';
2
+ import type { Expression, ExpressionBuilder } from 'kysely';
3
3
  import { type Selectable } from 'kysely';
4
4
  import type { UserInternal } from './auth.js';
5
5
  import * as db from './database.js';
6
- interface AccessControllable {
6
+ export interface Target {
7
7
  userId: string;
8
8
  publicPermission: Permission;
9
9
  }
10
10
  type _TableNames = (string & keyof db.Schema) & keyof {
11
- [K in Exclude<keyof db.Schema, `acl.${string}`> as Selectable<db.Schema[K]> extends Omit<AccessControllable, 'acl'> ? K : never]: null;
11
+ [K in Exclude<keyof db.Schema, `acl.${string}`> as Selectable<db.Schema[K]> extends Omit<Target, 'acl'> ? K : never]: null;
12
12
  };
13
13
  /**
14
14
  * `never` causes a ton of problems, so we use `string` if none of the tables are shareable.
15
15
  */
16
- export type AccessControllableTableName = _TableNames extends never ? keyof db.Schema : _TableNames;
16
+ export type TargetName = _TableNames extends never ? keyof db.Schema : _TableNames;
17
17
  export interface AccessControlInternal extends AccessControl {
18
18
  user?: UserInternal;
19
19
  }
20
- export declare const ACLTypes: {
20
+ export declare const expectedTypes: {
21
21
  userId: {
22
22
  type: string;
23
23
  required: true;
@@ -41,14 +41,15 @@ export declare const ACLTypes: {
41
41
  * Adds an Access Control List (ACL) in the database for managing access to rows in an existing table.
42
42
  * @category Plugin API
43
43
  */
44
- export declare function createACL(table: AccessControllableTableName): Promise<void>;
45
- export declare function dropACL(table: AccessControllableTableName): Promise<void>;
46
- export declare function wipeACL(table: AccessControllableTableName): Promise<void>;
47
- export declare function createEntry(itemType: AccessControllableTableName, data: Omit<AccessControl, 'createdAt'>): Promise<AccessControlInternal>;
48
- export declare function deleteEntry(itemType: AccessControllableTableName, itemId: string, userId: string): Promise<void>;
44
+ export declare function createTable(table: TargetName): Promise<void>;
45
+ export declare function dropTable(table: TargetName): Promise<void>;
46
+ export declare function wipeTable(table: TargetName): Promise<void>;
47
+ export declare function createEntry(itemType: TargetName, data: Omit<AccessControl, 'createdAt'>): Promise<AccessControlInternal>;
48
+ export declare function deleteEntry(itemType: TargetName, itemId: string, userId: string): Promise<void>;
49
49
  /**
50
- * Helper to select all shares for a given table, including the user information.
50
+ * Helper to select all access controls for a given table, including the user information.
51
+ * @param onlyId If specified, only returns the access control for the given user ID.
51
52
  */
52
- export declare function sharesFrom(table: AccessControllableTableName): (eb: ExpressionBuilder<db.Schema, any>) => import("kysely").AliasedRawBuilder<Required<AccessControl>[], "shares">;
53
- export declare function getShares(itemType: AccessControllableTableName, itemId: string): Promise<Required<AccessControlInternal>[]>;
53
+ export declare function from(table: TargetName, onlyId?: string | Expression<any>): (eb: ExpressionBuilder<db.Schema, any>) => import("kysely").AliasedRawBuilder<Required<AccessControl>[], "acl">;
54
+ export declare function get(itemType: TargetName, itemId: string): Promise<Required<AccessControlInternal>[]>;
54
55
  export {};
package/dist/acl.js CHANGED
@@ -6,7 +6,7 @@ const accessControllableTypes = {
6
6
  userId: { type: 'uuid' },
7
7
  publicPermission: { type: 'int4' },
8
8
  };
9
- export const ACLTypes = {
9
+ export const expectedTypes = {
10
10
  userId: { type: 'uuid', required: true },
11
11
  createdAt: { type: 'timestamptz', required: true, hasDefault: true },
12
12
  itemId: { type: 'uuid', required: true },
@@ -16,7 +16,7 @@ export const ACLTypes = {
16
16
  * Adds an Access Control List (ACL) in the database for managing access to rows in an existing table.
17
17
  * @category Plugin API
18
18
  */
19
- export async function createACL(table) {
19
+ export async function createTable(table) {
20
20
  await db.checkTableTypes(table, accessControllableTypes, { strict: true, extra: false });
21
21
  io.start(`Creating table acl.${table}`);
22
22
  await db.database.schema
@@ -32,11 +32,11 @@ export async function createACL(table) {
32
32
  await db.createIndex(`acl.${table}`, 'userId');
33
33
  await db.createIndex(`acl.${table}`, 'itemId');
34
34
  }
35
- export async function dropACL(table) {
35
+ export async function dropTable(table) {
36
36
  io.start(`Dropping table acl.${table}`);
37
37
  await db.database.schema.dropTable(`acl.${table}`).execute().then(io.done).catch(db.warnExists);
38
38
  }
39
- export async function wipeACL(table) {
39
+ export async function wipeTable(table) {
40
40
  io.start(`Wiping table acl.${table}`);
41
41
  await db.database.deleteFrom(`acl.${table}`).execute().then(io.done).catch(db.warnExists);
42
42
  }
@@ -47,17 +47,19 @@ export async function deleteEntry(itemType, itemId, userId) {
47
47
  await db.database.deleteFrom(`acl.${itemType}`).where('itemId', '=', itemId).where('userId', '=', userId).execute();
48
48
  }
49
49
  /**
50
- * Helper to select all shares for a given table, including the user information.
50
+ * Helper to select all access controls for a given table, including the user information.
51
+ * @param onlyId If specified, only returns the access control for the given user ID.
51
52
  */
52
- export function sharesFrom(table) {
53
+ export function from(table, onlyId) {
53
54
  return (eb) => jsonArrayFrom(eb
54
55
  .selectFrom(`acl.${table} as _acl`)
55
56
  .selectAll()
56
57
  .select(db.userFromId)
57
- .whereRef(`_acl.itemId`, '=', `${table}.id`))
58
+ .whereRef(`_acl.itemId`, '=', `${table}.id`)
59
+ .$if(!!onlyId, qb => qb.where('userId', '=', onlyId)))
58
60
  .$castTo()
59
- .as('shares');
61
+ .as('acl');
60
62
  }
61
- export async function getShares(itemType, itemId) {
63
+ export async function get(itemType, itemId) {
62
64
  return await db.database.selectFrom(`acl.${itemType}`).where('itemId', '=', itemId).selectAll().select(db.userFromId).execute();
63
65
  }
package/dist/api/acl.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as z from 'zod';
2
2
  import { addRoute } from '../routes.js';
3
3
  import { parseBody, withError } from '../requests.js';
4
- import { createEntry } from '../acl.js';
4
+ import * as acl from '../acl.js';
5
5
  addRoute({
6
6
  path: '/api/acl/:itemType/:itemId',
7
7
  params: {
@@ -15,7 +15,7 @@ addRoute({
15
15
  userId: z.uuid(),
16
16
  permission: z.number().int().min(0).max(5),
17
17
  }));
18
- const share = await createEntry(type, { ...data, itemId }).catch(withError('Failed to create access control'));
18
+ const share = await acl.createEntry(type, { ...data, itemId }).catch(withError('Failed to create access control'));
19
19
  return share;
20
20
  },
21
21
  });
@@ -2,10 +2,10 @@ import { PasskeyChangeable } from '@axium/core/schemas';
2
2
  import { error } from '@sveltejs/kit';
3
3
  import { omit } from 'utilium';
4
4
  import * as z from 'zod';
5
- import { getPasskey } from '../auth.js';
5
+ import { checkAuthForUser, getPasskey } from '../auth.js';
6
6
  import { database as db } from '../database.js';
7
+ import { parseBody, withError } from '../requests.js';
7
8
  import { addRoute } from '../routes.js';
8
- import { checkAuth, parseBody, withError } from '../requests.js';
9
9
  addRoute({
10
10
  path: '/api/passkeys/:id',
11
11
  params: {
@@ -13,13 +13,13 @@ addRoute({
13
13
  },
14
14
  async GET(event) {
15
15
  const passkey = await getPasskey(event.params.id);
16
- await checkAuth(event, passkey.userId);
16
+ await checkAuthForUser(event, passkey.userId);
17
17
  return omit(passkey, 'counter', 'publicKey');
18
18
  },
19
19
  async PATCH(event) {
20
20
  const body = await parseBody(event, PasskeyChangeable);
21
21
  const passkey = await getPasskey(event.params.id);
22
- await checkAuth(event, passkey.userId);
22
+ await checkAuthForUser(event, passkey.userId);
23
23
  const result = await db
24
24
  .updateTable('passkeys')
25
25
  .set(body)
@@ -31,7 +31,7 @@ addRoute({
31
31
  },
32
32
  async DELETE(event) {
33
33
  const passkey = await getPasskey(event.params.id);
34
- await checkAuth(event, passkey.userId);
34
+ await checkAuthForUser(event, passkey.userId);
35
35
  const { count } = await db
36
36
  .selectFrom('passkeys')
37
37
  .select(db.fn.countAll().as('count'))
@@ -1,15 +1,16 @@
1
1
  import { error } from '@sveltejs/kit';
2
2
  import { omit } from 'utilium';
3
- import { authenticate } from '../auth.js';
3
+ import { getSessionAndUser } from '../auth.js';
4
4
  import { connect, database as db } from '../database.js';
5
+ import { getToken, stripUser, withError } from '../requests.js';
5
6
  import { addRoute } from '../routes.js';
6
- import { getToken, stripUser } from '../requests.js';
7
7
  addRoute({
8
8
  path: '/api/session',
9
9
  async GET(event) {
10
- const result = await authenticate(event);
11
- if (!result)
12
- error(404, 'Session does not exist');
10
+ const token = getToken(event);
11
+ if (!token)
12
+ error(401, 'Missing token');
13
+ const result = await getSessionAndUser(token).catch(withError('Invalid session', 400));
13
14
  return {
14
15
  ...omit(result, 'token'),
15
16
  user: stripUser(result.user, true),
package/dist/api/users.js CHANGED
@@ -4,10 +4,10 @@ import * as webauthn from '@simplewebauthn/server';
4
4
  import { error } from '@sveltejs/kit';
5
5
  import { omit, pick } from 'utilium';
6
6
  import * as z from 'zod';
7
- import { createPasskey, createVerification, getPasskey, getPasskeysByUserId, getSessions, getUser, useVerification } from '../auth.js';
7
+ import { checkAuthForUser, createPasskey, createVerification, getPasskey, getPasskeysByUserId, getSessions, getUser, useVerification, } from '../auth.js';
8
8
  import { config } from '../config.js';
9
9
  import { connect, database as db } from '../database.js';
10
- import { checkAuth, createSessionData, parseBody, stripUser, withError } from '../requests.js';
10
+ import { createSessionData, parseBody, stripUser, withError } from '../requests.js';
11
11
  import { addRoute } from '../routes.js';
12
12
  const challenges = new Map();
13
13
  const params = { id: z.uuid() };
@@ -33,14 +33,14 @@ addRoute({
33
33
  params,
34
34
  async GET(event) {
35
35
  const userId = event.params.id;
36
- const auth = await checkAuth(event, userId).catch(() => null);
36
+ const auth = await checkAuthForUser(event, userId).catch(() => null);
37
37
  const user = auth?.user || (await getUser(userId).catch(withError('User does not exist', 404)));
38
38
  return stripUser(user, !!auth);
39
39
  },
40
40
  async PATCH(event) {
41
41
  const userId = event.params.id;
42
42
  const body = await parseBody(event, UserChangeable);
43
- await checkAuth(event, userId);
43
+ await checkAuthForUser(event, userId);
44
44
  if ('email' in body)
45
45
  body.emailVerified = null;
46
46
  const result = await db
@@ -54,7 +54,7 @@ addRoute({
54
54
  },
55
55
  async DELETE(event) {
56
56
  const userId = event.params.id;
57
- await checkAuth(event, userId, true);
57
+ await checkAuthForUser(event, userId, true);
58
58
  const result = await db
59
59
  .deleteFrom('users')
60
60
  .where('id', '=', userId)
@@ -69,7 +69,7 @@ addRoute({
69
69
  params,
70
70
  async GET(event) {
71
71
  const userId = event.params.id;
72
- const { user } = await checkAuth(event, userId);
72
+ const { user } = await checkAuthForUser(event, userId);
73
73
  const sessions = await getSessions(userId);
74
74
  return {
75
75
  ...stripUser(user, true),
@@ -137,7 +137,7 @@ addRoute({
137
137
  async OPTIONS(event) {
138
138
  const userId = event.params.id;
139
139
  const existing = await getPasskeysByUserId(userId);
140
- const { user } = await checkAuth(event, userId);
140
+ const { user } = await checkAuthForUser(event, userId);
141
141
  const options = await webauthn.generateRegistrationOptions({
142
142
  rpName: config.auth.rp_name,
143
143
  rpID: config.auth.rp_id,
@@ -159,7 +159,7 @@ addRoute({
159
159
  */
160
160
  async GET(event) {
161
161
  const userId = event.params.id;
162
- await checkAuth(event, userId);
162
+ await checkAuthForUser(event, userId);
163
163
  const passkeys = await getPasskeysByUserId(userId);
164
164
  return passkeys.map(p => omit(p, 'publicKey', 'counter'));
165
165
  },
@@ -169,7 +169,7 @@ addRoute({
169
169
  async PUT(event) {
170
170
  const userId = event.params.id;
171
171
  const response = await parseBody(event, PasskeyRegistration);
172
- await checkAuth(event, userId);
172
+ await checkAuthForUser(event, userId);
173
173
  const expectedChallenge = registrations.get(userId);
174
174
  if (!expectedChallenge)
175
175
  error(404, { message: 'No registration challenge found for this user' });
@@ -198,13 +198,13 @@ addRoute({
198
198
  params,
199
199
  async GET(event) {
200
200
  const userId = event.params.id;
201
- await checkAuth(event, userId);
201
+ await checkAuthForUser(event, userId);
202
202
  return (await getSessions(userId).catch(e => error(503, 'Failed to get sessions' + (config.debug ? ': ' + e : '')))).map(s => omit(s, 'token'));
203
203
  },
204
204
  async DELETE(event) {
205
205
  const userId = event.params.id;
206
206
  const body = await parseBody(event, LogoutSessions);
207
- await checkAuth(event, userId, body.confirm_all);
207
+ await checkAuthForUser(event, userId, body.confirm_all);
208
208
  if (!body.confirm_all && !Array.isArray(body.id))
209
209
  error(400, { message: 'Invalid request body' });
210
210
  const query = body.confirm_all ? db.deleteFrom('sessions') : db.deleteFrom('sessions').where('sessions.id', 'in', body.id);
@@ -223,14 +223,14 @@ addRoute({
223
223
  const userId = event.params.id;
224
224
  if (!config.auth.email_verification)
225
225
  return { enabled: false };
226
- await checkAuth(event, userId);
226
+ await checkAuthForUser(event, userId);
227
227
  if (!config.auth.email_verification)
228
228
  return { enabled: false };
229
229
  return { enabled: true };
230
230
  },
231
231
  async GET(event) {
232
232
  const userId = event.params.id;
233
- const { user } = await checkAuth(event, userId);
233
+ const { user } = await checkAuthForUser(event, userId);
234
234
  if (user.emailVerified)
235
235
  error(409, { message: 'Email already verified' });
236
236
  const verification = await createVerification('verify_email', userId, config.auth.verification_timeout * 60);
@@ -239,7 +239,7 @@ addRoute({
239
239
  async POST(event) {
240
240
  const userId = event.params.id;
241
241
  const { token } = await parseBody(event, z.object({ token: z.string() }));
242
- const { user } = await checkAuth(event, userId);
242
+ const { user } = await checkAuthForUser(event, userId);
243
243
  if (user.emailVerified)
244
244
  error(409, { message: 'Email already verified' });
245
245
  await useVerification('verify_email', userId, token).catch(withError('Invalid or expired verification token', 400));
package/dist/auth.d.ts CHANGED
@@ -1,7 +1,9 @@
1
+ import type { Permission } from '@axium/core';
1
2
  import type { Passkey, Session, Verification } from '@axium/core/api';
2
3
  import type { User } from '@axium/core/user';
3
- import type { RequestEvent } from '@sveltejs/kit';
4
+ import { type RequestEvent } from '@sveltejs/kit';
4
5
  import type { Insertable } from 'kysely';
6
+ import * as acl from './acl.js';
5
7
  import { type Schema } from './database.js';
6
8
  export interface UserInternal extends User {
7
9
  isAdmin: boolean;
@@ -39,4 +41,15 @@ export declare function getPasskey(id: string): Promise<PasskeyInternal>;
39
41
  export declare function createPasskey(passkey: Omit<PasskeyInternal, 'createdAt'>): Promise<PasskeyInternal>;
40
42
  export declare function getPasskeysByUserId(userId: string): Promise<PasskeyInternal[]>;
41
43
  export declare function updatePasskeyCounter(id: PasskeyInternal['id'], newCounter: PasskeyInternal['counter']): Promise<PasskeyInternal>;
42
- export declare function authenticate(event: RequestEvent): Promise<SessionAndUser | null>;
44
+ export interface UserAuthResult extends SessionAndUser {
45
+ /** The user authenticating the request. */
46
+ accessor: UserInternal;
47
+ }
48
+ export declare function checkAuthForUser(event: RequestEvent, userId: string, sensitive?: boolean): Promise<UserAuthResult>;
49
+ export interface ItemAuthResult<T extends acl.Target> {
50
+ fromACL: boolean;
51
+ item: T;
52
+ user?: UserInternal;
53
+ session?: SessionInternal;
54
+ }
55
+ export declare function checkAuthForItem<const V extends acl.Target>(event: RequestEvent, itemType: acl.TargetName, itemId: string, permission: Permission): Promise<ItemAuthResult<V>>;
package/dist/auth.js CHANGED
@@ -1,6 +1,9 @@
1
+ import { error } from '@sveltejs/kit';
1
2
  import { randomBytes, randomUUID } from 'node:crypto';
3
+ import { omit } from 'utilium';
4
+ import * as acl from './acl.js';
2
5
  import { connect, database as db, userFromId } from './database.js';
3
- import { getToken } from './requests.js';
6
+ import { getToken, withError } from './requests.js';
4
7
  export async function getUser(id) {
5
8
  connect();
6
9
  return await db.selectFrom('users').selectAll().where('id', '=', id).executeTakeFirstOrThrow();
@@ -95,10 +98,56 @@ export async function updatePasskeyCounter(id, newCounter) {
95
98
  throw new Error('Passkey not found');
96
99
  return passkey;
97
100
  }
98
- export async function authenticate(event) {
99
- const maybe_header = event.request.headers.get('Authorization');
100
- const token = maybe_header?.startsWith('Bearer ') ? maybe_header.slice(7) : event.cookies.get('session_token');
101
+ export async function checkAuthForUser(event, userId, sensitive = false) {
102
+ const token = getToken(event, sensitive);
101
103
  if (!token)
102
- return null;
103
- return await getSessionAndUser(token).catch(() => null);
104
+ throw error(401, 'Missing token');
105
+ const session = await getSessionAndUser(token).catch(withError('Invalid or expired session', 401));
106
+ if (session.userId !== userId) {
107
+ if (!session.user?.isAdmin)
108
+ error(403, 'User ID mismatch');
109
+ // Admins are allowed to manage other users.
110
+ const accessor = session.user;
111
+ session.user = await getUser(userId).catch(withError('Target user not found', 404));
112
+ return Object.assign(session, { accessor });
113
+ }
114
+ if (!session.elevated && sensitive)
115
+ error(403, 'This token can not be used for sensitive actions');
116
+ return Object.assign(session, { accessor: session.user });
117
+ }
118
+ export async function checkAuthForItem(event, itemType, itemId, permission) {
119
+ const token = getToken(event, true);
120
+ if (!token)
121
+ error(401, 'Missing token');
122
+ connect();
123
+ const session = await getSessionAndUser(token).catch(() => null);
124
+ const item = await db
125
+ .selectFrom(itemType)
126
+ .selectAll()
127
+ .where('id', '=', itemId)
128
+ .$if(!!session, eb => eb.select(acl.from(itemType, session.userId)))
129
+ .$castTo()
130
+ .executeTakeFirstOrThrow()
131
+ .catch(withError('Item not found', 404));
132
+ const result = {
133
+ session: session ? omit(session, 'user') : undefined,
134
+ item: omit(item, 'acl'),
135
+ user: session?.user,
136
+ fromACL: false,
137
+ };
138
+ if (item.publicPermission >= permission)
139
+ return result;
140
+ if (!session)
141
+ error(403, 'Access denied');
142
+ if (session.userId == item.userId)
143
+ return result;
144
+ result.fromACL = true;
145
+ if (!item.acl || !item.acl.length)
146
+ error(403, 'Access denied');
147
+ const [control] = item.acl;
148
+ if (control.userId !== session.userId)
149
+ error(500, 'Access control entry does not match session user'); // @todo: audit log
150
+ if (control.permission >= permission)
151
+ return result;
152
+ error(403, 'Access denied');
104
153
  }
@@ -3,6 +3,12 @@ import type { AuthenticatorTransportFuture, CredentialDeviceType } from '@simple
3
3
  import type * as kysely from 'kysely';
4
4
  import { Kysely } from 'kysely';
5
5
  import type { UserInternal, VerificationRole } from './auth.js';
6
+ export interface DBAccessControl {
7
+ itemId: string;
8
+ userId: string;
9
+ createdAt: kysely.GeneratedAlways<Date>;
10
+ permission: Permission;
11
+ }
6
12
  export interface Schema {
7
13
  users: {
8
14
  id: string;
@@ -41,12 +47,7 @@ export interface Schema {
41
47
  backedUp: boolean;
42
48
  transports: AuthenticatorTransportFuture[];
43
49
  };
44
- [key: `acl.${string}`]: {
45
- itemId: string;
46
- userId: string;
47
- createdAt: kysely.GeneratedAlways<Date>;
48
- permission: Permission;
49
- };
50
+ [key: `acl.${string}`]: DBAccessControl;
50
51
  }
51
52
  export type Database = Kysely<Schema> & AsyncDisposable;
52
53
  export declare let database: Database;
package/dist/database.js CHANGED
@@ -58,7 +58,6 @@ import pg from 'pg';
58
58
  import config from './config.js';
59
59
  import * as io from './io.js';
60
60
  import { plugins } from './plugins.js';
61
- import * as acl from './acl.js';
62
61
  const sym = Symbol.for('Axium:database');
63
62
  export let database;
64
63
  export function connect() {
@@ -1,14 +1,9 @@
1
1
  import { type User } from '@axium/core/user';
2
2
  import { type HttpError, type RequestEvent } from '@sveltejs/kit';
3
3
  import * as z from 'zod';
4
- import { type SessionAndUser, type UserInternal } from './auth.js';
4
+ import { type UserInternal } from './auth.js';
5
5
  export declare function parseBody<const Schema extends z.ZodType, const Result extends z.infer<Schema> = z.infer<Schema>>(event: RequestEvent, schema: Schema): Promise<Result>;
6
6
  export declare function getToken(event: RequestEvent, sensitive?: boolean): string | undefined;
7
- export interface AuthResult extends SessionAndUser {
8
- /** The user authenticating the request. */
9
- accessor: UserInternal;
10
- }
11
- export declare function checkAuth(event: RequestEvent, userId: string, sensitive?: boolean): Promise<AuthResult>;
12
7
  export declare function createSessionData(userId: string, elevated?: boolean): Promise<Response>;
13
8
  export declare function stripUser(user: UserInternal, includeProtected?: boolean): User;
14
9
  export declare function withError(text: string, code?: number): (e: Error | HttpError) => never;
package/dist/requests.js CHANGED
@@ -25,23 +25,6 @@ export function getToken(event, sensitive = false) {
25
25
  return event.cookies.get(sensitive ? 'elevated_token' : 'session_token');
26
26
  }
27
27
  }
28
- export async function checkAuth(event, userId, sensitive = false) {
29
- const token = getToken(event, sensitive);
30
- if (!token)
31
- throw error(401, { message: 'Missing token' });
32
- const session = await getSessionAndUser(token).catch(() => error(401, { message: 'Invalid or expired session' }));
33
- if (session.userId !== userId) {
34
- if (!session.user?.isAdmin)
35
- error(403, { message: 'User ID mismatch' });
36
- // Admins are allowed to manage other users.
37
- const accessor = session.user;
38
- session.user = await getUser(userId).catch(() => error(404, { message: 'Target user not found' }));
39
- return Object.assign(session, { accessor });
40
- }
41
- if (!session.elevated && sensitive)
42
- error(403, 'This token can not be used for sensitive actions');
43
- return Object.assign(session, { accessor: session.user });
44
- }
45
28
  export async function createSessionData(userId, elevated = false) {
46
29
  const { token, expires } = await createSession(userId, elevated);
47
30
  const response = json({ userId, token: elevated ? '[[redacted:elevated]]' : token }, { status: 201 });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axium/server",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "author": "James Prevett <axium@jamespre.dev> (https://jamespre.dev)",
5
5
  "funding": {
6
6
  "type": "individual",
@@ -1 +0,0 @@
1
- import{l as o,a as r}from"../chunks/DQ-d8a5w.js";export{o as load_css,r as start};
@@ -1,2 +0,0 @@
1
- )�import{l as o,a as r}from"../chunks/DQ-d8a5w.js";export{o as load_css,r as start};
2
- 
@@ -1 +0,0 @@
1
- import"../chunks/DsnmJJEf.js";import{L as t}from"../chunks/BIqJFsZ3.js";function r(o){t(o,{fullPage:!0})}export{r as component};