@memberjunction/storage 6.2.0-edge.4 → 6.2.0-edge.6

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.
Files changed (41) hide show
  1. package/dist/FileStorageEngine.d.ts +45 -1
  2. package/dist/FileStorageEngine.d.ts.map +1 -1
  3. package/dist/FileStorageEngine.js +72 -4
  4. package/dist/FileStorageEngine.js.map +1 -1
  5. package/dist/StorageAccessEvaluator.d.ts +196 -0
  6. package/dist/StorageAccessEvaluator.d.ts.map +1 -0
  7. package/dist/StorageAccessEvaluator.js +435 -0
  8. package/dist/StorageAccessEvaluator.js.map +1 -0
  9. package/dist/config.d.ts +22 -10
  10. package/dist/config.d.ts.map +1 -1
  11. package/dist/config.js +3 -0
  12. package/dist/config.js.map +1 -1
  13. package/dist/drivers/AWSFileStorage.d.ts +8 -0
  14. package/dist/drivers/AWSFileStorage.d.ts.map +1 -1
  15. package/dist/drivers/AWSFileStorage.js +11 -0
  16. package/dist/drivers/AWSFileStorage.js.map +1 -1
  17. package/dist/drivers/AzureFileStorage.d.ts +9 -0
  18. package/dist/drivers/AzureFileStorage.d.ts.map +1 -1
  19. package/dist/drivers/AzureFileStorage.js +22 -24
  20. package/dist/drivers/AzureFileStorage.js.map +1 -1
  21. package/dist/drivers/DropboxFileStorage.d.ts.map +1 -1
  22. package/dist/drivers/DropboxFileStorage.js +0 -51
  23. package/dist/drivers/DropboxFileStorage.js.map +1 -1
  24. package/dist/drivers/GoogleDriveFileStorage.d.ts +49 -2
  25. package/dist/drivers/GoogleDriveFileStorage.d.ts.map +1 -1
  26. package/dist/drivers/GoogleDriveFileStorage.js +80 -16
  27. package/dist/drivers/GoogleDriveFileStorage.js.map +1 -1
  28. package/dist/generic/FileStorageBase.d.ts +17 -1
  29. package/dist/generic/FileStorageBase.d.ts.map +1 -1
  30. package/dist/generic/FileStorageBase.js +18 -0
  31. package/dist/generic/FileStorageBase.js.map +1 -1
  32. package/dist/generic/ObjectKeys.d.ts +61 -0
  33. package/dist/generic/ObjectKeys.d.ts.map +1 -0
  34. package/dist/generic/ObjectKeys.js +82 -0
  35. package/dist/generic/ObjectKeys.js.map +1 -0
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +2 -0
  39. package/dist/index.js.map +1 -1
  40. package/package.json +6 -6
  41. package/readme.md +74 -0
@@ -1,4 +1,5 @@
1
1
  import { Readable } from 'stream';
2
+ import { StorageObjectKeyNormalizer } from './ObjectKeys.js';
2
3
  /**
3
4
  * Represents the payload returned by the CreatePreAuthUploadUrl method.
4
5
  * This type contains the necessary information for uploading a file to a storage provider.
@@ -369,7 +370,7 @@ export interface StorageProviderConfig {
369
370
  * `driver.GetObject is not a function`. The marker turns an unresolved driver key into an
370
371
  * immediate, named failure at the point of resolution.
371
372
  */
372
- export declare abstract class FileStorageBase {
373
+ export declare abstract class FileStorageBase implements StorageObjectKeyNormalizer {
373
374
  /**
374
375
  * The name of this storage provider, used in error messages and logging.
375
376
  * Each implementation must define this property with a descriptive name.
@@ -860,6 +861,21 @@ export declare abstract class FileStorageBase {
860
861
  * @returns A Promise that resolves to a boolean indicating if the directory exists.
861
862
  */
862
863
  abstract DirectoryExists(directoryPath: string): Promise<boolean>;
864
+ /**
865
+ * The canonical form of an object key for this storage — what the storage access checks compare when they ask whether
866
+ * an object backs an `MJ: Files` row (see `StorageAccessEvaluator.UnreadableTrackedObjectKeys`). Both the key a client
867
+ * sends and the key a row stores go through this one method, so two spellings this driver resolves to the same object
868
+ * must canonicalize alike.
869
+ *
870
+ * The default ({@link NormalizeStorageObjectKey}) trims the key, collapses runs of `/` and strips leading and
871
+ * trailing `/` — right for every driver whose spellings differ only in slashes. A driver that adds its own root or
872
+ * prefix to SOME keys and not others (S3's key prefix) overrides this to return the key relative to that root.
873
+ * Case is preserved; callers compare case-insensitively.
874
+ *
875
+ * @param objectKey - An object key as a client or an `MJ: Files` row spells it
876
+ * @returns The canonical key: relative to this driver's root, no leading/trailing `/`, no repeated `/`
877
+ */
878
+ NormalizeObjectKey(objectKey: string): string;
863
879
  /**
864
880
  * Initialize storage provider with optional configuration.
865
881
  *
@@ -1 +1 @@
1
- {"version":3,"file":"FileStorageBase.d.ts","sourceRoot":"","sources":["../../src/generic/FileStorageBase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FileStorageBase.d.ts","sourceRoot":"","sources":["../../src/generic/FileStorageBase.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { RequiresSubclass } from '@memberjunction/global';
8
+ import { NormalizeStorageObjectKey } from './ObjectKeys.js';
8
9
  /**
9
10
  * Builds an HTTP `Range` header value (`bytes=Start-End` or `bytes=Start-`) from a
10
11
  * {@link ByteRange}. Shared by streaming-capable drivers so the inclusive-range
@@ -218,6 +219,23 @@ let FileStorageBase = class FileStorageBase {
218
219
  GetObjectStream(params) {
219
220
  throw new StreamingNotSupportedError(this.providerName);
220
221
  }
222
+ /**
223
+ * The canonical form of an object key for this storage — what the storage access checks compare when they ask whether
224
+ * an object backs an `MJ: Files` row (see `StorageAccessEvaluator.UnreadableTrackedObjectKeys`). Both the key a client
225
+ * sends and the key a row stores go through this one method, so two spellings this driver resolves to the same object
226
+ * must canonicalize alike.
227
+ *
228
+ * The default ({@link NormalizeStorageObjectKey}) trims the key, collapses runs of `/` and strips leading and
229
+ * trailing `/` — right for every driver whose spellings differ only in slashes. A driver that adds its own root or
230
+ * prefix to SOME keys and not others (S3's key prefix) overrides this to return the key relative to that root.
231
+ * Case is preserved; callers compare case-insensitively.
232
+ *
233
+ * @param objectKey - An object key as a client or an `MJ: Files` row spells it
234
+ * @returns The canonical key: relative to this driver's root, no leading/trailing `/`, no repeated `/`
235
+ */
236
+ NormalizeObjectKey(objectKey) {
237
+ return NormalizeStorageObjectKey(objectKey);
238
+ }
221
239
  /**
222
240
  * Initialize storage provider with optional configuration.
223
241
  *
@@ -1 +1 @@
1
- {"version":3,"file":"FileStorageBase.js","sourceRoot":"","sources":["../../src/generic/FileStorageBase.ts"],"names":[],"mappings":";;;;;;AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AA8H1D;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAgB;IACnD,OAAO,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;AAC3F,CAAC;AAiKD;;;;GAIG;AACH,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAClD;;;;;OAKG;IACH,YAAY,UAAkB,EAAE,YAAoB;QAClD,KAAK,CAAC,cAAc,UAAU,6BAA6B,YAAY,WAAW,CAAC,CAAC;QACpF,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACnD;;;;OAIG;IACH,YAAY,YAAoB;QAC9B,KAAK,CAAC,uDAAuD,YAAY,WAAW,CAAC,CAAC;QACtF,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF;AA+CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEI,IAAe,eAAe,GAA9B,MAAe,eAAe;IAkBnC;;;OAGG;IACH,IAAW,SAAS;QAClB,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,IAAW,WAAW;QACpB,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED;;;;;;OAMG;IACO,8BAA8B,CAAC,UAAkB;QACzD,MAAM,IAAI,yBAAyB,CAAC,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IACrE,CAAC;IAED;;;;;;;;;;OAUG;IACI,OAAO;QACZ,0CAA0C;IAC5C,CAAC;IA4QD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,IAAW,iBAAiB;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;;;OAQG;IACH,IAAW,qBAAqB;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;OAIG;IACH,IAAW,uBAAuB;QAChC,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+CG;IACI,eAAe,CAAC,MAA6B;QAClD,MAAM,IAAI,0BAA0B,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1D,CAAC;IA4GD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiEG;IACI,KAAK,CAAC,UAAU,CAAC,MAA8B;QACpD,oEAAoE;QACpE,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC;YACnC,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC;QACzC,CAAC;IACH,CAAC;CA8GF,CAAA;AAzsBqB,eAAe;IADpC,gBAAgB,EAAE;GACG,eAAe,CAysBpC"}
1
+ {"version":3,"file":"FileStorageBase.js","sourceRoot":"","sources":["../../src/generic/FileStorageBase.ts"],"names":[],"mappings":";;;;;;AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAA8B,MAAM,cAAc,CAAC;AA8HrF;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAgB;IACnD,OAAO,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;AAC3F,CAAC;AAiKD;;;;GAIG;AACH,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAClD;;;;;OAKG;IACH,YAAY,UAAkB,EAAE,YAAoB;QAClD,KAAK,CAAC,cAAc,UAAU,6BAA6B,YAAY,WAAW,CAAC,CAAC;QACpF,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACnD;;;;OAIG;IACH,YAAY,YAAoB;QAC9B,KAAK,CAAC,uDAAuD,YAAY,WAAW,CAAC,CAAC;QACtF,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF;AA+CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEI,IAAe,eAAe,GAA9B,MAAe,eAAe;IAkBnC;;;OAGG;IACH,IAAW,SAAS;QAClB,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,IAAW,WAAW;QACpB,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED;;;;;;OAMG;IACO,8BAA8B,CAAC,UAAkB;QACzD,MAAM,IAAI,yBAAyB,CAAC,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IACrE,CAAC;IAED;;;;;;;;;;OAUG;IACI,OAAO;QACZ,0CAA0C;IAC5C,CAAC;IA4QD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,IAAW,iBAAiB;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;;;OAQG;IACH,IAAW,qBAAqB;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;OAIG;IACH,IAAW,uBAAuB;QAChC,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+CG;IACI,eAAe,CAAC,MAA6B;QAClD,MAAM,IAAI,0BAA0B,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1D,CAAC;IA4GD;;;;;;;;;;;;;OAaG;IACI,kBAAkB,CAAC,SAAiB;QACzC,OAAO,yBAAyB,CAAC,SAAS,CAAC,CAAC;IAC9C,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiEG;IACI,KAAK,CAAC,UAAU,CAAC,MAA8B;QACpD,oEAAoE;QACpE,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC;YACnC,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC;QACzC,CAAC;IACH,CAAC;CA8GF,CAAA;AA3tBqB,eAAe;IADpC,gBAAgB,EAAE;GACG,eAAe,CA2tBpC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @fileoverview Object-key canonicalization and the key-safety rule the storage access checks use.
3
+ *
4
+ * The tracked-file rule ("an object backing an `MJ: Files` row the caller cannot read is refused") compares the key a
5
+ * client sends with the key an `MJ: Files` row stores. Drivers accept several spellings of the same object — S3 adds or
6
+ * keeps its key prefix, Box strips leading and trailing `/`, Dropbox adds a leading `/` — so a raw string comparison would
7
+ * let `/hr/secret.pdf` or `hr/secret.pdf/` through as "untracked" while the driver serves `hr/secret.pdf`. Both sides are
8
+ * therefore put through ONE canonicalizer ({@link StorageObjectKeyNormalizer}, implemented by every driver as
9
+ * `FileStorageBase.NormalizeObjectKey`) and compared case-insensitively.
10
+ *
11
+ * The canonical form is deliberately coarse: when two spellings might name the same object they canonicalize alike. A
12
+ * coarse form can only make the rule refuse more, never less.
13
+ *
14
+ * @module @memberjunction/storage
15
+ */
16
+ /**
17
+ * The object key an `MJ: Files` row resolves to: its `ProviderKey`, or its `Name` when `ProviderKey` is null or empty.
18
+ * The one rule every route from a row to its bytes and the tracked-file lookup use, so a row cannot be served under one
19
+ * key and checked under another.
20
+ */
21
+ export declare function StorageObjectKeyOf(file: {
22
+ ProviderKey?: string | null;
23
+ Name?: string | null;
24
+ }): string;
25
+ /** Turns an object key into the canonical form the storage access checks compare. */
26
+ export interface StorageObjectKeyNormalizer {
27
+ /**
28
+ * The canonical form of `objectKey` for this storage: the object the driver would address, relative to the driver's
29
+ * own root or prefix, with no leading or trailing `/` and no repeated `/`. Case is preserved; callers compare
30
+ * case-insensitively.
31
+ */
32
+ NormalizeObjectKey(objectKey: string): string;
33
+ }
34
+ /**
35
+ * The default canonical form of an object key: trimmed, with runs of `/` collapsed to one and leading and trailing `/`
36
+ * removed. Case is preserved (callers compare case-insensitively).
37
+ *
38
+ * Nothing else is rewritten. A key whose meaning depends on the provider (a backslash, a `.`/`..` segment, a
39
+ * meaning-changing percent encoding) is refused by {@link IsSafeStorageObjectKey} before it is ever compared, so the
40
+ * canonical form never has to guess what a driver would make of it.
41
+ */
42
+ export declare function NormalizeStorageObjectKey(objectKey: string): string;
43
+ /** The default {@link StorageObjectKeyNormalizer}: {@link NormalizeStorageObjectKey}. */
44
+ export declare const DEFAULT_OBJECT_KEY_NORMALIZER: StorageObjectKeyNormalizer;
45
+ /**
46
+ * Whether an object key is one the storage access checks will compare at all. A key that fails is refused (treated as
47
+ * an object the caller may not read) rather than canonicalized, because its meaning depends on the provider:
48
+ *
49
+ * - a `.` or `..` path segment, including one padded with whitespace or zero-width characters — a hierarchical
50
+ * provider (Box, Dropbox, Google Drive, SharePoint) may resolve it as traversal, so the object served need not be
51
+ * the one compared;
52
+ * - a backslash — some providers and URL layers treat it as a path separator;
53
+ * - a percent-encoded `/`, `\`, `.` or control character (`%2F`, `%5C`, `%2E`, `%00`–`%1F`, `%7F`) — a pre-signed URL
54
+ * carries the key in its path, where the provider decodes it, so `hr%2Fsecret.pdf` would be compared as one segment and
55
+ * served as `hr/secret.pdf`. A literal `%` followed by anything else (`50% off.pdf`, `%20`) is allowed;
56
+ * - a raw control character (including NUL).
57
+ *
58
+ * An empty or whitespace-only key is not unsafe — it names the root, which no `MJ: Files` row tracks.
59
+ */
60
+ export declare function IsSafeStorageObjectKey(objectKey: string): boolean;
61
+ //# sourceMappingURL=ObjectKeys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObjectKeys.d.ts","sourceRoot":"","sources":["../../src/generic/ObjectKeys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,MAAM,CAEtG;AAED,qFAAqF;AACrF,MAAM,WAAW,0BAA0B;IACvC;;;;OAIG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CACjD;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CASnE;AAED,yFAAyF;AACzF,eAAO,MAAM,6BAA6B,EAAE,0BAE3C,CAAC;AAQF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAQjE"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * @fileoverview Object-key canonicalization and the key-safety rule the storage access checks use.
3
+ *
4
+ * The tracked-file rule ("an object backing an `MJ: Files` row the caller cannot read is refused") compares the key a
5
+ * client sends with the key an `MJ: Files` row stores. Drivers accept several spellings of the same object — S3 adds or
6
+ * keeps its key prefix, Box strips leading and trailing `/`, Dropbox adds a leading `/` — so a raw string comparison would
7
+ * let `/hr/secret.pdf` or `hr/secret.pdf/` through as "untracked" while the driver serves `hr/secret.pdf`. Both sides are
8
+ * therefore put through ONE canonicalizer ({@link StorageObjectKeyNormalizer}, implemented by every driver as
9
+ * `FileStorageBase.NormalizeObjectKey`) and compared case-insensitively.
10
+ *
11
+ * The canonical form is deliberately coarse: when two spellings might name the same object they canonicalize alike. A
12
+ * coarse form can only make the rule refuse more, never less.
13
+ *
14
+ * @module @memberjunction/storage
15
+ */
16
+ /**
17
+ * The object key an `MJ: Files` row resolves to: its `ProviderKey`, or its `Name` when `ProviderKey` is null or empty.
18
+ * The one rule every route from a row to its bytes and the tracked-file lookup use, so a row cannot be served under one
19
+ * key and checked under another.
20
+ */
21
+ export function StorageObjectKeyOf(file) {
22
+ return file.ProviderKey || file.Name || '';
23
+ }
24
+ /**
25
+ * The default canonical form of an object key: trimmed, with runs of `/` collapsed to one and leading and trailing `/`
26
+ * removed. Case is preserved (callers compare case-insensitively).
27
+ *
28
+ * Nothing else is rewritten. A key whose meaning depends on the provider (a backslash, a `.`/`..` segment, a
29
+ * meaning-changing percent encoding) is refused by {@link IsSafeStorageObjectKey} before it is ever compared, so the
30
+ * canonical form never has to guess what a driver would make of it.
31
+ */
32
+ export function NormalizeStorageObjectKey(objectKey) {
33
+ // Split and join rather than regex trimming: dropping empty segments collapses runs of `/` and strips leading and
34
+ // trailing `/` in one linear pass with no backtracking. CodeQL flags a trailing-anchor pattern such as `/\/+$/` on
35
+ // caller input as polynomial (js/polynomial-redos), so this form keeps every pattern out of the path.
36
+ return (objectKey ?? '')
37
+ .trim()
38
+ .split('/')
39
+ .filter(segment => segment.length > 0)
40
+ .join('/');
41
+ }
42
+ /** The default {@link StorageObjectKeyNormalizer}: {@link NormalizeStorageObjectKey}. */
43
+ export const DEFAULT_OBJECT_KEY_NORMALIZER = {
44
+ NormalizeObjectKey: NormalizeStorageObjectKey
45
+ };
46
+ /** Characters whose percent-encoded form a provider or URL layer could decode into a path-changing character. */
47
+ const MEANING_CHANGING_ENCODED = /%(2f|5c|2e|[01][0-9a-f]|7f)/i;
48
+ /** ASCII control characters, including NUL. */
49
+ const CONTROL_CHARACTERS = /[\x00-\x1f\x7f]/;
50
+ /**
51
+ * Whether an object key is one the storage access checks will compare at all. A key that fails is refused (treated as
52
+ * an object the caller may not read) rather than canonicalized, because its meaning depends on the provider:
53
+ *
54
+ * - a `.` or `..` path segment, including one padded with whitespace or zero-width characters — a hierarchical
55
+ * provider (Box, Dropbox, Google Drive, SharePoint) may resolve it as traversal, so the object served need not be
56
+ * the one compared;
57
+ * - a backslash — some providers and URL layers treat it as a path separator;
58
+ * - a percent-encoded `/`, `\`, `.` or control character (`%2F`, `%5C`, `%2E`, `%00`–`%1F`, `%7F`) — a pre-signed URL
59
+ * carries the key in its path, where the provider decodes it, so `hr%2Fsecret.pdf` would be compared as one segment and
60
+ * served as `hr/secret.pdf`. A literal `%` followed by anything else (`50% off.pdf`, `%20`) is allowed;
61
+ * - a raw control character (including NUL).
62
+ *
63
+ * An empty or whitespace-only key is not unsafe — it names the root, which no `MJ: Files` row tracks.
64
+ */
65
+ export function IsSafeStorageObjectKey(objectKey) {
66
+ if (typeof objectKey !== 'string') {
67
+ return false;
68
+ }
69
+ if (objectKey.includes('\\') || CONTROL_CHARACTERS.test(objectKey) || MEANING_CHANGING_ENCODED.test(objectKey)) {
70
+ return false;
71
+ }
72
+ return !objectKey.split('/').map(visibleSegment).some(segment => segment === '.' || segment === '..');
73
+ }
74
+ /**
75
+ * A path segment as a filesystem would read it: Unicode format characters (`\p{Cf}`: zero-width space, joiners,
76
+ * word joiner, BOM, soft hyphen) removed, then trimmed. Without this, `\u200B..\u200B` would not compare equal to
77
+ * `..` though a driver that drops such characters would resolve it as traversal.
78
+ */
79
+ function visibleSegment(segment) {
80
+ return segment.replace(/\p{Cf}/gu, '').trim();
81
+ }
82
+ //# sourceMappingURL=ObjectKeys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObjectKeys.js","sourceRoot":"","sources":["../../src/generic/ObjectKeys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAA2D;IAC1F,OAAO,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;AAC/C,CAAC;AAYD;;;;;;;GAOG;AACH,MAAM,UAAU,yBAAyB,CAAC,SAAiB;IACvD,kHAAkH;IAClH,mHAAmH;IACnH,sGAAsG;IACtG,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC;SACnB,IAAI,EAAE;SACN,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;SACrC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnB,CAAC;AAED,yFAAyF;AACzF,MAAM,CAAC,MAAM,6BAA6B,GAA+B;IACrE,kBAAkB,EAAE,yBAAyB;CAChD,CAAC;AAEF,iHAAiH;AACjH,MAAM,wBAAwB,GAAG,8BAA8B,CAAC;AAEhE,+CAA+C;AAC/C,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAE7C;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACpD,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,wBAAwB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7G,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,CAAC,CAAC;AAC1G,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,OAAe;IACnC,OAAO,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAClD,CAAC"}
package/dist/index.d.ts 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.d.ts.map
@@ -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",
4
+ "version": "6.2.0-edge.6",
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.4",
25
- "@memberjunction/core-entities": "6.2.0-edge.4",
26
- "@memberjunction/credentials": "6.2.0-edge.4",
27
- "@memberjunction/global": "6.2.0-edge.4",
28
- "@memberjunction/network-utils": "6.2.0-edge.4",
24
+ "@memberjunction/core": "6.2.0-edge.6",
25
+ "@memberjunction/core-entities": "6.2.0-edge.6",
26
+ "@memberjunction/credentials": "6.2.0-edge.6",
27
+ "@memberjunction/global": "6.2.0-edge.6",
28
+ "@memberjunction/network-utils": "6.2.0-edge.6",
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