@90soft/parse-server-kit 2.12.0 → 2.13.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 +43 -0
- package/dist/files/fileAccess.d.ts +33 -22
- package/dist/files/fileAccess.d.ts.map +1 -1
- package/dist/files/fileAccess.js +43 -34
- package/dist/files/fileAccess.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,49 @@ All notable changes to `@90soft/parse-server-kit`.
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
+
## [2.13.0]
|
|
12
|
+
|
|
13
|
+
### Changed — BREAKING (file access rules, added in 2.12.0)
|
|
14
|
+
|
|
15
|
+
- **The governed prefix is `acl/`, not `private/`, and the API is renamed to
|
|
16
|
+
match.**
|
|
17
|
+
|
|
18
|
+
`private` was wrong in the most confusing way possible. The commonest case is
|
|
19
|
+
a **publicly readable** row — a login background, say — whose file is then
|
|
20
|
+
correctly served to everybody, from a url that said `private`. The prefix
|
|
21
|
+
never meant "secret". It means **the owning row decides**, and a public row
|
|
22
|
+
decides "everyone".
|
|
23
|
+
|
|
24
|
+
Renamed now because the prefix is baked into stored filenames: changing it
|
|
25
|
+
later orphans every file already written under the old one. 2.12.0 was hours
|
|
26
|
+
old and had one consumer.
|
|
27
|
+
|
|
28
|
+
| 2.12.0 | 2.13.0 |
|
|
29
|
+
|---|---|
|
|
30
|
+
| `private/<Class>/<objectId>/` | `acl/<Class>/<objectId>/` |
|
|
31
|
+
| `PRIVATE_PREFIX` | `ACL_PREFIX` |
|
|
32
|
+
| `isPrivatePath` | `isAclGoverned` |
|
|
33
|
+
| `privateOwnerOf` | `aclOwnerOf` |
|
|
34
|
+
| `privateDirectoryFor` | `aclDirectoryFor` |
|
|
35
|
+
| `attachPrivateFile` | `attachAclFile` |
|
|
36
|
+
| `privateFileRule` | `aclFileRule` |
|
|
37
|
+
| `PrivateFileOwner` | `AclFileOwner` |
|
|
38
|
+
| `PrivateFileRuleOptions` | `AclFileRuleOptions` |
|
|
39
|
+
|
|
40
|
+
**Migrating:** rename the imports, then **re-upload** anything already stored
|
|
41
|
+
under `private/`. Those files keep working — but as ordinary public Parse
|
|
42
|
+
files, because the guard no longer recognises their path. There is no
|
|
43
|
+
rewriting a stored filename.
|
|
44
|
+
|
|
45
|
+
The `Cache-Control: private, no-store` default is unchanged: that `private`
|
|
46
|
+
is the HTTP cache directive and has nothing to do with the prefix.
|
|
47
|
+
|
|
48
|
+
Version 2.13.0 rather than 3.0.0 despite being breaking: 3.0.0 is reserved
|
|
49
|
+
for the public `parse-server-kit` package (see the note at the top of this
|
|
50
|
+
file).
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
11
54
|
## [2.12.0]
|
|
12
55
|
|
|
13
56
|
### Added
|
|
@@ -44,12 +44,12 @@
|
|
|
44
44
|
* The usual setup, in cloud code:
|
|
45
45
|
*
|
|
46
46
|
* ```ts
|
|
47
|
-
* import {registerFileAccessRule,
|
|
48
|
-
* registerFileAccessRule(
|
|
47
|
+
* import {registerFileAccessRule, aclFileRule} from '@90soft/parse-server-kit';
|
|
48
|
+
* registerFileAccessRule(aclFileRule());
|
|
49
49
|
* ```
|
|
50
50
|
*
|
|
51
|
-
* [
|
|
52
|
-
* `
|
|
51
|
+
* [aclFileRule] is the general case: a file stored under
|
|
52
|
+
* `acl/<ClassName>/<objectId>/` is served only to a caller who can read
|
|
53
53
|
* THAT row, judged by Parse's own ACL and CLP. The permission is not a copy of
|
|
54
54
|
* the row's ACL; it IS the row's ACL — nothing to stamp, nothing to sync.
|
|
55
55
|
*/
|
|
@@ -140,46 +140,55 @@ export declare function getFileAccessRules(): FileAccessRule[];
|
|
|
140
140
|
*/
|
|
141
141
|
export declare function clearFileAccessRules(): void;
|
|
142
142
|
/**
|
|
143
|
-
* The directory prefix marking a file as governed by [
|
|
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.
|
|
144
153
|
*
|
|
145
154
|
* Parse's own `validateDirectory` reserves `metadata` and requires a directory
|
|
146
155
|
* to match `^[a-zA-Z0-9][a-zA-Z0-9_\-/]*$`, so a single lowercase word is safe.
|
|
147
156
|
* It is baked into stored file names, so changing it would orphan every file
|
|
148
157
|
* already written under the old one.
|
|
149
158
|
*/
|
|
150
|
-
export declare const
|
|
151
|
-
/** Who
|
|
152
|
-
export interface
|
|
159
|
+
export declare const ACL_PREFIX = "acl";
|
|
160
|
+
/** Who an ACL-governed file's path says owns it. */
|
|
161
|
+
export interface AclFileOwner {
|
|
153
162
|
className: string;
|
|
154
163
|
objectId: string;
|
|
155
164
|
}
|
|
156
165
|
/**
|
|
157
166
|
* Is this path governed at all?
|
|
158
167
|
*
|
|
159
|
-
* Deliberately separate from [
|
|
168
|
+
* Deliberately separate from [aclOwnerOf], and the separation is the
|
|
160
169
|
* safety property: "under the prefix" and "parses into an owner" are different
|
|
161
170
|
* questions, and a single predicate returning `owner | null` conflates them
|
|
162
171
|
* into a fail-OPEN. It would answer `null` both for an ordinary image and for
|
|
163
|
-
* `
|
|
172
|
+
* `acl/<Class>/<id>/extra/doc.jpg` — one directory deeper than expected —
|
|
164
173
|
* and so serve that document to anybody.
|
|
165
174
|
*/
|
|
166
|
-
export declare function
|
|
175
|
+
export declare function isAclGoverned(path: string): boolean;
|
|
167
176
|
/**
|
|
168
177
|
* Read the owner out of a governed path, or null if it is not well formed.
|
|
169
178
|
*
|
|
170
179
|
* `null` means "I cannot tell who owns this", which the rule treats as a
|
|
171
180
|
* refusal — never as permission.
|
|
172
181
|
*/
|
|
173
|
-
export declare function
|
|
182
|
+
export declare function aclOwnerOf(path: string): AclFileOwner | null;
|
|
174
183
|
/**
|
|
175
|
-
* The directory a row's
|
|
184
|
+
* The directory a row's ACL-governed files live in.
|
|
176
185
|
*
|
|
177
186
|
* Throws rather than quietly producing something Parse will reject: a class
|
|
178
187
|
* whose name cannot be a path segment (`_User`, since a directory must start
|
|
179
188
|
* alphanumeric) surfaces here, at the one call site, instead of as a confusing
|
|
180
189
|
* upload failure later.
|
|
181
190
|
*/
|
|
182
|
-
export declare function
|
|
191
|
+
export declare function aclDirectoryFor(className: string, objectId: string): string;
|
|
183
192
|
/**
|
|
184
193
|
* Store a file so that the owning row's ACL governs it.
|
|
185
194
|
*
|
|
@@ -188,7 +197,7 @@ export declare function privateDirectoryFor(className: string, objectId: string)
|
|
|
188
197
|
* truth. For a new record that means save, attach, save again: one extra write
|
|
189
198
|
* on a rare operation.
|
|
190
199
|
*
|
|
191
|
-
* **This should be the only way an application stores a
|
|
200
|
+
* **This should be the only way an application stores a governed file.** The
|
|
192
201
|
* prefix is the entire boundary: a document saved without it is simply public,
|
|
193
202
|
* and nothing anywhere will complain.
|
|
194
203
|
*
|
|
@@ -196,23 +205,25 @@ export declare function privateDirectoryFor(className: string, objectId: string)
|
|
|
196
205
|
* thumbnail, and no blurhash, which is a small preview of the document and
|
|
197
206
|
* travels inside DTOs where the document itself does not.
|
|
198
207
|
*/
|
|
199
|
-
export declare function
|
|
208
|
+
export declare function attachAclFile(row: Parse.Object, field: string, upload: {
|
|
200
209
|
base64: string;
|
|
201
210
|
name?: string;
|
|
202
211
|
}): Promise<void>;
|
|
203
|
-
/** Options for [
|
|
204
|
-
export interface
|
|
212
|
+
/** Options for [aclFileRule]. */
|
|
213
|
+
export interface AclFileRuleOptions {
|
|
205
214
|
/**
|
|
206
|
-
* Headers for a
|
|
215
|
+
* Headers for a governed response. Defaults to `private, no-store`.
|
|
216
|
+
*
|
|
217
|
+
* That `private` is the HTTP cache directive, unrelated to the prefix.
|
|
207
218
|
*
|
|
208
|
-
* One cached
|
|
219
|
+
* One cached governed response served to the next caller undoes the whole
|
|
209
220
|
* check, and the symptom is that the document loads — so this defaults to
|
|
210
221
|
* the strict value rather than being left to the caller.
|
|
211
222
|
*/
|
|
212
223
|
headers?: Record<string, string>;
|
|
213
224
|
}
|
|
214
225
|
/**
|
|
215
|
-
* Serve a
|
|
226
|
+
* Serve a governed file only to a caller who can read its owning row.
|
|
216
227
|
*
|
|
217
228
|
* The caller is resolved from their session token, so Parse evaluates the
|
|
218
229
|
* row's ACL and the class's CLP exactly as it would for a query. With no
|
|
@@ -220,5 +231,5 @@ export interface PrivateFileRuleOptions {
|
|
|
220
231
|
* shortcut: if the owning row is publicly readable then its file is public
|
|
221
232
|
* too, because the row's ACL is the whole rule.
|
|
222
233
|
*/
|
|
223
|
-
export declare function
|
|
234
|
+
export declare function aclFileRule(options?: AclFileRuleOptions): FileAccessRule;
|
|
224
235
|
//# 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
|
|
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"}
|
package/dist/files/fileAccess.js
CHANGED
|
@@ -45,27 +45,27 @@
|
|
|
45
45
|
* The usual setup, in cloud code:
|
|
46
46
|
*
|
|
47
47
|
* ```ts
|
|
48
|
-
* import {registerFileAccessRule,
|
|
49
|
-
* registerFileAccessRule(
|
|
48
|
+
* import {registerFileAccessRule, aclFileRule} from '@90soft/parse-server-kit';
|
|
49
|
+
* registerFileAccessRule(aclFileRule());
|
|
50
50
|
* ```
|
|
51
51
|
*
|
|
52
|
-
* [
|
|
53
|
-
* `
|
|
52
|
+
* [aclFileRule] is the general case: a file stored under
|
|
53
|
+
* `acl/<ClassName>/<objectId>/` is served only to a caller who can read
|
|
54
54
|
* THAT row, judged by Parse's own ACL and CLP. The permission is not a copy of
|
|
55
55
|
* the row's ACL; it IS the row's ACL — nothing to stamp, nothing to sync.
|
|
56
56
|
*/
|
|
57
57
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
58
|
-
exports.
|
|
58
|
+
exports.ACL_PREFIX = void 0;
|
|
59
59
|
exports.evaluateFileAccess = evaluateFileAccess;
|
|
60
60
|
exports.applyFileAccessHeaders = applyFileAccessHeaders;
|
|
61
61
|
exports.registerFileAccessRule = registerFileAccessRule;
|
|
62
62
|
exports.getFileAccessRules = getFileAccessRules;
|
|
63
63
|
exports.clearFileAccessRules = clearFileAccessRules;
|
|
64
|
-
exports.
|
|
65
|
-
exports.
|
|
66
|
-
exports.
|
|
67
|
-
exports.
|
|
68
|
-
exports.
|
|
64
|
+
exports.isAclGoverned = isAclGoverned;
|
|
65
|
+
exports.aclOwnerOf = aclOwnerOf;
|
|
66
|
+
exports.aclDirectoryFor = aclDirectoryFor;
|
|
67
|
+
exports.attachAclFile = attachAclFile;
|
|
68
|
+
exports.aclFileRule = aclFileRule;
|
|
69
69
|
/** Ordered; the first rule that governs a path decides it. */
|
|
70
70
|
const rules = [];
|
|
71
71
|
/** The hook is attached once, lazily, on the first registration. */
|
|
@@ -169,28 +169,37 @@ function getFileAccessRules() {
|
|
|
169
169
|
function clearFileAccessRules() {
|
|
170
170
|
rules.length = 0;
|
|
171
171
|
}
|
|
172
|
-
// ── The
|
|
172
|
+
// ── The ACL-governed rule ───────────────────────────────────────────────────
|
|
173
173
|
/**
|
|
174
|
-
* The directory prefix marking a file as governed by [
|
|
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".
|
|
181
|
+
*
|
|
182
|
+
* Renamed before anything depended on it, because the prefix is baked into
|
|
183
|
+
* stored filenames: changing it later orphans every file already written.
|
|
175
184
|
*
|
|
176
185
|
* Parse's own `validateDirectory` reserves `metadata` and requires a directory
|
|
177
186
|
* to match `^[a-zA-Z0-9][a-zA-Z0-9_\-/]*$`, so a single lowercase word is safe.
|
|
178
187
|
* It is baked into stored file names, so changing it would orphan every file
|
|
179
188
|
* already written under the old one.
|
|
180
189
|
*/
|
|
181
|
-
exports.
|
|
190
|
+
exports.ACL_PREFIX = 'acl';
|
|
182
191
|
/**
|
|
183
192
|
* Is this path governed at all?
|
|
184
193
|
*
|
|
185
|
-
* Deliberately separate from [
|
|
194
|
+
* Deliberately separate from [aclOwnerOf], and the separation is the
|
|
186
195
|
* safety property: "under the prefix" and "parses into an owner" are different
|
|
187
196
|
* questions, and a single predicate returning `owner | null` conflates them
|
|
188
197
|
* into a fail-OPEN. It would answer `null` both for an ordinary image and for
|
|
189
|
-
* `
|
|
198
|
+
* `acl/<Class>/<id>/extra/doc.jpg` — one directory deeper than expected —
|
|
190
199
|
* and so serve that document to anybody.
|
|
191
200
|
*/
|
|
192
|
-
function
|
|
193
|
-
return typeof path === 'string' && path.startsWith(`${exports.
|
|
201
|
+
function isAclGoverned(path) {
|
|
202
|
+
return typeof path === 'string' && path.startsWith(`${exports.ACL_PREFIX}/`);
|
|
194
203
|
}
|
|
195
204
|
/**
|
|
196
205
|
* Read the owner out of a governed path, or null if it is not well formed.
|
|
@@ -198,10 +207,10 @@ function isPrivatePath(path) {
|
|
|
198
207
|
* `null` means "I cannot tell who owns this", which the rule treats as a
|
|
199
208
|
* refusal — never as permission.
|
|
200
209
|
*/
|
|
201
|
-
function
|
|
202
|
-
if (!
|
|
210
|
+
function aclOwnerOf(path) {
|
|
211
|
+
if (!isAclGoverned(path))
|
|
203
212
|
return null;
|
|
204
|
-
// Exactly:
|
|
213
|
+
// Exactly: acl / ClassName / objectId / filename
|
|
205
214
|
const parts = path.split('/');
|
|
206
215
|
if (parts.length !== 4)
|
|
207
216
|
return null;
|
|
@@ -211,21 +220,21 @@ function privateOwnerOf(path) {
|
|
|
211
220
|
return { className, objectId };
|
|
212
221
|
}
|
|
213
222
|
/**
|
|
214
|
-
* The directory a row's
|
|
223
|
+
* The directory a row's ACL-governed files live in.
|
|
215
224
|
*
|
|
216
225
|
* Throws rather than quietly producing something Parse will reject: a class
|
|
217
226
|
* whose name cannot be a path segment (`_User`, since a directory must start
|
|
218
227
|
* alphanumeric) surfaces here, at the one call site, instead of as a confusing
|
|
219
228
|
* upload failure later.
|
|
220
229
|
*/
|
|
221
|
-
function
|
|
230
|
+
function aclDirectoryFor(className, objectId) {
|
|
222
231
|
if (!/^[a-zA-Z0-9][a-zA-Z0-9_]*$/.test(className)) {
|
|
223
|
-
throw new Parse.Error(Parse.Error.OTHER_CAUSE, `${className} cannot own
|
|
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`);
|
|
224
233
|
}
|
|
225
234
|
if (!/^[a-zA-Z0-9]+$/.test(objectId)) {
|
|
226
|
-
throw new Parse.Error(Parse.Error.OTHER_CAUSE, '
|
|
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');
|
|
227
236
|
}
|
|
228
|
-
return `${exports.
|
|
237
|
+
return `${exports.ACL_PREFIX}/${className}/${objectId}`;
|
|
229
238
|
}
|
|
230
239
|
/**
|
|
231
240
|
* Store a file so that the owning row's ACL governs it.
|
|
@@ -235,7 +244,7 @@ function privateDirectoryFor(className, objectId) {
|
|
|
235
244
|
* truth. For a new record that means save, attach, save again: one extra write
|
|
236
245
|
* on a rare operation.
|
|
237
246
|
*
|
|
238
|
-
* **This should be the only way an application stores a
|
|
247
|
+
* **This should be the only way an application stores a governed file.** The
|
|
239
248
|
* prefix is the entire boundary: a document saved without it is simply public,
|
|
240
249
|
* and nothing anywhere will complain.
|
|
241
250
|
*
|
|
@@ -243,20 +252,20 @@ function privateDirectoryFor(className, objectId) {
|
|
|
243
252
|
* thumbnail, and no blurhash, which is a small preview of the document and
|
|
244
253
|
* travels inside DTOs where the document itself does not.
|
|
245
254
|
*/
|
|
246
|
-
async function
|
|
255
|
+
async function attachAclFile(row, field, upload) {
|
|
247
256
|
if (!row.id) {
|
|
248
|
-
throw new Parse.Error(Parse.Error.OTHER_CAUSE, 'Save the row before attaching a
|
|
257
|
+
throw new Parse.Error(Parse.Error.OTHER_CAUSE, 'Save the row before attaching a governed file — its objectId is part of the path');
|
|
249
258
|
}
|
|
250
259
|
const file = new Parse.File(encodeURIComponent(upload.name ?? 'document'), {
|
|
251
260
|
base64: upload.base64,
|
|
252
261
|
});
|
|
253
262
|
// Sent as `X-Parse-File-Directory`; honoured by Parse Server from 9.5.0.
|
|
254
|
-
file.setDirectory(
|
|
263
|
+
file.setDirectory(aclDirectoryFor(row.className, row.id));
|
|
255
264
|
const saved = await file.save({ useMasterKey: true });
|
|
256
265
|
row.set(field, saved);
|
|
257
266
|
}
|
|
258
267
|
/**
|
|
259
|
-
* Serve a
|
|
268
|
+
* Serve a governed file only to a caller who can read its owning row.
|
|
260
269
|
*
|
|
261
270
|
* The caller is resolved from their session token, so Parse evaluates the
|
|
262
271
|
* row's ACL and the class's CLP exactly as it would for a query. With no
|
|
@@ -264,12 +273,12 @@ async function attachPrivateFile(row, field, upload) {
|
|
|
264
273
|
* shortcut: if the owning row is publicly readable then its file is public
|
|
265
274
|
* too, because the row's ACL is the whole rule.
|
|
266
275
|
*/
|
|
267
|
-
function
|
|
276
|
+
function aclFileRule(options = {}) {
|
|
268
277
|
const headers = options.headers ?? { 'Cache-Control': 'private, no-store' };
|
|
269
278
|
return {
|
|
270
|
-
name: '
|
|
279
|
+
name: 'acl-prefix',
|
|
271
280
|
headers,
|
|
272
|
-
governs:
|
|
281
|
+
governs: isAclGoverned,
|
|
273
282
|
async authorize({ path, user }) {
|
|
274
283
|
/*
|
|
275
284
|
* Under the prefix but not a shape we understand: REFUSE.
|
|
@@ -278,7 +287,7 @@ function privateFileRule(options = {}) {
|
|
|
278
287
|
* failure mode of this design that nobody would notice, because the
|
|
279
288
|
* document would load perfectly.
|
|
280
289
|
*/
|
|
281
|
-
const owner =
|
|
290
|
+
const owner = aclOwnerOf(path);
|
|
282
291
|
if (!owner)
|
|
283
292
|
throw notFound();
|
|
284
293
|
const sessionToken = user?.getSessionToken();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileAccess.js","sourceRoot":"","sources":["../../src/files/fileAccess.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;;;AAqGH,gDAiBC;AAQD,wDASC;AAQD,wDAsBC;AAGD,gDAEC;AAQD,oDAEC;
|
|
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,
|
|
28
|
-
export type { FileAccessRule, FileAccessContext, FileTriggerRequest,
|
|
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';
|
|
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjI,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAE3G,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAC1G,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAC9E,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,0BAA0B,EAChE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAChE,cAAc,EAAE,aAAa,EAC7B,gBAAgB,EAAE,eAAe,EACjC,aAAa,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE9E,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,qBAAqB,EAAE,gBAAgB,EACnF,sBAAsB,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAEpJ,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtH,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACnG,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAChF,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAG9E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAG1H,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACxE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAC3D,sBAAsB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACrG,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGpD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC1G,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,cAAc,EACnE,sBAAsB,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACrF,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAOxD,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,oBAAoB,EACvE,kBAAkB,EAAE,sBAAsB,EAC1C,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -2,7 +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.
|
|
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
6
|
exports.setupSwagger = exports.getSwaggerJson = void 0;
|
|
7
7
|
// ── Decorators ──
|
|
8
8
|
var parseDecorators_1 = require("./decorators/parseDecorators");
|
|
@@ -108,12 +108,12 @@ Object.defineProperty(exports, "getFileAccessRules", { enumerable: true, get: fu
|
|
|
108
108
|
Object.defineProperty(exports, "clearFileAccessRules", { enumerable: true, get: function () { return fileAccess_1.clearFileAccessRules; } });
|
|
109
109
|
Object.defineProperty(exports, "evaluateFileAccess", { enumerable: true, get: function () { return fileAccess_1.evaluateFileAccess; } });
|
|
110
110
|
Object.defineProperty(exports, "applyFileAccessHeaders", { enumerable: true, get: function () { return fileAccess_1.applyFileAccessHeaders; } });
|
|
111
|
-
Object.defineProperty(exports, "
|
|
112
|
-
Object.defineProperty(exports, "
|
|
113
|
-
Object.defineProperty(exports, "
|
|
114
|
-
Object.defineProperty(exports, "
|
|
115
|
-
Object.defineProperty(exports, "
|
|
116
|
-
Object.defineProperty(exports, "
|
|
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; } });
|
|
117
117
|
// ── Database ──
|
|
118
118
|
var schema_1 = require("./database/schema");
|
|
119
119
|
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":";AAAA,+DAA+D;;;;;AAE/D,mBAAmB;AACnB,gEAAiI;AAAxH,6GAAA,UAAU,OAAA;AAAE,6GAAA,UAAU,OAAA;AAAE,sHAAA,mBAAmB,OAAA;AAAE,oHAAA,iBAAiB,OAAA;AAAE,oHAAA,iBAAiB,OAAA;AAG1F,8DAA0G;AAAjG,+GAAA,aAAa,OAAA;AAAE,wHAAA,sBAAsB,OAAA;AAAE,sHAAA,oBAAoB,OAAA;AACpE,4DAAmE;AAA1D,sHAAA,qBAAqB,OAAA;AAE9B,kEAKoF;AAL3E,8GAAA,UAAU,OAAA;AAAE,6GAAA,SAAS,OAAA;AAAE,gHAAA,YAAY,OAAA;AAAE,+GAAA,WAAW,OAAA;AAAE,8GAAA,UAAU,OAAA;AAAE,6GAAA,SAAS,OAAA;AAC9E,+GAAA,WAAW,OAAA;AAAE,8GAAA,UAAU,OAAA;AAAE,+GAAA,WAAW,OAAA;AAAE,8HAAA,0BAA0B,OAAA;AAChE,kHAAA,cAAc,OAAA;AAAE,iHAAA,aAAa,OAAA;AAAE,oHAAA,gBAAgB,OAAA;AAAE,mHAAA,eAAe,OAAA;AAChE,kHAAA,cAAc,OAAA;AAAE,iHAAA,aAAa,OAAA;AAC7B,oHAAA,gBAAgB,OAAA;AAAE,mHAAA,eAAe,OAAA;AACjC,iHAAA,aAAa,OAAA;AAAE,mHAAA,eAAe,OAAA;AAAE,8GAAA,UAAU,OAAA;AAC5C,gEAA+D;AAAtD,kHAAA,eAAe,OAAA;AAExB,4DAA8E;AAArE,qGAAA,IAAI,OAAA;AAAE,6GAAA,YAAY,OAAA;AAAE,6GAAA,YAAY,OAAA;AAEzC,8DAAmE;AAA1D,uGAAA,KAAK,OAAA;AAAE,+GAAA,aAAa,OAAA;AAE7B,cAAc;AACd,8DAA4D;AAAnD,yGAAA,UAAU,OAAA;AASnB,mBAAmB;AACnB,sEAA0H;AAAjH,iHAAA,cAAc,OAAA;AAAE,kHAAA,eAAe,OAAA;AAAE,gHAAA,aAAa,OAAA;AAAE,uHAAA,oBAAoB,OAAA;AAE7E,eAAe;AACf,gDAA+C;AAAtC,sGAAA,SAAS,OAAA;AAElB,0BAA0B;AAC1B,mCAA2C;AAAlC,mGAAA,YAAY,OAAA;AACrB,6CAA0D;AAAjD,wGAAA,YAAY,OAAA;AAAE,oGAAA,QAAQ,OAAA;AAC/B,+CAAwE;AAA/D,sGAAA,SAAS,OAAA;AAAE,oGAAA,OAAO,OAAA;AAAE,4GAAA,eAAe,OAAA;AAG5C,kBAAkB;AAClB,yCACqG;AAD5F,oGAAA,UAAU,OAAA;AAAE,sGAAA,YAAY,OAAA;AAAE,uGAAA,aAAa,OAAA;AAAE,qGAAA,WAAW,OAAA;AAC3D,gHAAA,sBAAsB,OAAA;AAAE,+GAAA,qBAAqB,OAAA;AAAE,8GAAA,oBAAoB,OAAA;AAAE,+FAAA,KAAK,OAAA;AAC5E,uDAAoD;AAA3C,4GAAA,WAAW,OAAA;AAEpB,4BAA4B;AAC5B,+CAA0G;AAAjG,+GAAA,kBAAkB,OAAA;AAAE,4GAAA,eAAe,OAAA;AAAE,6GAAA,gBAAgB,OAAA;AAAE,2GAAA,cAAc,OAAA;AAG9E,mBAAmB;AACnB,sDACqF;AAD5E,oHAAA,sBAAsB,OAAA;AAAE,kHAAA,oBAAoB,OAAA;AAAE,4GAAA,cAAc,OAAA;AACnE,oHAAA,sBAAsB,OAAA;AAAE,uHAAA,yBAAyB,OAAA;AACnD,oDAAwD;AAA/C,2GAAA,cAAc,OAAA;AAEvB,gFAAgF;AAChF,+EAA+E;AAC/E,8EAA8E;AAC9E,8EAA8E;AAC9E,gFAAgF;AAChF,
|
|
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.
|
|
3
|
+
"version": "2.13.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",
|