@memberjunction/storage 6.2.0-edge.4 → 6.2.0-edge.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FileStorageEngine.d.ts +45 -1
- package/dist/FileStorageEngine.d.ts.map +1 -1
- package/dist/FileStorageEngine.js +72 -4
- package/dist/FileStorageEngine.js.map +1 -1
- package/dist/StorageAccessEvaluator.d.ts +196 -0
- package/dist/StorageAccessEvaluator.d.ts.map +1 -0
- package/dist/StorageAccessEvaluator.js +435 -0
- package/dist/StorageAccessEvaluator.js.map +1 -0
- package/dist/config.d.ts +22 -10
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/drivers/AWSFileStorage.d.ts +8 -0
- package/dist/drivers/AWSFileStorage.d.ts.map +1 -1
- package/dist/drivers/AWSFileStorage.js +11 -0
- package/dist/drivers/AWSFileStorage.js.map +1 -1
- package/dist/drivers/AzureFileStorage.d.ts +9 -0
- package/dist/drivers/AzureFileStorage.d.ts.map +1 -1
- package/dist/drivers/AzureFileStorage.js +22 -24
- package/dist/drivers/AzureFileStorage.js.map +1 -1
- package/dist/drivers/GoogleDriveFileStorage.d.ts +49 -2
- package/dist/drivers/GoogleDriveFileStorage.d.ts.map +1 -1
- package/dist/drivers/GoogleDriveFileStorage.js +80 -16
- package/dist/drivers/GoogleDriveFileStorage.js.map +1 -1
- package/dist/generic/FileStorageBase.d.ts +17 -1
- package/dist/generic/FileStorageBase.d.ts.map +1 -1
- package/dist/generic/FileStorageBase.js +18 -0
- package/dist/generic/FileStorageBase.js.map +1 -1
- package/dist/generic/ObjectKeys.d.ts +61 -0
- package/dist/generic/ObjectKeys.d.ts.map +1 -0
- package/dist/generic/ObjectKeys.js +82 -0
- package/dist/generic/ObjectKeys.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/readme.md +74 -0
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,9 @@ export * from './drivers/SharePointFileStorage.js';
|
|
|
6
6
|
export * from './drivers/DropboxFileStorage.js';
|
|
7
7
|
export * from './drivers/BoxFileStorage.js';
|
|
8
8
|
export * from './generic/FileStorageBase.js';
|
|
9
|
+
export * from './generic/ObjectKeys.js';
|
|
9
10
|
export * from './util.js';
|
|
10
11
|
export * from './config.js';
|
|
11
12
|
export * from './FileStorageEngine.js';
|
|
13
|
+
export * from './StorageAccessEvaluator.js';
|
|
12
14
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/storage",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "6.2.0-edge.
|
|
4
|
+
"version": "6.2.0-edge.5",
|
|
5
5
|
"description": "This library provides a set of objects that handle the interface between the server-side API and various cloud storage providers.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
"@azure/identity": "^4.13.0",
|
|
22
22
|
"@azure/storage-blob": "^12.30.0",
|
|
23
23
|
"@google-cloud/storage": "^7.19.0",
|
|
24
|
-
"@memberjunction/core": "6.2.0-edge.
|
|
25
|
-
"@memberjunction/core-entities": "6.2.0-edge.
|
|
26
|
-
"@memberjunction/credentials": "6.2.0-edge.
|
|
27
|
-
"@memberjunction/global": "6.2.0-edge.
|
|
28
|
-
"@memberjunction/network-utils": "6.2.0-edge.
|
|
24
|
+
"@memberjunction/core": "6.2.0-edge.5",
|
|
25
|
+
"@memberjunction/core-entities": "6.2.0-edge.5",
|
|
26
|
+
"@memberjunction/credentials": "6.2.0-edge.5",
|
|
27
|
+
"@memberjunction/global": "6.2.0-edge.5",
|
|
28
|
+
"@memberjunction/network-utils": "6.2.0-edge.5",
|
|
29
29
|
"@microsoft/mgt-element": "^4.6.0",
|
|
30
30
|
"@microsoft/mgt-msal2-provider": "^4.6.0",
|
|
31
31
|
"@microsoft/mgt-sharepoint-provider": "^4.6.0",
|
package/readme.md
CHANGED
|
@@ -251,6 +251,79 @@ sequenceDiagram
|
|
|
251
251
|
Driver-->>App: initialized driver
|
|
252
252
|
```
|
|
253
253
|
|
|
254
|
+
### Account Permissions (`StorageAccessEvaluator`)
|
|
255
|
+
|
|
256
|
+
Neither `FileStorageEngine.GetDriver()` nor the utility functions check who is asking — they act on whatever account
|
|
257
|
+
they are given. Anything that acts on an account on a user's behalf must ask `StorageAccessEvaluator` first. It is the
|
|
258
|
+
one place `MJ: File Storage Account Permissions` (Everyone / Role / User rows with `CanRead` / `CanWrite`) are decided,
|
|
259
|
+
and the one place the tracked-file rule (below) is decided:
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
import { FileStorageEngine, StorageAccessEvaluator } from '@memberjunction/storage';
|
|
263
|
+
|
|
264
|
+
const evaluator = StorageAccessEvaluator.Instance;
|
|
265
|
+
|
|
266
|
+
// Throws StorageAccountAccessDeniedError ("You do not have access to this storage account or it does not exist.")
|
|
267
|
+
await evaluator.AssertAccountAccess(accountId, contextUser, 'Write', provider);
|
|
268
|
+
|
|
269
|
+
// Or filter a list: returns the NormalizeUUID'd IDs the user may read
|
|
270
|
+
const readable = await evaluator.AccessibleAccountIDs(accountIds, contextUser, 'Read', provider);
|
|
271
|
+
|
|
272
|
+
// Object keys in an account that back an MJ: Files row the user cannot read — pass the account's driver so keys are
|
|
273
|
+
// compared the way that driver addresses them
|
|
274
|
+
const driver = await FileStorageEngine.Instance.GetDriver(accountId, contextUser);
|
|
275
|
+
const blocked = await evaluator.UnreadableTrackedObjectKeys(account.ProviderID, [objectKey], contextUser, provider, driver);
|
|
276
|
+
// Or throw TrackedFileAccessDeniedError ("You do not have access to this file or it does not exist.")
|
|
277
|
+
await evaluator.AssertTrackedObjectsReadable(account.ProviderID, [objectKey], contextUser, provider, driver);
|
|
278
|
+
|
|
279
|
+
// From an MJ: Files row (loaded as the caller) to its bytes: account gate + tracked-file rule, then the driver
|
|
280
|
+
const resolved = await FileStorageEngine.Instance.ResolveFileObject(fileRow, contextUser, 'Read', provider);
|
|
281
|
+
const bytes = resolved ? await resolved.Driver.GetObject({ fullPath: resolved.ObjectKey }) : null;
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**The account rule**
|
|
285
|
+
|
|
286
|
+
- **Evaluated per call** — nothing is cached, so a grant or revocation applies to the next call.
|
|
287
|
+
- **Read as the system user, decided for the caller** — the permission rows are read with the MJ system user
|
|
288
|
+
(`WellKnownUserSource`), so a caller who cannot read the permission table is not mistaken for an account with no rows.
|
|
289
|
+
- **Never truncated** — every read sets `IgnoreMaxRows`, so the entity's row cap cannot drop an account's rows (which
|
|
290
|
+
would make it look like an account with none) or a tracked file's row.
|
|
291
|
+
- **An account with no permission rows is open** to every authenticated user (the current product rule, kept in one
|
|
292
|
+
place in the evaluator; flipping it needs a data migration that writes explicit `Everyone` rows).
|
|
293
|
+
- **`Read` vs `Write`** — listing, downloading, signing a download URL and searching need `CanRead`; uploading, signing an
|
|
294
|
+
upload URL, copying into, moving, deleting and creating directories need `CanWrite`. A copy between accounts needs
|
|
295
|
+
`Read` on the source and `Write` on the destination.
|
|
296
|
+
- **Fails closed** — an unknown account, a malformed ID, a user without `UserRoles`, a missing system user or a failed
|
|
297
|
+
read all mean "no access". An unknown account is refused with the same message as a restricted one.
|
|
298
|
+
|
|
299
|
+
**The tracked-file rule**
|
|
300
|
+
|
|
301
|
+
- An object that backs an `MJ: Files` row — the row's `ProviderKey`, or `Name` when `ProviderKey` is empty, on the
|
|
302
|
+
account's storage provider — may be read, signed, listed or returned by search only when the caller can read that row
|
|
303
|
+
(entity permission and row-level security, asked as the caller). Untracked objects are governed by the account rule
|
|
304
|
+
alone. Rows are keyed by provider, not account, so a row in another account on the same provider counts too.
|
|
305
|
+
- **Writes**: an object may be overwritten (upload, upload URL, copy/move destination), moved, copied out of or deleted
|
|
306
|
+
only when the caller can read every row that tracks it — the minimum; the account rule still requires `CanWrite`.
|
|
307
|
+
`UploadFile` applies this before `PutObject`.
|
|
308
|
+
- **Matching** — the client's key and the row's key both go through the account driver's `NormalizeObjectKey` (default:
|
|
309
|
+
trim, collapse repeated `/`, strip leading/trailing `/`; S3 also strips its key prefix the way it addresses keys) and
|
|
310
|
+
are compared case-insensitively, so `/hr/secret.pdf`, `hr/secret.pdf/` and `HR/Secret.PDF` are the same tracked
|
|
311
|
+
object.
|
|
312
|
+
- **Refused keys** — a key with a `.`/`..` segment, a backslash, a percent-encoded `/`, `\`, `.` or control character
|
|
313
|
+
(`%2F`, `%5C`, `%2E`, `%00`–`%1F`, `%7F`) or a raw control character is never compared: its meaning depends on the
|
|
314
|
+
provider, so it is treated as an object the caller may not read. A literal `%` otherwise (`50% off.pdf`) is fine.
|
|
315
|
+
- **File-ID routes** (`DownloadUrl`, `GetFileContents`, `CreateMediaAccessToken`, `DeleteFile`, the artifact download
|
|
316
|
+
URL, the agent file handler, the realtime recording reader) go through `FileStorageEngine.ResolveFileObject`: the
|
|
317
|
+
row's provider resolves to its first account, which must allow the access, and the row's object gets the tracked-file
|
|
318
|
+
rule — so a row whose `ProviderKey`/`Name` aliases another row's object is refused. On the server, `ProviderID` and
|
|
319
|
+
`ProviderKey` cannot be changed on an existing row by a client save (`MJFileEntityServer`).
|
|
320
|
+
|
|
321
|
+
**Pre-authenticated URLs** are scoped to one object: Azure Blob URLs carry a blob-scoped service SAS (`sr=b`, `r` to
|
|
322
|
+
download, `cw` to upload), never an account SAS; every URL expires after 10 minutes.
|
|
323
|
+
|
|
324
|
+
The MJServer storage GraphQL routes, the File Storage core actions (and `List Storage Accounts`, which lists only the
|
|
325
|
+
accounts the caller may read), `StorageSearchProvider` and `SearchEngine`'s late permission filter all use it.
|
|
326
|
+
|
|
254
327
|
### Using Utility Functions
|
|
255
328
|
|
|
256
329
|
The library provides high-level utility functions that work with MemberJunction's entity system:
|
|
@@ -594,6 +667,7 @@ Each provider also supports environment variable configuration. Environment vari
|
|
|
594
667
|
| `STORAGE_GOOGLE_DRIVE_REFRESH_TOKEN` | OAuth refresh token |
|
|
595
668
|
| `STORAGE_GOOGLE_DRIVE_REDIRECT_URI` | OAuth redirect URI |
|
|
596
669
|
| `STORAGE_GDRIVE_ROOT_FOLDER_ID` | Root folder ID (optional) |
|
|
670
|
+
| `STORAGE_GDRIVE_DRIVE_ID` | Shared Drive ID. Required for a service account to upload, since a service account has no storage quota of its own. Also the default root when no root folder is set. A credential record carries it as `driveID`. |
|
|
597
671
|
| `STORAGE_GDRIVE_KEY_FILE` | Service account key file (legacy) |
|
|
598
672
|
| `STORAGE_GDRIVE_CREDENTIALS_JSON` | Service account credentials JSON (legacy) |
|
|
599
673
|
|