@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.
- package/build/client/_app/immutable/chunks/{BQEW-soH.js → BKTxLcVa.js} +1 -1
- package/build/client/_app/immutable/chunks/BKTxLcVa.js.br +0 -0
- package/build/client/_app/immutable/chunks/BKTxLcVa.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{DQ-d8a5w.js → Bhc2cIbs.js} +2 -2
- package/build/client/_app/immutable/chunks/Bhc2cIbs.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bhc2cIbs.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{ClV-nJVy.js → DecEAa7H.js} +1 -1
- package/build/client/_app/immutable/chunks/DecEAa7H.js.br +0 -0
- package/build/client/_app/immutable/chunks/{ClV-nJVy.js.gz → DecEAa7H.js.gz} +0 -0
- package/build/client/_app/immutable/chunks/{BIqJFsZ3.js → uGVpjdha.js} +1 -1
- package/build/client/_app/immutable/chunks/uGVpjdha.js.br +0 -0
- package/build/client/_app/immutable/chunks/uGVpjdha.js.gz +0 -0
- package/build/client/_app/immutable/entry/{app.Bexu3pho.js → app.J50e72uV.js} +2 -2
- package/build/client/_app/immutable/entry/app.J50e72uV.js.br +0 -0
- package/build/client/_app/immutable/entry/app.J50e72uV.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.CpRP1d0a.js +1 -0
- package/build/client/_app/immutable/entry/start.CpRP1d0a.js.br +2 -0
- package/build/client/_app/immutable/entry/start.CpRP1d0a.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{1.Di0t29Xx.js → 1.rTsuaAPg.js} +1 -1
- package/build/client/_app/immutable/nodes/1.rTsuaAPg.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.rTsuaAPg.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{3.dB5xKZIR.js → 3.BYti3cIq.js} +1 -1
- package/build/client/_app/immutable/nodes/3.BYti3cIq.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.BYti3cIq.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{4.DC1TCp7U.js → 4.CBowWWW9.js} +1 -1
- package/build/client/_app/immutable/nodes/4.CBowWWW9.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.CBowWWW9.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.BpAkygAb.js +1 -0
- package/build/client/_app/immutable/nodes/5.BpAkygAb.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.BpAkygAb.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{6.WTfzqOhT.js → 6.CdqSI5TW.js} +1 -1
- package/build/client/_app/immutable/nodes/6.CdqSI5TW.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.CdqSI5TW.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/server/chunks/{1-Db3AncWW.js → 1-Bg_TotRw.js} +2 -2
- package/build/server/chunks/{1-Db3AncWW.js.map → 1-Bg_TotRw.js.map} +1 -1
- package/build/server/chunks/{3-BzEpIldk.js → 3-BjeVNwGc.js} +2 -2
- package/build/server/chunks/{3-BzEpIldk.js.map → 3-BjeVNwGc.js.map} +1 -1
- package/build/server/chunks/{4-J7bxt5HT.js → 4-B_CUNdkn.js} +2 -2
- package/build/server/chunks/{4-J7bxt5HT.js.map → 4-B_CUNdkn.js.map} +1 -1
- package/build/server/chunks/{5-uwjgYAk8.js → 5-DTv8qrfa.js} +2 -2
- package/build/server/chunks/{5-uwjgYAk8.js.map → 5-DTv8qrfa.js.map} +1 -1
- package/build/server/chunks/{6-Cj4cg3MT.js → 6-Cvu6ZsHJ.js} +2 -2
- package/build/server/chunks/{6-Cj4cg3MT.js.map → 6-Cvu6ZsHJ.js.map} +1 -1
- package/build/server/index.js +1 -1
- package/build/server/index.js.map +1 -1
- package/build/server/manifest.js +6 -6
- package/build/server/manifest.js.map +1 -1
- package/dist/acl.d.ts +14 -13
- package/dist/acl.js +11 -9
- package/dist/api/acl.js +2 -2
- package/dist/api/passkeys.js +5 -5
- package/dist/api/session.js +6 -5
- package/dist/api/users.js +14 -14
- package/dist/auth.d.ts +15 -2
- package/dist/auth.js +55 -6
- package/dist/database.d.ts +7 -6
- package/dist/database.js +0 -1
- package/dist/requests.d.ts +1 -6
- package/dist/requests.js +0 -17
- package/package.json +1 -1
- package/build/client/_app/immutable/chunks/BIqJFsZ3.js.br +0 -0
- package/build/client/_app/immutable/chunks/BIqJFsZ3.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BQEW-soH.js.br +0 -0
- package/build/client/_app/immutable/chunks/BQEW-soH.js.gz +0 -0
- package/build/client/_app/immutable/chunks/ClV-nJVy.js.br +0 -0
- package/build/client/_app/immutable/chunks/DQ-d8a5w.js.br +0 -0
- package/build/client/_app/immutable/chunks/DQ-d8a5w.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.Bexu3pho.js.br +0 -0
- package/build/client/_app/immutable/entry/app.Bexu3pho.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.CkXOtoPI.js +0 -1
- package/build/client/_app/immutable/entry/start.CkXOtoPI.js.br +0 -2
- package/build/client/_app/immutable/entry/start.CkXOtoPI.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.Di0t29Xx.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.Di0t29Xx.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.dB5xKZIR.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.dB5xKZIR.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.DC1TCp7U.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.DC1TCp7U.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.DGB0QJIF.js +0 -1
- package/build/client/_app/immutable/nodes/5.DGB0QJIF.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.DGB0QJIF.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.WTfzqOhT.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.WTfzqOhT.js.gz +0 -0
package/build/server/manifest.js
CHANGED
|
@@ -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.
|
|
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-
|
|
16
|
+
__memo(() => import('./chunks/1-Bg_TotRw.js')),
|
|
17
17
|
__memo(() => import('./chunks/2-c1bljkMr.js')),
|
|
18
|
-
__memo(() => import('./chunks/3-
|
|
19
|
-
__memo(() => import('./chunks/4-
|
|
20
|
-
__memo(() => import('./chunks/5-
|
|
21
|
-
__memo(() => import('./chunks/6-
|
|
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.
|
|
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
|
|
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<
|
|
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
|
|
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
|
|
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
|
|
45
|
-
export declare function
|
|
46
|
-
export declare function
|
|
47
|
-
export declare function createEntry(itemType:
|
|
48
|
-
export declare function deleteEntry(itemType:
|
|
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
|
|
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
|
|
53
|
-
export declare function
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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('
|
|
61
|
+
.as('acl');
|
|
60
62
|
}
|
|
61
|
-
export async function
|
|
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
|
|
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
|
});
|
package/dist/api/passkeys.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
34
|
+
await checkAuthForUser(event, passkey.userId);
|
|
35
35
|
const { count } = await db
|
|
36
36
|
.selectFrom('passkeys')
|
|
37
37
|
.select(db.fn.countAll().as('count'))
|
package/dist/api/session.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { error } from '@sveltejs/kit';
|
|
2
2
|
import { omit } from 'utilium';
|
|
3
|
-
import {
|
|
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
|
|
11
|
-
if (!
|
|
12
|
-
error(
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
99
|
-
const
|
|
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
|
-
|
|
103
|
-
|
|
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
|
}
|
package/dist/database.d.ts
CHANGED
|
@@ -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() {
|
package/dist/requests.d.ts
CHANGED
|
@@ -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
|
|
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
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{l as o,a as r}from"../chunks/DQ-d8a5w.js";export{o as load_css,r as start};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|