@rebasepro/server 0.13.0 → 0.13.1-canary.g249daa1
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_block-CcSGdH7M.js → admin_block-CLeUMG8G.js} +3 -1
- package/dist/admin_block-CLeUMG8G.js.map +1 -0
- package/dist/api/errors.d.ts +0 -6
- package/dist/api/openapi-generator.d.ts +14 -0
- package/dist/api/rest/idempotency.d.ts +41 -4
- package/dist/api/rest/write-validation.d.ts +12 -5
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/jwt.d.ts +12 -0
- package/dist/{auth-CuC9M2x6.js → auth-BANhRhN9.js} +194 -84
- package/dist/auth-BANhRhN9.js.map +1 -0
- package/dist/{backup-CVggVhR2.js → backup-BJiY_mM-.js} +2 -2
- package/dist/{backup-CVggVhR2.js.map → backup-BJiY_mM-.js.map} +1 -1
- package/dist/boot/boot.d.ts +19 -0
- package/dist/boot/ddl-bootstrap.d.ts +70 -0
- package/dist/{contract-routes-Dj8i5AiM.js → contract-routes-FSt0Nyfk.js} +2 -2
- package/dist/{contract-routes-Dj8i5AiM.js.map → contract-routes-FSt0Nyfk.js.map} +1 -1
- package/dist/cron/cron-scheduler.d.ts +8 -3
- package/dist/cron/define-cron.d.ts +5 -3
- package/dist/{cron-routes-CrQ0tK-_.js → cron-routes-D5a9v1HY.js} +2 -2
- package/dist/{cron-routes-CrQ0tK-_.js.map → cron-routes-D5a9v1HY.js.map} +1 -1
- package/dist/{cron-scheduler-B3RFt0HS.js → cron-scheduler-CsQtYLMq.js} +28 -3
- package/dist/cron-scheduler-CsQtYLMq.js.map +1 -0
- package/dist/{cron-store-BywZsyfZ.js → cron-store-ZbjfuvMb.js} +65 -46
- package/dist/cron-store-ZbjfuvMb.js.map +1 -0
- package/dist/ddl-bootstrap-Bp3mr6Td.js +183 -0
- package/dist/ddl-bootstrap-Bp3mr6Td.js.map +1 -0
- package/dist/{errors-CgkCzoj7.js → errors-BpudWAVU.js} +2 -10
- package/dist/errors-BpudWAVU.js.map +1 -0
- package/dist/functions/define-function.d.ts +1 -1
- package/dist/history/history-routes.d.ts +6 -0
- package/dist/index.es.js +835 -276
- package/dist/index.es.js.map +1 -1
- package/dist/{jwt-DD6EtpGj.js → jwt-CzeviDcB.js} +17 -2
- package/dist/{jwt-DD6EtpGj.js.map → jwt-CzeviDcB.js.map} +1 -1
- package/dist/{openapi-generator-BEwyiaAr.js → openapi-generator-VB0MUH8h.js} +340 -128
- package/dist/openapi-generator-VB0MUH8h.js.map +1 -0
- package/dist/{schema-editor-routes-CbF20Mf1.js → schema-editor-routes-BqjzvvWU.js} +4 -4
- package/dist/{schema-editor-routes-CbF20Mf1.js.map → schema-editor-routes-BqjzvvWU.js.map} +1 -1
- package/dist/{src-_qQ3RNCK.js → src-Ca6NhxKs.js} +79 -2
- package/dist/src-Ca6NhxKs.js.map +1 -0
- package/dist/{src-Cum9kox5.js → src-DVb5a0bp.js} +153 -39
- package/dist/src-DVb5a0bp.js.map +1 -0
- package/dist/storage/keys.d.ts +65 -0
- package/dist/utils/logging.d.ts +0 -4
- package/dist/utils/sql.d.ts +11 -6
- package/package.json +6 -6
- package/dist/admin_block-CcSGdH7M.js.map +0 -1
- package/dist/auth-CuC9M2x6.js.map +0 -1
- package/dist/backend-CIxN4FVm.js +0 -15
- package/dist/backend-CIxN4FVm.js.map +0 -1
- package/dist/cron-scheduler-B3RFt0HS.js.map +0 -1
- package/dist/cron-store-BywZsyfZ.js.map +0 -1
- package/dist/errors-CgkCzoj7.js.map +0 -1
- package/dist/openapi-generator-BEwyiaAr.js.map +0 -1
- package/dist/src-Cum9kox5.js.map +0 -1
- package/dist/src-_qQ3RNCK.js.map +0 -1
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical storage keys.
|
|
3
|
+
*
|
|
4
|
+
* Storage is not under RLS, so a `storageAuthorize` hook is the whole access
|
|
5
|
+
* control model — and a hook can only be correct if the key it is shown is the
|
|
6
|
+
* key that is written. That is the invariant this module exists to hold: one
|
|
7
|
+
* canonical string, computed once per request, handed to the hook, to the
|
|
8
|
+
* controller, and to the download token alike.
|
|
9
|
+
*
|
|
10
|
+
* ## Why rejecting beats stripping
|
|
11
|
+
*
|
|
12
|
+
* The previous `sanitizeStorageKey` *stripped* `../` in a single pass. Two
|
|
13
|
+
* things were wrong with that, and only one of them was the obvious one.
|
|
14
|
+
*
|
|
15
|
+
* The obvious one: a single pass is not a fixed point. `....//` contains `../`
|
|
16
|
+
* at offset 2, so removing it leaves `../` behind — the sanitizer manufactured
|
|
17
|
+
* the traversal it was there to remove. `users/alice/....//bob/x` came out as
|
|
18
|
+
* `users/alice/../bob/x`, which a prefix hook reads as alice's (it starts with
|
|
19
|
+
* `users/alice/`) and the filesystem reads as bob's. The hook approved one
|
|
20
|
+
* object and the controller wrote another.
|
|
21
|
+
*
|
|
22
|
+
* The subtler one, and the reason this is a rewrite rather than a loop: even a
|
|
23
|
+
* correct strip is a silent rewrite. A caller who asks to store at `a/../b` and
|
|
24
|
+
* gets an object at `a/b` was not protected, they were misled — and every later
|
|
25
|
+
* read, ownership row and audit line now refers to a path nobody chose. So a key
|
|
26
|
+
* that means something other than what it says is refused (400), not repaired.
|
|
27
|
+
*
|
|
28
|
+
* Note what is NOT traversal under this rule: `....` is an ordinary directory
|
|
29
|
+
* name, and `users/alice/....//bob/x` canonicalizes to
|
|
30
|
+
* `users/alice/..../bob/x` — still comfortably inside alice's prefix, which is
|
|
31
|
+
* exactly right. Only a real `..` segment is refused.
|
|
32
|
+
*/
|
|
33
|
+
/** Longest key accepted, in UTF-16 code units. Matches the previous cap. */
|
|
34
|
+
export declare const MAX_STORAGE_KEY_LENGTH = 1024;
|
|
35
|
+
/**
|
|
36
|
+
* A key that cannot be canonicalized. Carries no path back to the caller
|
|
37
|
+
* beyond what they sent, so it is safe to surface as a 400 message.
|
|
38
|
+
*/
|
|
39
|
+
export declare class InvalidStorageKeyError extends Error {
|
|
40
|
+
constructor(message: string);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Canonicalize a caller-supplied storage key, or throw
|
|
44
|
+
* {@link InvalidStorageKeyError}.
|
|
45
|
+
*
|
|
46
|
+
* Normalizations applied (safe, idempotent, and meaning-preserving):
|
|
47
|
+
* - leading slashes removed — `/a/b` and `a/b` name the same object
|
|
48
|
+
* - `.` segments and repeated slashes collapsed
|
|
49
|
+
*
|
|
50
|
+
* Refusals (the key means something other than what it says):
|
|
51
|
+
* - any `..` segment, on either separator, at any depth
|
|
52
|
+
* - null bytes
|
|
53
|
+
* - keys longer than {@link MAX_STORAGE_KEY_LENGTH}
|
|
54
|
+
*
|
|
55
|
+
* A trailing slash is preserved: it is how the folder route marks a prefix.
|
|
56
|
+
*/
|
|
57
|
+
export declare function canonicalStorageKey(rawKey: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Canonicalize, or return `null` when the key is not canonicalizable.
|
|
60
|
+
*
|
|
61
|
+
* For callers that must fail closed without an exception — the download-token
|
|
62
|
+
* middleware compares a request path against a granted path, and a key it
|
|
63
|
+
* cannot canonicalize simply matches nothing.
|
|
64
|
+
*/
|
|
65
|
+
export declare function tryCanonicalStorageKey(rawKey: string): string | null;
|
package/dist/utils/logging.d.ts
CHANGED
package/dist/utils/sql.d.ts
CHANGED
|
@@ -1,27 +1,32 @@
|
|
|
1
1
|
import { SQL } from "drizzle-orm";
|
|
2
2
|
/**
|
|
3
|
-
* Returns a SQL chunk calling `
|
|
4
|
-
* This is a PostgreSQL RLS helper function created in the `
|
|
3
|
+
* Returns a SQL chunk calling `rebase.uid()` — the current user's ID.
|
|
4
|
+
* This is a PostgreSQL RLS helper function created in the `rebase` schema
|
|
5
5
|
* that reads `app.uid` set per-transaction by `withAuth()`.
|
|
6
6
|
*
|
|
7
|
+
* The function moved from `auth.uid()` to `rebase.uid()` in 1.0 — `auth` is
|
|
8
|
+
* Supabase's schema, and taking it meant Rebase could not be pointed at a
|
|
9
|
+
* database that already had one. Use this helper rather than writing the call
|
|
10
|
+
* by hand and the move costs you nothing.
|
|
11
|
+
*
|
|
7
12
|
* @example
|
|
8
13
|
* sql`${table.uid} = ${authUid()}`
|
|
9
14
|
*/
|
|
10
15
|
export declare const authUid: () => SQL;
|
|
11
16
|
/**
|
|
12
|
-
* Returns a SQL chunk calling `
|
|
17
|
+
* Returns a SQL chunk calling `rebase.roles()` — the current user's roles
|
|
13
18
|
* as a comma-separated string.
|
|
14
19
|
* Reads `app.user_roles` set per-transaction by `withAuth()`.
|
|
15
20
|
*
|
|
16
21
|
* @example
|
|
17
|
-
* sql
|
|
22
|
+
* sql`${authRoles()} ~ 'admin'`
|
|
18
23
|
*/
|
|
19
24
|
export declare const authRoles: () => SQL;
|
|
20
25
|
/**
|
|
21
|
-
* Returns a SQL chunk calling `
|
|
26
|
+
* Returns a SQL chunk calling `rebase.jwt()` — the full JWT claims as JSONB.
|
|
22
27
|
* Reads `app.jwt` set per-transaction by `withAuth()`.
|
|
23
28
|
*
|
|
24
29
|
* @example
|
|
25
|
-
* sql
|
|
30
|
+
* sql`${authJwt()}->>'sub'`
|
|
26
31
|
*/
|
|
27
32
|
export declare const authJwt: () => SQL;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/server",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.13.
|
|
4
|
+
"version": "0.13.1-canary.g249daa1",
|
|
5
5
|
"description": "Database-Agnostic Backend Core for Rebase",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/rebaseco"
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"jsonwebtoken": "^9.0.3",
|
|
45
45
|
"ws": "^8.21.1",
|
|
46
46
|
"zod": "^4.4.3",
|
|
47
|
-
"@rebasepro/client": "0.13.
|
|
48
|
-
"@rebasepro/common": "0.13.
|
|
49
|
-
"@rebasepro/types": "0.13.
|
|
50
|
-
"@rebasepro/utils": "0.13.
|
|
47
|
+
"@rebasepro/client": "0.13.1-canary.g249daa1",
|
|
48
|
+
"@rebasepro/common": "0.13.1-canary.g249daa1",
|
|
49
|
+
"@rebasepro/types": "0.13.1-canary.g249daa1",
|
|
50
|
+
"@rebasepro/utils": "0.13.1-canary.g249daa1"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@jest/globals": "^30.4.1",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@types/nodemailer": "^8.0.1",
|
|
58
58
|
"@types/ws": "^8.18.1",
|
|
59
59
|
"cross-env": "^10.1.0",
|
|
60
|
-
"hono": "^4.
|
|
60
|
+
"hono": "^4.13.0",
|
|
61
61
|
"jest": "^30.4.2",
|
|
62
62
|
"ts-jest": "29.4.12",
|
|
63
63
|
"typescript": "^6.0.3",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"admin_block-CcSGdH7M.js","names":[],"sources":["../../types/src/types/admin_block.ts"],"sourcesContent":["/**\n * The keys of a collection's admin block, as data.\n *\n * There is no *type* for the block in this package any more, and that is the point:\n * `admin` is not declared on `BaseCollectionConfig` or on any property here, so a\n * BaaS install cannot even write one. `@rebasepro/admin-types` adds the field back by\n * declaration merging, which is why installing it is what makes the admin surface\n * appear.\n *\n * The *list* still has to live here, because three runtime consumers need it and two\n * of them are core — see below.\n */\n\n/**\n * Every key that belongs inside a collection's `admin` block, as data.\n *\n * The type that describes these fields is `AdminCollectionOptions` in\n * `@rebasepro/admin-types`, and it is erased at build time — but three runtime\n * consumers need the list, and two of them are core:\n *\n * - `serializeCollections`, to drop the block from the contract\n * - the ts-morph schema editor in `@rebasepro/server`, which rewrites collection\n * files on disk from the admin panel and has to know where each key goes. A key\n * missing from this list gets written to the *top level* of the file, where the\n * backend ignores it and the panel never finds it again.\n * - the `collections-admin-block` codemod\n *\n * `@rebasepro/admin-types` re-exports this and asserts it names only real option\n * keys; the count is pinned by a test there.\n *\n * @group Models\n */\nexport const ADMIN_COLLECTION_KEYS = [\n \"Actions\",\n \"additionalFields\",\n \"alwaysApplyDefaultValues\",\n \"components\",\n \"defaultEntityAction\",\n \"defaultFilter\",\n \"defaultSelectedView\",\n \"defaultSize\",\n \"defaultViewMode\",\n \"disableDefaultActions\",\n \"enabledViews\",\n \"entityActions\",\n \"entityViews\",\n \"exportable\",\n \"filterPresets\",\n \"fixedFilter\",\n \"form\",\n \"formAutoSave\",\n \"formView\",\n \"group\",\n \"hideFromNavigation\",\n \"hideIdFromCollection\",\n \"hideIdFromForm\",\n \"icon\",\n \"includeJsonView\",\n \"inlineEditing\",\n \"kanban\",\n \"listProperties\",\n \"localChangesBackup\",\n \"openEntityMode\",\n \"orderProperty\",\n \"pagination\",\n \"previewProperties\",\n \"propertiesOrder\",\n \"selectionController\",\n \"selectionEnabled\",\n \"sideDialogWidth\",\n \"sort\",\n \"titleProperty\"\n] as const;\n\n/** A key of a collection's `admin` block. @group Models */\nexport type AdminCollectionKey = typeof ADMIN_COLLECTION_KEYS[number];\n\n/**\n * Every key that belongs inside a *property's* `admin` block, as data.\n *\n * The union of `AdminPropertyOptions` and its per-type extensions\n * (`AdminStringOptions`, `AdminArrayOptions`, …) in `@rebasepro/admin-types`.\n * It lives here for the same reason {@link ADMIN_COLLECTION_KEYS} does: the\n * runtime consumers are core packages that the BaaS guard forbids from\n * importing `@rebasepro/admin-types`. Here it is the boot-time collection\n * validator in `@rebasepro/server`, which has to tell \"you left `readOnly` at\n * the top of the property, where nothing reads it\" apart from \"you invented a\n * key we have never heard of\".\n *\n * `@rebasepro/admin-types` re-exports this and asserts it names only real\n * option keys.\n *\n * @group Models\n */\nexport const ADMIN_PROPERTY_KEYS = [\n \"canAddElements\",\n \"clearable\",\n \"columnWidth\",\n \"customProps\",\n \"disabled\",\n \"expanded\",\n \"Field\",\n \"Filter\",\n \"filterOperators\",\n \"fixedFilter\",\n \"hideFromCollection\",\n \"includeEntityLink\",\n \"includeId\",\n \"markdown\",\n \"minimalistView\",\n \"multiline\",\n \"Preview\",\n \"previewAsTag\",\n \"previewProperties\",\n \"readOnly\",\n \"sortable\",\n \"span\",\n \"spreadChildren\",\n \"urlPreview\",\n \"widget\",\n] as const;\n\n/** A key of a property's `admin` block. @group Models */\nexport type AdminPropertyKey = typeof ADMIN_PROPERTY_KEYS[number];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAa,wBAAwB;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACJ;;;;;;;;;;;;;;;;;;AAsBA,IAAa,sBAAsB;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACJ"}
|