@90soft/parse-server-kit 2.13.0 → 2.14.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/CHANGELOG.md CHANGED
@@ -8,6 +8,72 @@ All notable changes to `@90soft/parse-server-kit`.
8
8
 
9
9
  ---
10
10
 
11
+ ## [2.14.0]
12
+
13
+ ### Changed — BREAKING (file access rules)
14
+
15
+ - **The owning row's ACL is now evaluated at READ time, for every file. The
16
+ prefix and the per-class flag are gone.**
17
+
18
+ 2.12.0/2.13.0 marked files governed at UPLOAD time, by storing them under a
19
+ prefix. That cannot work for an application where content moves between
20
+ public and private, and the reason is structural: **storage location is
21
+ permanent, visibility is not.** A file stored while its row was public stays
22
+ world-readable forever, whatever the row later says — and the failure is
23
+ invisible, because the file loads perfectly.
24
+
25
+ Now every file is stored under `<ClassName>/<objectId>/`, so the path always
26
+ names its owner, and permission is decided on each request from that row's
27
+ ACL:
28
+
29
+ | | before | now |
30
+ |---|---|---|
31
+ | row made private | needed the bytes re-stored | takes effect on the next request |
32
+ | row made public | needed the bytes re-stored | takes effect immediately |
33
+ | class becomes public | flag flip **+ re-upload every file** | nothing to do |
34
+ | per-row visibility | inexpressible | the normal case |
35
+
36
+ | 2.13.0 | 2.14.0 |
37
+ |---|---|
38
+ | `acl/<Class>/<objectId>/` | `<Class>/<objectId>/` |
39
+ | `ACL_PREFIX` | *gone* |
40
+ | `isAclGoverned` | *gone* — every path is governed |
41
+ | `aclOwnerOf` | `fileOwnerOf` |
42
+ | `aclDirectoryFor` | `ownerDirectoryFor` |
43
+ | `attachAclFile` | `attachOwnedFile` |
44
+ | `aclFileRule` | `rowAclFileRule` |
45
+ | `AclFileOwner` | `FileOwner` |
46
+ | `AclFileRuleOptions` | `RowAclFileRuleOptions` |
47
+
48
+ **A path with no identifiable owner is REFUSED**, so files stored before this
49
+ (flat names, or under the old prefix) stop serving until re-uploaded. That is
50
+ deliberate: the alternative is a permanent ungoverned tier that nobody
51
+ remembers.
52
+
53
+ ### Added
54
+
55
+ - **`Cache-Control` derived from the caller, not from configuration.** A rule's
56
+ `headers` now receives the access context. `rowAclFileRule` uses it: an
57
+ **anonymous** success proves the row is readable by everyone, so the response
58
+ is `public, max-age=60`; an identified caller gets `private, max-age=60`,
59
+ because from there it cannot be told whether the row is public or restricted
60
+ to them — and a second query to find out is not worth doubling the cost.
61
+
62
+ `maxAge: 0` gives instant revocation at the price of re-downloading, since
63
+ Parse sends no `ETag` and answers no conditional request. The default 60
64
+ bounds less than it appears: a cached copy only ever exists for someone who
65
+ was already allowed to see the file, and anyone who has viewed an image has
66
+ it on their device regardless.
67
+
68
+ ### Note
69
+
70
+ - Clients must send `X-Parse-Session-Token` on image requests for any class
71
+ whose CLP is not public — a browser `<img src>` cannot, so protected images
72
+ need fetching and binding. This is the honest cost of the ACL being the
73
+ source of truth, and no design avoids it.
74
+
75
+ ---
76
+
11
77
  ## [2.13.0]
12
78
 
13
79
  ### Changed — BREAKING (file access rules, added in 2.12.0)
@@ -1,63 +1,66 @@
1
1
  /**
2
- * File access rules — turn a file's PATH into a permission.
2
+ * File access rules — the owning row's ACL decides who gets the bytes.
3
3
  *
4
4
  * Parse has no per-file permission and cannot have one: the file router is
5
5
  * handed a name, and a name does not know which row references it. So a file
6
6
  * url is a bearer capability — anyone holding the string gets the bytes, with
7
- * no session, no ACL check and no expiry. For published pictures that is
8
- * correct and cheap. For a document (a certificate, an ID photo, an invoice) it
9
- * is not: a url that leaks once works forever, for anyone, which is a
10
- * REVOCATION problem that signed urls do not solve — a signed url is the same
11
- * bearer token on a timer, and it cannot express "this account was banned
12
- * thirty seconds ago".
7
+ * no session, no ACL check and no expiry. Fine for a logo. Not fine for a
8
+ * document, a profile photo, or anything a person can make private, because a
9
+ * url that leaks once works forever.
13
10
  *
14
- * Parse does give us one hook: `beforeFind` on `Parse.File`, which runs on
15
- * every `GET /files/...` and can throw to refuse. This module owns that hook
16
- * and makes it usable, because using it directly has five traps:
11
+ * Parse gives one hook: `beforeFind` on `Parse.File`, which runs on every
12
+ * `GET /files/...` and can throw to refuse. This module owns that hook.
13
+ *
14
+ * **Every file is stored under `<ClassName>/<objectId>/`**, so the path always
15
+ * names the row that owns it, and permission is decided **at read time** from
16
+ * that row's ACL. That matters more than it sounds:
17
+ *
18
+ * - a row made private takes its file out of service on the NEXT request;
19
+ * - a row made public starts serving immediately;
20
+ * - neither needs the bytes re-stored, re-named or migrated.
21
+ *
22
+ * The alternative — marking files private *when they are uploaded* — cannot do
23
+ * either. Storage location is permanent and visibility is not, so an
24
+ * upload-time decision is wrong the moment anything changes, and wrong in the
25
+ * fail-open direction: a file stored while its row was public stays
26
+ * world-readable forever, whatever the row later says. For an application where
27
+ * content moves between public and private, that design is not merely weaker,
28
+ * it is unable to express the requirement.
29
+ *
30
+ * **Five traps this absorbs**, each of which cost real debugging:
17
31
  *
18
32
  * 1. **There is exactly ONE slot.** File triggers are keyed on the
19
- * pseudo-class `@File`, not on a class, so a second
20
- * `beforeFind(Parse.File)` anywhere REPLACES the first — Parse logs
21
- * "Only the last one will be used" and carries on serving. Two features
22
- * each registering their own rule would silently disable one of them.
23
- * Hence a registry: this module holds the slot, rules compose.
24
- * 2. **The headers come from `afterFind`.** `beforeFind`'s `responseHeaders`
25
- * are discarded; only the `afterFind` request's are written to the
26
- * response. A rule that marks a response uncacheable has to act there.
27
- * 3. **Only a header authenticates.** The file GET route reads the session
28
- * from `X-Parse-Session-Token` and nowhere else — no query parameter, no
29
- * cookie. A browser `<img src>` therefore cannot fetch a governed file;
30
- * the client must fetch it and bind a blob. The upside is that nobody can
31
- * "simplify" this by putting a session token in a url.
32
- * 4. **A throw is global.** This runs on every file download in the app, so
33
- * a mistake does not break documents, it blanks every image at once.
34
- * Everything on the public path here is a string comparison, before any
35
- * `await`, and cannot throw.
36
- * 5. **Fail-open is the invisible failure.** If "I cannot tell who owns
37
- * this" is treated as "public", the document is served and the symptom is
38
- * that it loads perfectly. So governed-but-unidentifiable must REFUSE.
39
- *
40
- * **Nothing is registered until a rule is added.** Upgrading the kit therefore
41
- * changes no behaviour in a project that does not opt in, and a project that
42
- * already registers its own file trigger is not quietly overridden.
43
- *
44
- * The usual setup, in cloud code:
33
+ * pseudo-class `@File`, so a second `beforeFind(Parse.File)` REPLACES the
34
+ * first — Parse logs "Only the last one will be used" and keeps serving.
35
+ * Two features each registering a rule would silently disable one. Hence
36
+ * a registry: this module holds the slot, rules compose.
37
+ * 2. **Response headers come from `afterFind`.** `beforeFind`'s are
38
+ * discarded. A rule that controls caching has to act there.
39
+ * 3. **Only a header authenticates.** The file route reads the session from
40
+ * `X-Parse-Session-Token` and nowhere else — no cookie, no query
41
+ * parameter. A browser `<img src>` cannot send one, so a client must
42
+ * fetch protected images itself and bind the bytes. The upside: nobody
43
+ * can "simplify" this by putting a session token in a url.
44
+ * 4. **A throw is global.** This runs on every file download in the
45
+ * application, so a mistake does not break documents — it blanks every
46
+ * image at once. A rule whose predicate throws is skipped, not fatal.
47
+ * 5. **Fail-open is the invisible failure.** A path whose owner cannot be
48
+ * identified must be REFUSED. Treating it as public means the file loads
49
+ * perfectly and nobody ever notices.
50
+ *
51
+ * **Nothing is registered until a rule is added**, so upgrading changes no
52
+ * behaviour in a project that has not opted in.
45
53
  *
46
54
  * ```ts
47
- * import {registerFileAccessRule, aclFileRule} from '@90soft/parse-server-kit';
48
- * registerFileAccessRule(aclFileRule());
55
+ * registerFileAccessRule(rowAclFileRule());
56
+ * await attachOwnedFile(row, 'document', upload); // -> Row/<objectId>/...
49
57
  * ```
50
- *
51
- * [aclFileRule] is the general case: a file stored under
52
- * `acl/<ClassName>/<objectId>/` is served only to a caller who can read
53
- * THAT row, judged by Parse's own ACL and CLP. The permission is not a copy of
54
- * the row's ACL; it IS the row's ACL — nothing to stamp, nothing to sync.
55
58
  */
56
59
  /**
57
60
  * What a FILE trigger is handed, which is not what a class trigger gets: there
58
61
  * is no `object` and no `query`, only the file.
59
62
  *
60
- * Declared HERE rather than taken from the ambient Parse types on purpose.
63
+ * Declared here rather than taken from the ambient Parse types on purpose:
61
64
  * `@types/parse` does not describe file triggers at all, so a consumer relying
62
65
  * on it could not name the argument of [evaluateFileAccess] — a published
63
66
  * library should not require its callers to declare types for its own API.
@@ -74,7 +77,7 @@ export interface FileTriggerRequest {
74
77
  }
75
78
  /** The decision a rule is asked to make. */
76
79
  export interface FileAccessContext {
77
- /** The stored path, including any directory prefix. */
80
+ /** The stored path, including the owner directory. */
78
81
  path: string;
79
82
  /** The caller, when they sent a session token. */
80
83
  user?: Parse.User;
@@ -92,26 +95,26 @@ export interface FileAccessRule {
92
95
  * Does this rule govern that path?
93
96
  *
94
97
  * **Must not throw and should not await.** It is consulted for every file
95
- * download in the application, including every public image.
98
+ * download in the application.
96
99
  */
97
100
  governs(path: string): boolean;
98
101
  /**
99
- * Decide. Throw a `Parse.Error` to refuse.
102
+ * Decide. Throw a `Parse.Error` to refuse; return normally to allow.
100
103
  *
101
- * Returning normally allows the download. Only called when [governs] said
102
- * yes and the request is not master-key.
104
+ * Only called when [governs] matched and the request is not master-key.
103
105
  */
104
106
  authorize(context: FileAccessContext): Promise<void> | void;
105
107
  /**
106
- * Headers to add to a governed response, e.g. `Cache-Control`.
108
+ * Headers for a governed response.
107
109
  *
108
- * Applied whenever [governs] matches — including on a refusal, so that a
109
- * denial is not cached either.
110
+ * Receives the same context, so a rule can vary caching by caller — see
111
+ * [rowAclFileRule], where an anonymous success is itself the proof that a
112
+ * row is public and therefore safe for a shared cache.
110
113
  */
111
- headers?: Record<string, string>;
114
+ headers?(context: FileAccessContext): Record<string, string>;
112
115
  }
113
116
  /**
114
- * The gate. Public files leave before anything is awaited.
117
+ * The gate. Ungoverned files leave before anything is awaited.
115
118
  *
116
119
  * Exported so a project can unit-test its rules without going through HTTP.
117
120
  */
@@ -135,101 +138,77 @@ export declare function getFileAccessRules(): FileAccessRule[];
135
138
  /**
136
139
  * Drop every rule. For tests.
137
140
  *
138
- * The Parse hooks stay attached — they are harmless with no rules, since every
139
- * path is then public — and re-attaching would hit Parse's duplicate warning.
141
+ * The Parse hooks stay attached — harmless with no rules, since every path is
142
+ * then ungoverned — and re-attaching would hit Parse's duplicate warning.
140
143
  */
141
144
  export declare function clearFileAccessRules(): void;
142
- /**
143
- * The directory prefix marking a file as governed by [aclFileRule].
144
- *
145
- * **Named for the mechanism, not the outcome.** It was `private` first, which
146
- * was wrong in the most confusing way: the commonest case is a PUBLICLY
147
- * readable row, whose file is then served to everybody — from a path that
148
- * said "private". The prefix does not mean secret. It means **the owning row
149
- * decides**, and a public row decides "everyone".
150
- *
151
- * Renamed before anything depended on it, because the prefix is baked into
152
- * stored filenames: changing it later orphans every file already written.
153
- *
154
- * Parse's own `validateDirectory` reserves `metadata` and requires a directory
155
- * to match `^[a-zA-Z0-9][a-zA-Z0-9_\-/]*$`, so a single lowercase word is safe.
156
- * It is baked into stored file names, so changing it would orphan every file
157
- * already written under the old one.
158
- */
159
- export declare const ACL_PREFIX = "acl";
160
- /** Who an ACL-governed file's path says owns it. */
161
- export interface AclFileOwner {
145
+ /** Who a stored path says owns the bytes. */
146
+ export interface FileOwner {
162
147
  className: string;
163
148
  objectId: string;
164
149
  }
165
150
  /**
166
- * Is this path governed at all?
167
- *
168
- * Deliberately separate from [aclOwnerOf], and the separation is the
169
- * safety property: "under the prefix" and "parses into an owner" are different
170
- * questions, and a single predicate returning `owner | null` conflates them
171
- * into a fail-OPEN. It would answer `null` both for an ordinary image and for
172
- * `acl/<Class>/<id>/extra/doc.jpg` — one directory deeper than expected —
173
- * and so serve that document to anybody.
174
- */
175
- export declare function isAclGoverned(path: string): boolean;
176
- /**
177
- * Read the owner out of a governed path, or null if it is not well formed.
151
+ * Read the owner out of a stored path, or null if the path has no owner.
152
+ *
153
+ * **Must never throw.** It runs on every file download in the application, and
154
+ * a throw inside the file trigger does not break one feature — it blanks every
155
+ * image at once. Hence a plain `split` and nothing clever.
178
156
  *
179
- * `null` means "I cannot tell who owns this", which the rule treats as a
180
- * refusal — never as permission.
157
+ * `null` means "this file predates owner directories, or was stored by
158
+ * something else". A rule must treat that as a REFUSAL rather than as
159
+ * permission; see the fail-open note in the module docs.
181
160
  */
182
- export declare function aclOwnerOf(path: string): AclFileOwner | null;
161
+ export declare function fileOwnerOf(path: string): FileOwner | null;
183
162
  /**
184
- * The directory a row's ACL-governed files live in.
163
+ * The directory a row's files live in.
185
164
  *
186
- * Throws rather than quietly producing something Parse will reject: a class
187
- * whose name cannot be a path segment (`_User`, since a directory must start
165
+ * Throws rather than quietly producing something Parse rejects: a class whose
166
+ * name cannot be a path segment (`_User`, since a directory must start
188
167
  * alphanumeric) surfaces here, at the one call site, instead of as a confusing
189
168
  * upload failure later.
190
169
  */
191
- export declare function aclDirectoryFor(className: string, objectId: string): string;
170
+ export declare function ownerDirectoryFor(className: string, objectId: string): string;
192
171
  /**
193
172
  * Store a file so that the owning row's ACL governs it.
194
173
  *
195
174
  * The row must already be saved — its objectId is part of the path, which is
196
- * what lets the rule find the owner with no index and no second source of
197
- * truth. For a new record that means save, attach, save again: one extra write
198
- * on a rare operation.
199
- *
200
- * **This should be the only way an application stores a governed file.** The
201
- * prefix is the entire boundary: a document saved without it is simply public,
202
- * and nothing anywhere will complain.
175
+ * what lets a rule find the owner with no index and no second source of truth.
176
+ * For a new record that means save, attach, save again: one extra write on a
177
+ * rare operation.
203
178
  *
204
- * Private files deliberately get no derivatives — no converted copy, no
205
- * thumbnail, and no blurhash, which is a small preview of the document and
206
- * travels inside DTOs where the document itself does not.
179
+ * **This should be the only way an application stores a file.** A file stored
180
+ * without an owner directory is ungoverned, and nothing anywhere complains.
207
181
  */
208
- export declare function attachAclFile(row: Parse.Object, field: string, upload: {
182
+ export declare function attachOwnedFile(row: Parse.Object, field: string, upload: {
209
183
  base64: string;
210
184
  name?: string;
211
185
  }): Promise<void>;
212
- /** Options for [aclFileRule]. */
213
- export interface AclFileRuleOptions {
186
+ /** Options for [rowAclFileRule]. */
187
+ export interface RowAclFileRuleOptions {
214
188
  /**
215
- * Headers for a governed response. Defaults to `private, no-store`.
189
+ * How long a response may be cached, in seconds. Default 60.
216
190
  *
217
- * That `private` is the HTTP cache directive, unrelated to the prefix.
191
+ * This is the only lag in the design, and it is a straight trade: Parse sends
192
+ * no `ETag` and answers no conditional request, so "revalidate every time"
193
+ * costs the same bytes as "do not cache". `0` makes revocation instant and
194
+ * re-downloads every image on every view.
218
195
  *
219
- * One cached governed response served to the next caller undoes the whole
220
- * check, and the symptom is that the document loads — so this defaults to
221
- * the strict value rather than being left to the caller.
196
+ * It bounds less than it appears to. A cached copy only ever exists in the
197
+ * cache of someone who was ALREADY allowed to see the file — a caller who
198
+ * was refused has nothing stored. And anyone who has viewed an image has it
199
+ * on their device regardless: revocation stops future access, it cannot
200
+ * un-see.
222
201
  */
223
- headers?: Record<string, string>;
202
+ maxAge?: number;
224
203
  }
225
204
  /**
226
- * Serve a governed file only to a caller who can read its owning row.
205
+ * Serve a file only to a caller who can read the row that owns it.
227
206
  *
228
- * The caller is resolved from their session token, so Parse evaluates the
229
- * row's ACL and the class's CLP exactly as it would for a query. With no
230
- * session the row is loaded with no auth, which is right rather than a
231
- * shortcut: if the owning row is publicly readable then its file is public
232
- * too, because the row's ACL is the whole rule.
207
+ * The caller is resolved from their session token, so Parse evaluates the row's
208
+ * ACL and the class's CLP exactly as it would for a query. With no session the
209
+ * row is loaded with no auth, which is right rather than a shortcut: if the
210
+ * owning row is publicly readable then its file is public too, because the
211
+ * row's ACL is the whole rule.
233
212
  */
234
- export declare function aclFileRule(options?: AclFileRuleOptions): FileAccessRule;
213
+ export declare function rowAclFileRule(options?: RowAclFileRuleOptions): FileAccessRule;
235
214
  //# sourceMappingURL=fileAccess.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fileAccess.d.ts","sourceRoot":"","sources":["../../src/files/fileAccess.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAEH;;;;;;;;GAQG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,4CAA4C;AAC5C,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC;IAClB,qCAAqC;IACrC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;OAKG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAE/B;;;;;OAKG;IACH,SAAS,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAE5D;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAiCD;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,kBAAkB,GAC1B,IAAI,CAON;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAsBjE;AAED,6DAA6D;AAC7D,wBAAgB,kBAAkB,IAAI,cAAc,EAAE,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAID;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,UAAU,QAAQ,CAAC;AAEhC,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAW5D;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAc3E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,KAAK,CAAC,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,iCAAiC;AACjC,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CACzB,OAAO,GAAE,kBAAuB,GAC/B,cAAc,CA8BhB"}
1
+ {"version":3,"file":"fileAccess.d.ts","sourceRoot":"","sources":["../../src/files/fileAccess.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAEH;;;;;;;;GAQG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,4CAA4C;AAC5C,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC;IAClB,qCAAqC;IACrC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;OAKG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAE/B;;;;OAIG;IACH,SAAS,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAE5D;;;;;;OAMG;IACH,OAAO,CAAC,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9D;AAuCD;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAYxE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAqBjE;AAED,6DAA6D;AAC7D,wBAAgB,kBAAkB,IAAI,cAAc,EAAE,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAID,6CAA6C;AAC7C,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAW1D;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAc7E;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,KAAK,CAAC,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,oCAAoC;AACpC,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,OAAO,GAAE,qBAA0B,GAClC,cAAc,CAkDhB"}
@@ -1,71 +1,72 @@
1
1
  "use strict";
2
2
  /**
3
- * File access rules — turn a file's PATH into a permission.
3
+ * File access rules — the owning row's ACL decides who gets the bytes.
4
4
  *
5
5
  * Parse has no per-file permission and cannot have one: the file router is
6
6
  * handed a name, and a name does not know which row references it. So a file
7
7
  * url is a bearer capability — anyone holding the string gets the bytes, with
8
- * no session, no ACL check and no expiry. For published pictures that is
9
- * correct and cheap. For a document (a certificate, an ID photo, an invoice) it
10
- * is not: a url that leaks once works forever, for anyone, which is a
11
- * REVOCATION problem that signed urls do not solve — a signed url is the same
12
- * bearer token on a timer, and it cannot express "this account was banned
13
- * thirty seconds ago".
8
+ * no session, no ACL check and no expiry. Fine for a logo. Not fine for a
9
+ * document, a profile photo, or anything a person can make private, because a
10
+ * url that leaks once works forever.
14
11
  *
15
- * Parse does give us one hook: `beforeFind` on `Parse.File`, which runs on
16
- * every `GET /files/...` and can throw to refuse. This module owns that hook
17
- * and makes it usable, because using it directly has five traps:
12
+ * Parse gives one hook: `beforeFind` on `Parse.File`, which runs on every
13
+ * `GET /files/...` and can throw to refuse. This module owns that hook.
18
14
  *
19
- * 1. **There is exactly ONE slot.** File triggers are keyed on the
20
- * pseudo-class `@File`, not on a class, so a second
21
- * `beforeFind(Parse.File)` anywhere REPLACES the first — Parse logs
22
- * "Only the last one will be used" and carries on serving. Two features
23
- * each registering their own rule would silently disable one of them.
24
- * Hence a registry: this module holds the slot, rules compose.
25
- * 2. **The headers come from `afterFind`.** `beforeFind`'s `responseHeaders`
26
- * are discarded; only the `afterFind` request's are written to the
27
- * response. A rule that marks a response uncacheable has to act there.
28
- * 3. **Only a header authenticates.** The file GET route reads the session
29
- * from `X-Parse-Session-Token` and nowhere else — no query parameter, no
30
- * cookie. A browser `<img src>` therefore cannot fetch a governed file;
31
- * the client must fetch it and bind a blob. The upside is that nobody can
32
- * "simplify" this by putting a session token in a url.
33
- * 4. **A throw is global.** This runs on every file download in the app, so
34
- * a mistake does not break documents, it blanks every image at once.
35
- * Everything on the public path here is a string comparison, before any
36
- * `await`, and cannot throw.
37
- * 5. **Fail-open is the invisible failure.** If "I cannot tell who owns
38
- * this" is treated as "public", the document is served and the symptom is
39
- * that it loads perfectly. So governed-but-unidentifiable must REFUSE.
15
+ * **Every file is stored under `<ClassName>/<objectId>/`**, so the path always
16
+ * names the row that owns it, and permission is decided **at read time** from
17
+ * that row's ACL. That matters more than it sounds:
18
+ *
19
+ * - a row made private takes its file out of service on the NEXT request;
20
+ * - a row made public starts serving immediately;
21
+ * - neither needs the bytes re-stored, re-named or migrated.
22
+ *
23
+ * The alternative — marking files private *when they are uploaded* — cannot do
24
+ * either. Storage location is permanent and visibility is not, so an
25
+ * upload-time decision is wrong the moment anything changes, and wrong in the
26
+ * fail-open direction: a file stored while its row was public stays
27
+ * world-readable forever, whatever the row later says. For an application where
28
+ * content moves between public and private, that design is not merely weaker,
29
+ * it is unable to express the requirement.
30
+ *
31
+ * **Five traps this absorbs**, each of which cost real debugging:
40
32
  *
41
- * **Nothing is registered until a rule is added.** Upgrading the kit therefore
42
- * changes no behaviour in a project that does not opt in, and a project that
43
- * already registers its own file trigger is not quietly overridden.
33
+ * 1. **There is exactly ONE slot.** File triggers are keyed on the
34
+ * pseudo-class `@File`, so a second `beforeFind(Parse.File)` REPLACES the
35
+ * first — Parse logs "Only the last one will be used" and keeps serving.
36
+ * Two features each registering a rule would silently disable one. Hence
37
+ * a registry: this module holds the slot, rules compose.
38
+ * 2. **Response headers come from `afterFind`.** `beforeFind`'s are
39
+ * discarded. A rule that controls caching has to act there.
40
+ * 3. **Only a header authenticates.** The file route reads the session from
41
+ * `X-Parse-Session-Token` and nowhere else — no cookie, no query
42
+ * parameter. A browser `<img src>` cannot send one, so a client must
43
+ * fetch protected images itself and bind the bytes. The upside: nobody
44
+ * can "simplify" this by putting a session token in a url.
45
+ * 4. **A throw is global.** This runs on every file download in the
46
+ * application, so a mistake does not break documents — it blanks every
47
+ * image at once. A rule whose predicate throws is skipped, not fatal.
48
+ * 5. **Fail-open is the invisible failure.** A path whose owner cannot be
49
+ * identified must be REFUSED. Treating it as public means the file loads
50
+ * perfectly and nobody ever notices.
44
51
  *
45
- * The usual setup, in cloud code:
52
+ * **Nothing is registered until a rule is added**, so upgrading changes no
53
+ * behaviour in a project that has not opted in.
46
54
  *
47
55
  * ```ts
48
- * import {registerFileAccessRule, aclFileRule} from '@90soft/parse-server-kit';
49
- * registerFileAccessRule(aclFileRule());
56
+ * registerFileAccessRule(rowAclFileRule());
57
+ * await attachOwnedFile(row, 'document', upload); // -> Row/<objectId>/...
50
58
  * ```
51
- *
52
- * [aclFileRule] is the general case: a file stored under
53
- * `acl/<ClassName>/<objectId>/` is served only to a caller who can read
54
- * THAT row, judged by Parse's own ACL and CLP. The permission is not a copy of
55
- * the row's ACL; it IS the row's ACL — nothing to stamp, nothing to sync.
56
59
  */
57
60
  Object.defineProperty(exports, "__esModule", { value: true });
58
- exports.ACL_PREFIX = void 0;
59
61
  exports.evaluateFileAccess = evaluateFileAccess;
60
62
  exports.applyFileAccessHeaders = applyFileAccessHeaders;
61
63
  exports.registerFileAccessRule = registerFileAccessRule;
62
64
  exports.getFileAccessRules = getFileAccessRules;
63
65
  exports.clearFileAccessRules = clearFileAccessRules;
64
- exports.isAclGoverned = isAclGoverned;
65
- exports.aclOwnerOf = aclOwnerOf;
66
- exports.aclDirectoryFor = aclDirectoryFor;
67
- exports.attachAclFile = attachAclFile;
68
- exports.aclFileRule = aclFileRule;
66
+ exports.fileOwnerOf = fileOwnerOf;
67
+ exports.ownerDirectoryFor = ownerDirectoryFor;
68
+ exports.attachOwnedFile = attachOwnedFile;
69
+ exports.rowAclFileRule = rowAclFileRule;
69
70
  /** Ordered; the first rule that governs a path decides it. */
70
71
  const rules = [];
71
72
  /** The hook is attached once, lazily, on the first registration. */
@@ -74,17 +75,15 @@ let attached = false;
74
75
  * 404, never 403.
75
76
  *
76
77
  * A 403 confirms the file is there and merely forbidden, which for a document
77
- * is itself the leak — it tells the caller that a particular row has one.
78
- * "Not found" is the same answer an invented name would get.
78
+ * is itself the leak. "Not found" is the answer an invented name would get.
79
79
  */
80
80
  function notFound() {
81
81
  return new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'File not found');
82
82
  }
83
- /** The first rule governing this path, or undefined when the file is public. */
83
+ /** The first rule governing this path, or undefined when none does. */
84
84
  function ruleFor(path) {
85
85
  for (const rule of rules) {
86
- // A rule that throws here would blank every image in the app, so one
87
- // misbehaving rule must not take the public path down with it.
86
+ // One misbehaving rule must not blank every image in the app.
88
87
  try {
89
88
  if (rule.governs(path))
90
89
  return rule;
@@ -95,25 +94,28 @@ function ruleFor(path) {
95
94
  }
96
95
  return undefined;
97
96
  }
97
+ function contextFor(request) {
98
+ return {
99
+ path: request.file?.name() ?? '',
100
+ user: request.user,
101
+ master: request.master === true,
102
+ };
103
+ }
98
104
  /**
99
- * The gate. Public files leave before anything is awaited.
105
+ * The gate. Ungoverned files leave before anything is awaited.
100
106
  *
101
107
  * Exported so a project can unit-test its rules without going through HTTP.
102
108
  */
103
109
  async function evaluateFileAccess(request) {
104
- const path = request.file?.name() ?? '';
105
- const rule = ruleFor(path);
110
+ const context = contextFor(request);
111
+ const rule = ruleFor(context.path);
106
112
  if (!rule)
107
113
  return;
108
- // Cloud code reading deliberately with the master key. Note this is NOT how
109
- // a worker that fetches a url reaches a file: a plain GET carries no key.
110
- if (request.master)
114
+ // Cloud code reading deliberately. NOT how a worker that fetches a url
115
+ // reaches a file — a plain GET carries no key.
116
+ if (context.master)
111
117
  return;
112
- await rule.authorize({
113
- path,
114
- user: request.user,
115
- master: false,
116
- });
118
+ await rule.authorize(context);
117
119
  }
118
120
  /**
119
121
  * Add the governed response's headers.
@@ -122,12 +124,16 @@ async function evaluateFileAccess(request) {
122
124
  * the `afterFind` request and ignores `beforeFind`'s.
123
125
  */
124
126
  function applyFileAccessHeaders(request) {
125
- const rule = ruleFor(request.file?.name() ?? '');
127
+ const context = contextFor(request);
128
+ const rule = ruleFor(context.path);
126
129
  if (!rule?.headers)
127
130
  return;
128
131
  // The incoming object already carries `X-Content-Type-Options: nosniff`, so
129
132
  // extend it rather than replacing it.
130
- request.responseHeaders = { ...(request.responseHeaders ?? {}), ...rule.headers };
133
+ request.responseHeaders = {
134
+ ...(request.responseHeaders ?? {}),
135
+ ...rule.headers(context),
136
+ };
131
137
  }
132
138
  /**
133
139
  * Register a rule, attaching the Parse hooks on the first call.
@@ -149,9 +155,8 @@ function registerFileAccessRule(rule) {
149
155
  attached = true;
150
156
  /*
151
157
  * `Parse.File` is passed as the class, which Parse maps to `@File`. This is
152
- * the only pair of triggers in a kit project that is not declared on a model
153
- * with `@BeforeFind` / `@AfterFind`, because there is no model to declare it
154
- * on.
158
+ * the only pair of triggers in a kit project not declared on a model with
159
+ * `@BeforeFind` / `@AfterFind`, because there is no model to declare it on.
155
160
  */
156
161
  Parse.Cloud.beforeFind(Parse.File, evaluateFileAccess);
157
162
  Parse.Cloud.afterFind(Parse.File, applyFileAccessHeaders);
@@ -163,131 +168,93 @@ function getFileAccessRules() {
163
168
  /**
164
169
  * Drop every rule. For tests.
165
170
  *
166
- * The Parse hooks stay attached — they are harmless with no rules, since every
167
- * path is then public — and re-attaching would hit Parse's duplicate warning.
171
+ * The Parse hooks stay attached — harmless with no rules, since every path is
172
+ * then ungoverned — and re-attaching would hit Parse's duplicate warning.
168
173
  */
169
174
  function clearFileAccessRules() {
170
175
  rules.length = 0;
171
176
  }
172
- // ── The ACL-governed rule ───────────────────────────────────────────────────
173
177
  /**
174
- * The directory prefix marking a file as governed by [aclFileRule].
175
- *
176
- * **Named for the mechanism, not the outcome.** It was `private` first, which
177
- * was wrong in the most confusing way: the commonest case is a PUBLICLY
178
- * readable row, whose file is then served to everybody — from a path that
179
- * said "private". The prefix does not mean secret. It means **the owning row
180
- * decides**, and a public row decides "everyone".
178
+ * Read the owner out of a stored path, or null if the path has no owner.
181
179
  *
182
- * Renamed before anything depended on it, because the prefix is baked into
183
- * stored filenames: changing it later orphans every file already written.
180
+ * **Must never throw.** It runs on every file download in the application, and
181
+ * a throw inside the file trigger does not break one feature — it blanks every
182
+ * image at once. Hence a plain `split` and nothing clever.
184
183
  *
185
- * Parse's own `validateDirectory` reserves `metadata` and requires a directory
186
- * to match `^[a-zA-Z0-9][a-zA-Z0-9_\-/]*$`, so a single lowercase word is safe.
187
- * It is baked into stored file names, so changing it would orphan every file
188
- * already written under the old one.
184
+ * `null` means "this file predates owner directories, or was stored by
185
+ * something else". A rule must treat that as a REFUSAL rather than as
186
+ * permission; see the fail-open note in the module docs.
189
187
  */
190
- exports.ACL_PREFIX = 'acl';
191
- /**
192
- * Is this path governed at all?
193
- *
194
- * Deliberately separate from [aclOwnerOf], and the separation is the
195
- * safety property: "under the prefix" and "parses into an owner" are different
196
- * questions, and a single predicate returning `owner | null` conflates them
197
- * into a fail-OPEN. It would answer `null` both for an ordinary image and for
198
- * `acl/<Class>/<id>/extra/doc.jpg` — one directory deeper than expected —
199
- * and so serve that document to anybody.
200
- */
201
- function isAclGoverned(path) {
202
- return typeof path === 'string' && path.startsWith(`${exports.ACL_PREFIX}/`);
203
- }
204
- /**
205
- * Read the owner out of a governed path, or null if it is not well formed.
206
- *
207
- * `null` means "I cannot tell who owns this", which the rule treats as a
208
- * refusal — never as permission.
209
- */
210
- function aclOwnerOf(path) {
211
- if (!isAclGoverned(path))
188
+ function fileOwnerOf(path) {
189
+ if (typeof path !== 'string' || path === '')
212
190
  return null;
213
- // Exactly: acl / ClassName / objectId / filename
191
+ // Exactly: ClassName / objectId / filename
214
192
  const parts = path.split('/');
215
- if (parts.length !== 4)
193
+ if (parts.length !== 3)
216
194
  return null;
217
- const [, className, objectId, filename] = parts;
195
+ const [className, objectId, filename] = parts;
218
196
  if (!className || !objectId || !filename)
219
197
  return null;
220
198
  return { className, objectId };
221
199
  }
222
200
  /**
223
- * The directory a row's ACL-governed files live in.
201
+ * The directory a row's files live in.
224
202
  *
225
- * Throws rather than quietly producing something Parse will reject: a class
226
- * whose name cannot be a path segment (`_User`, since a directory must start
203
+ * Throws rather than quietly producing something Parse rejects: a class whose
204
+ * name cannot be a path segment (`_User`, since a directory must start
227
205
  * alphanumeric) surfaces here, at the one call site, instead of as a confusing
228
206
  * upload failure later.
229
207
  */
230
- function aclDirectoryFor(className, objectId) {
208
+ function ownerDirectoryFor(className, objectId) {
231
209
  if (!/^[a-zA-Z0-9][a-zA-Z0-9_]*$/.test(className)) {
232
- throw new Parse.Error(Parse.Error.OTHER_CAUSE, `${className} cannot own ACL-governed files: Parse requires a directory segment to start with a letter or digit`);
210
+ throw new Parse.Error(Parse.Error.OTHER_CAUSE, `${className} cannot own files: Parse requires a directory segment to start with a letter or digit`);
233
211
  }
234
212
  if (!/^[a-zA-Z0-9]+$/.test(objectId)) {
235
- throw new Parse.Error(Parse.Error.OTHER_CAUSE, 'An ACL-governed file needs the owning row saved first, so that it has an objectId');
213
+ throw new Parse.Error(Parse.Error.OTHER_CAUSE, 'A file needs its owning row saved first, so that it has an objectId');
236
214
  }
237
- return `${exports.ACL_PREFIX}/${className}/${objectId}`;
215
+ return `${className}/${objectId}`;
238
216
  }
239
217
  /**
240
218
  * Store a file so that the owning row's ACL governs it.
241
219
  *
242
220
  * The row must already be saved — its objectId is part of the path, which is
243
- * what lets the rule find the owner with no index and no second source of
244
- * truth. For a new record that means save, attach, save again: one extra write
245
- * on a rare operation.
246
- *
247
- * **This should be the only way an application stores a governed file.** The
248
- * prefix is the entire boundary: a document saved without it is simply public,
249
- * and nothing anywhere will complain.
221
+ * what lets a rule find the owner with no index and no second source of truth.
222
+ * For a new record that means save, attach, save again: one extra write on a
223
+ * rare operation.
250
224
  *
251
- * Private files deliberately get no derivatives — no converted copy, no
252
- * thumbnail, and no blurhash, which is a small preview of the document and
253
- * travels inside DTOs where the document itself does not.
225
+ * **This should be the only way an application stores a file.** A file stored
226
+ * without an owner directory is ungoverned, and nothing anywhere complains.
254
227
  */
255
- async function attachAclFile(row, field, upload) {
228
+ async function attachOwnedFile(row, field, upload) {
256
229
  if (!row.id) {
257
- throw new Parse.Error(Parse.Error.OTHER_CAUSE, 'Save the row before attaching a governed file — its objectId is part of the path');
230
+ throw new Parse.Error(Parse.Error.OTHER_CAUSE, 'Save the row before attaching a file — its objectId is part of the path');
258
231
  }
259
- const file = new Parse.File(encodeURIComponent(upload.name ?? 'document'), {
232
+ const file = new Parse.File(encodeURIComponent(upload.name ?? 'file'), {
260
233
  base64: upload.base64,
261
234
  });
262
235
  // Sent as `X-Parse-File-Directory`; honoured by Parse Server from 9.5.0.
263
- file.setDirectory(aclDirectoryFor(row.className, row.id));
236
+ file.setDirectory(ownerDirectoryFor(row.className, row.id));
264
237
  const saved = await file.save({ useMasterKey: true });
265
238
  row.set(field, saved);
266
239
  }
267
240
  /**
268
- * Serve a governed file only to a caller who can read its owning row.
241
+ * Serve a file only to a caller who can read the row that owns it.
269
242
  *
270
- * The caller is resolved from their session token, so Parse evaluates the
271
- * row's ACL and the class's CLP exactly as it would for a query. With no
272
- * session the row is loaded with no auth, which is right rather than a
273
- * shortcut: if the owning row is publicly readable then its file is public
274
- * too, because the row's ACL is the whole rule.
243
+ * The caller is resolved from their session token, so Parse evaluates the row's
244
+ * ACL and the class's CLP exactly as it would for a query. With no session the
245
+ * row is loaded with no auth, which is right rather than a shortcut: if the
246
+ * owning row is publicly readable then its file is public too, because the
247
+ * row's ACL is the whole rule.
275
248
  */
276
- function aclFileRule(options = {}) {
277
- const headers = options.headers ?? { 'Cache-Control': 'private, no-store' };
249
+ function rowAclFileRule(options = {}) {
250
+ const maxAge = options.maxAge ?? 60;
278
251
  return {
279
- name: 'acl-prefix',
280
- headers,
281
- governs: isAclGoverned,
252
+ name: 'row-acl',
253
+ // Every path. A file with no identifiable owner is REFUSED below, not
254
+ // ignored — ignoring it is the fail-open case.
255
+ governs: () => true,
282
256
  async authorize({ path, user }) {
283
- /*
284
- * Under the prefix but not a shape we understand: REFUSE.
285
- *
286
- * Treating it as public because no owner could be found is the one
287
- * failure mode of this design that nobody would notice, because the
288
- * document would load perfectly.
289
- */
290
- const owner = aclOwnerOf(path);
257
+ const owner = fileOwnerOf(path);
291
258
  if (!owner)
292
259
  throw notFound();
293
260
  const sessionToken = user?.getSessionToken();
@@ -298,6 +265,28 @@ function aclFileRule(options = {}) {
298
265
  if (!row)
299
266
  throw notFound();
300
267
  },
268
+ headers({ user }) {
269
+ /*
270
+ * `public` only for an ANONYMOUS success.
271
+ *
272
+ * Reaching here means the row was readable by this caller. If the caller
273
+ * sent no session and still succeeded, the row is readable by everyone —
274
+ * so the bytes are genuinely public and a shared cache may hold them.
275
+ *
276
+ * Otherwise the caller was identified, and we cannot tell from here
277
+ * whether the row is public or restricted to them specifically.
278
+ * `private` is the safe answer: the response may sit in that one user's
279
+ * own cache and in no shared one. It costs nothing when the row happens
280
+ * to be public, and it is correct when it is not.
281
+ *
282
+ * Deliberately NOT a second query to find out. One database read per
283
+ * cold fetch is the budget; a caching hint is not worth doubling it.
284
+ */
285
+ const scope = user ? 'private' : 'public';
286
+ return {
287
+ 'Cache-Control': maxAge > 0 ? `${scope}, max-age=${maxAge}` : `${scope}, no-store`,
288
+ };
289
+ },
301
290
  };
302
291
  }
303
292
  //# sourceMappingURL=fileAccess.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fileAccess.js","sourceRoot":"","sources":["../../src/files/fileAccess.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fileAccess.js","sourceRoot":"","sources":["../../src/files/fileAccess.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -24,8 +24,8 @@ export { configureRoleCache, invalidateRoles, roleCacheEnabled, roleCacheStats }
24
24
  export type { RoleCacheOptions } from './utils/roleCache';
25
25
  export { validateFunctionRoutes, validateEntityRoutes, restrictRoutes, removeResultMiddleware, conditionalJsonMiddleware } from './middleware/middleware';
26
26
  export { checkRateLimit } from './middleware/rateLimit';
27
- export { registerFileAccessRule, getFileAccessRules, clearFileAccessRules, evaluateFileAccess, applyFileAccessHeaders, aclFileRule, attachAclFile, isAclGoverned, aclOwnerOf, aclDirectoryFor, ACL_PREFIX } from './files/fileAccess';
28
- export type { FileAccessRule, FileAccessContext, FileTriggerRequest, AclFileOwner, AclFileRuleOptions } from './files/fileAccess';
27
+ export { registerFileAccessRule, getFileAccessRules, clearFileAccessRules, evaluateFileAccess, applyFileAccessHeaders, rowAclFileRule, attachOwnedFile, fileOwnerOf, ownerDirectoryFor } from './files/fileAccess';
28
+ export type { FileAccessRule, FileAccessContext, FileTriggerRequest, FileOwner, RowAclFileRuleOptions } from './files/fileAccess';
29
29
  export { createSchemaConfig } from './database/schema';
30
30
  export type { SchemaConfigOptions } from './database/schema';
31
31
  export { applyAllIndexes, applyUniqueIndexes, getUniqueIndexes, getCompoundIndexes, getFieldIndexes } from './database/indexes';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -2,8 +2,7 @@
2
2
  // @90soft/parse-server-kit — complete toolkit for Parse Server
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.getUserRoles = exports.catchError = exports.MAX_QUERY_LIMIT = exports.roleKey = exports.UserRoles = exports.cloneAcl = exports.syncImageAcl = exports.implementACL = exports.BaseModel = exports.applyMongoValidators = exports.getValidators = exports.validateOrThrow = exports.validateObject = exports.classNames = exports.RouteRegistry = exports.Route = exports.CronRegistry = exports.CronSchedule = exports.Cron = exports.TriggerRegistry = exports.AfterEvent = exports.BeforeSubscribe = exports.BeforeConnect = exports.AfterSaveConfig = exports.BeforeSaveConfig = exports.AfterFindFile = exports.BeforeFindFile = exports.AfterDeleteFile = exports.BeforeDeleteFile = exports.AfterSaveFile = exports.BeforeSaveFile = exports.BeforePasswordResetRequest = exports.AfterLogout = exports.AfterLogin = exports.BeforeLogin = exports.AfterFind = exports.BeforeFind = exports.AfterDelete = exports.BeforeDelete = exports.AfterSave = exports.BeforeSave = exports.CloudFunctionRegistry = exports.onFunctionRegistered = exports.ProtectedCloudFunction = exports.CloudFunction = exports.onFieldRegistered = exports.onClassRegistered = exports.getSchemaDefinition = exports.ParseField = exports.ParseClass = void 0;
5
- exports.generateSwaggerSpec = exports.SwaggerRegistry = exports.NO_AMBIENT_TRANSACTION = exports.withAmbientSession = exports.CONFLICT_MESSAGE = exports.CONFLICT = exports.useTransactionAdapter = exports.currentSession = exports.inTransaction = exports.withTransaction = exports.Transactional = exports.VERSION_CONFLICT_MESSAGE = exports.VERSION_CONFLICT = exports.createVersionedMongoAdapter = exports.VersionRegistry = exports.ParseVersionField = exports.getFieldIndexes = exports.getCompoundIndexes = exports.getUniqueIndexes = exports.applyUniqueIndexes = exports.applyAllIndexes = exports.createSchemaConfig = exports.ACL_PREFIX = exports.aclDirectoryFor = exports.aclOwnerOf = exports.isAclGoverned = exports.attachAclFile = exports.aclFileRule = exports.applyFileAccessHeaders = exports.evaluateFileAccess = exports.clearFileAccessRules = exports.getFileAccessRules = exports.registerFileAccessRule = exports.checkRateLimit = exports.conditionalJsonMiddleware = exports.removeResultMiddleware = exports.restrictRoutes = exports.validateEntityRoutes = exports.validateFunctionRoutes = exports.roleCacheStats = exports.roleCacheEnabled = exports.invalidateRoles = exports.configureRoleCache = exports.importFiles = exports.sleep = exports.generateRandomString = exports.generateRandomInteger = exports.generateRandomPassword = exports.formatCount = exports.getUsersRoles = void 0;
6
- exports.setupSwagger = exports.getSwaggerJson = void 0;
5
+ exports.setupSwagger = exports.getSwaggerJson = exports.generateSwaggerSpec = exports.SwaggerRegistry = exports.NO_AMBIENT_TRANSACTION = exports.withAmbientSession = exports.CONFLICT_MESSAGE = exports.CONFLICT = exports.useTransactionAdapter = exports.currentSession = exports.inTransaction = exports.withTransaction = exports.Transactional = exports.VERSION_CONFLICT_MESSAGE = exports.VERSION_CONFLICT = exports.createVersionedMongoAdapter = exports.VersionRegistry = exports.ParseVersionField = exports.getFieldIndexes = exports.getCompoundIndexes = exports.getUniqueIndexes = exports.applyUniqueIndexes = exports.applyAllIndexes = exports.createSchemaConfig = exports.ownerDirectoryFor = exports.fileOwnerOf = exports.attachOwnedFile = exports.rowAclFileRule = exports.applyFileAccessHeaders = exports.evaluateFileAccess = exports.clearFileAccessRules = exports.getFileAccessRules = exports.registerFileAccessRule = exports.checkRateLimit = exports.conditionalJsonMiddleware = exports.removeResultMiddleware = exports.restrictRoutes = exports.validateEntityRoutes = exports.validateFunctionRoutes = exports.roleCacheStats = exports.roleCacheEnabled = exports.invalidateRoles = exports.configureRoleCache = exports.importFiles = exports.sleep = exports.generateRandomString = exports.generateRandomInteger = exports.generateRandomPassword = exports.formatCount = exports.getUsersRoles = void 0;
7
6
  // ── Decorators ──
8
7
  var parseDecorators_1 = require("./decorators/parseDecorators");
9
8
  Object.defineProperty(exports, "ParseClass", { enumerable: true, get: function () { return parseDecorators_1.ParseClass; } });
@@ -97,23 +96,21 @@ Object.defineProperty(exports, "removeResultMiddleware", { enumerable: true, get
97
96
  Object.defineProperty(exports, "conditionalJsonMiddleware", { enumerable: true, get: function () { return middleware_1.conditionalJsonMiddleware; } });
98
97
  var rateLimit_1 = require("./middleware/rateLimit");
99
98
  Object.defineProperty(exports, "checkRateLimit", { enumerable: true, get: function () { return rateLimit_1.checkRateLimit; } });
100
- // ── File access ──────────────────────────────────────────────────────────────
101
- // Parse has no per-file permission; these turn a file's PATH into one. The kit
102
- // owns the single `beforeFind(Parse.File)` slot so that rules compose instead
103
- // of silently replacing each other, and nothing is registered until a rule is
104
- // added — so upgrading changes no behaviour for a project that does not opt in.
99
+ // ── File access ──────────────────────────────────────────────────
100
+ // Parse has no per-file permission; these make the OWNING ROW'S ACL the
101
+ // permission, decided at READ time so a visibility change needs no migration.
102
+ // The kit owns the single `beforeFind(Parse.File)` slot so rules compose, and
103
+ // nothing is registered until a rule is added.
105
104
  var fileAccess_1 = require("./files/fileAccess");
106
105
  Object.defineProperty(exports, "registerFileAccessRule", { enumerable: true, get: function () { return fileAccess_1.registerFileAccessRule; } });
107
106
  Object.defineProperty(exports, "getFileAccessRules", { enumerable: true, get: function () { return fileAccess_1.getFileAccessRules; } });
108
107
  Object.defineProperty(exports, "clearFileAccessRules", { enumerable: true, get: function () { return fileAccess_1.clearFileAccessRules; } });
109
108
  Object.defineProperty(exports, "evaluateFileAccess", { enumerable: true, get: function () { return fileAccess_1.evaluateFileAccess; } });
110
109
  Object.defineProperty(exports, "applyFileAccessHeaders", { enumerable: true, get: function () { return fileAccess_1.applyFileAccessHeaders; } });
111
- Object.defineProperty(exports, "aclFileRule", { enumerable: true, get: function () { return fileAccess_1.aclFileRule; } });
112
- Object.defineProperty(exports, "attachAclFile", { enumerable: true, get: function () { return fileAccess_1.attachAclFile; } });
113
- Object.defineProperty(exports, "isAclGoverned", { enumerable: true, get: function () { return fileAccess_1.isAclGoverned; } });
114
- Object.defineProperty(exports, "aclOwnerOf", { enumerable: true, get: function () { return fileAccess_1.aclOwnerOf; } });
115
- Object.defineProperty(exports, "aclDirectoryFor", { enumerable: true, get: function () { return fileAccess_1.aclDirectoryFor; } });
116
- Object.defineProperty(exports, "ACL_PREFIX", { enumerable: true, get: function () { return fileAccess_1.ACL_PREFIX; } });
110
+ Object.defineProperty(exports, "rowAclFileRule", { enumerable: true, get: function () { return fileAccess_1.rowAclFileRule; } });
111
+ Object.defineProperty(exports, "attachOwnedFile", { enumerable: true, get: function () { return fileAccess_1.attachOwnedFile; } });
112
+ Object.defineProperty(exports, "fileOwnerOf", { enumerable: true, get: function () { return fileAccess_1.fileOwnerOf; } });
113
+ Object.defineProperty(exports, "ownerDirectoryFor", { enumerable: true, get: function () { return fileAccess_1.ownerDirectoryFor; } });
117
114
  // ── Database ──
118
115
  var schema_1 = require("./database/schema");
119
116
  Object.defineProperty(exports, "createSchemaConfig", { enumerable: true, get: function () { return schema_1.createSchemaConfig; } });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@90soft/parse-server-kit",
3
- "version": "2.13.0",
3
+ "version": "2.14.0",
4
4
  "description": "Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",