@spinajs/authz-fs 0.0.0-stage → 3.0.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.
Files changed (198) hide show
  1. package/README.md +30 -2
  2. package/lib/cjs/access-config/acl-config.d.ts +23 -0
  3. package/lib/cjs/access-config/acl-config.d.ts.map +1 -0
  4. package/lib/cjs/access-config/acl-config.js +36 -0
  5. package/lib/cjs/access-config/acl-config.js.map +1 -0
  6. package/lib/cjs/access-config/index.d.ts +34 -0
  7. package/lib/cjs/access-config/index.d.ts.map +1 -0
  8. package/lib/cjs/access-config/index.js +89 -0
  9. package/lib/cjs/access-config/index.js.map +1 -0
  10. package/lib/cjs/access-config/schema.d.ts +31 -0
  11. package/lib/cjs/access-config/schema.d.ts.map +1 -0
  12. package/lib/cjs/access-config/schema.js +55 -0
  13. package/lib/cjs/access-config/schema.js.map +1 -0
  14. package/lib/cjs/acl/facade.d.ts +39 -0
  15. package/lib/cjs/acl/facade.d.ts.map +1 -0
  16. package/lib/cjs/acl/facade.js +73 -0
  17. package/lib/cjs/acl/facade.js.map +1 -0
  18. package/lib/cjs/acl/index.d.ts +6 -0
  19. package/lib/cjs/acl/index.d.ts.map +1 -0
  20. package/lib/cjs/acl/index.js +25 -0
  21. package/lib/cjs/acl/index.js.map +1 -0
  22. package/lib/cjs/acl/orm-store.d.ts +31 -0
  23. package/lib/cjs/acl/orm-store.d.ts.map +1 -0
  24. package/lib/cjs/acl/orm-store.js +199 -0
  25. package/lib/cjs/acl/orm-store.js.map +1 -0
  26. package/lib/cjs/acl/relation.d.ts +29 -0
  27. package/lib/cjs/acl/relation.d.ts.map +1 -0
  28. package/lib/cjs/acl/relation.js +60 -0
  29. package/lib/cjs/acl/relation.js.map +1 -0
  30. package/lib/cjs/acl/shared.d.ts +36 -0
  31. package/lib/cjs/acl/shared.d.ts.map +1 -0
  32. package/lib/cjs/acl/shared.js +91 -0
  33. package/lib/cjs/acl/shared.js.map +1 -0
  34. package/lib/cjs/acl/store.d.ts +43 -0
  35. package/lib/cjs/acl/store.d.ts.map +1 -0
  36. package/lib/cjs/acl/store.js +12 -0
  37. package/lib/cjs/acl/store.js.map +1 -0
  38. package/lib/cjs/adapter/index.d.ts +33 -0
  39. package/lib/cjs/adapter/index.d.ts.map +1 -0
  40. package/lib/cjs/adapter/index.js +76 -0
  41. package/lib/cjs/adapter/index.js.map +1 -0
  42. package/lib/cjs/checks.d.ts +5 -0
  43. package/lib/cjs/checks.d.ts.map +1 -0
  44. package/lib/cjs/checks.js +20 -0
  45. package/lib/cjs/checks.js.map +1 -0
  46. package/lib/cjs/http/from-fs-path.d.ts +15 -0
  47. package/lib/cjs/http/from-fs-path.d.ts.map +1 -0
  48. package/lib/cjs/http/from-fs-path.js +43 -0
  49. package/lib/cjs/http/from-fs-path.js.map +1 -0
  50. package/lib/cjs/http/index.d.ts +3 -0
  51. package/lib/cjs/http/index.d.ts.map +1 -0
  52. package/lib/cjs/http/index.js +19 -0
  53. package/lib/cjs/http/index.js.map +1 -0
  54. package/lib/cjs/http/upload.d.ts +29 -0
  55. package/lib/cjs/http/upload.d.ts.map +1 -0
  56. package/lib/cjs/http/upload.js +67 -0
  57. package/lib/cjs/http/upload.js.map +1 -0
  58. package/lib/cjs/index.d.ts +9 -0
  59. package/lib/cjs/index.d.ts.map +1 -0
  60. package/lib/cjs/index.js +25 -0
  61. package/lib/cjs/index.js.map +1 -0
  62. package/lib/cjs/middleware/decide.d.ts +32 -0
  63. package/lib/cjs/middleware/decide.d.ts.map +1 -0
  64. package/lib/cjs/middleware/decide.js +51 -0
  65. package/lib/cjs/middleware/decide.js.map +1 -0
  66. package/lib/cjs/middleware/index.d.ts +53 -0
  67. package/lib/cjs/middleware/index.d.ts.map +1 -0
  68. package/lib/cjs/middleware/index.js +236 -0
  69. package/lib/cjs/middleware/index.js.map +1 -0
  70. package/lib/cjs/middleware/owner.d.ts +10 -0
  71. package/lib/cjs/middleware/owner.d.ts.map +1 -0
  72. package/lib/cjs/middleware/owner.js +20 -0
  73. package/lib/cjs/middleware/owner.js.map +1 -0
  74. package/lib/cjs/middleware/signed-url.d.ts +22 -0
  75. package/lib/cjs/middleware/signed-url.d.ts.map +1 -0
  76. package/lib/cjs/middleware/signed-url.js +36 -0
  77. package/lib/cjs/middleware/signed-url.js.map +1 -0
  78. package/lib/cjs/migrations/AuthzFsAcl_2026_10_17_00_00_00.d.ts +8 -0
  79. package/lib/cjs/migrations/AuthzFsAcl_2026_10_17_00_00_00.d.ts.map +1 -0
  80. package/lib/cjs/migrations/AuthzFsAcl_2026_10_17_00_00_00.js +45 -0
  81. package/lib/cjs/migrations/AuthzFsAcl_2026_10_17_00_00_00.js.map +1 -0
  82. package/lib/cjs/migrations/index.d.ts +2 -0
  83. package/lib/cjs/migrations/index.d.ts.map +1 -0
  84. package/lib/cjs/migrations/index.js +18 -0
  85. package/lib/cjs/migrations/index.js.map +1 -0
  86. package/lib/cjs/package.json +1 -0
  87. package/lib/cjs/permissions/index.d.ts +3 -0
  88. package/lib/cjs/permissions/index.d.ts.map +1 -0
  89. package/lib/cjs/permissions/index.js +7 -0
  90. package/lib/cjs/permissions/index.js.map +1 -0
  91. package/lib/cjs/refs/index.d.ts +3 -0
  92. package/lib/cjs/refs/index.d.ts.map +1 -0
  93. package/lib/cjs/refs/index.js +21 -0
  94. package/lib/cjs/refs/index.js.map +1 -0
  95. package/lib/cjs/refs/refs.d.ts +34 -0
  96. package/lib/cjs/refs/refs.d.ts.map +1 -0
  97. package/lib/cjs/refs/refs.js +79 -0
  98. package/lib/cjs/refs/refs.js.map +1 -0
  99. package/lib/mjs/access-config/acl-config.d.ts +23 -0
  100. package/lib/mjs/access-config/acl-config.d.ts.map +1 -0
  101. package/lib/mjs/access-config/acl-config.js +32 -0
  102. package/lib/mjs/access-config/acl-config.js.map +1 -0
  103. package/lib/mjs/access-config/index.d.ts +34 -0
  104. package/lib/mjs/access-config/index.d.ts.map +1 -0
  105. package/lib/mjs/access-config/index.js +71 -0
  106. package/lib/mjs/access-config/index.js.map +1 -0
  107. package/lib/mjs/access-config/schema.d.ts +31 -0
  108. package/lib/mjs/access-config/schema.d.ts.map +1 -0
  109. package/lib/mjs/access-config/schema.js +52 -0
  110. package/lib/mjs/access-config/schema.js.map +1 -0
  111. package/lib/mjs/acl/facade.d.ts +39 -0
  112. package/lib/mjs/acl/facade.d.ts.map +1 -0
  113. package/lib/mjs/acl/facade.js +69 -0
  114. package/lib/mjs/acl/facade.js.map +1 -0
  115. package/lib/mjs/acl/index.d.ts +6 -0
  116. package/lib/mjs/acl/index.d.ts.map +1 -0
  117. package/lib/mjs/acl/index.js +6 -0
  118. package/lib/mjs/acl/index.js.map +1 -0
  119. package/lib/mjs/acl/orm-store.d.ts +31 -0
  120. package/lib/mjs/acl/orm-store.d.ts.map +1 -0
  121. package/lib/mjs/acl/orm-store.js +196 -0
  122. package/lib/mjs/acl/orm-store.js.map +1 -0
  123. package/lib/mjs/acl/relation.d.ts +29 -0
  124. package/lib/mjs/acl/relation.d.ts.map +1 -0
  125. package/lib/mjs/acl/relation.js +56 -0
  126. package/lib/mjs/acl/relation.js.map +1 -0
  127. package/lib/mjs/acl/shared.d.ts +36 -0
  128. package/lib/mjs/acl/shared.d.ts.map +1 -0
  129. package/lib/mjs/acl/shared.js +73 -0
  130. package/lib/mjs/acl/shared.js.map +1 -0
  131. package/lib/mjs/acl/store.d.ts +43 -0
  132. package/lib/mjs/acl/store.d.ts.map +1 -0
  133. package/lib/mjs/acl/store.js +8 -0
  134. package/lib/mjs/acl/store.js.map +1 -0
  135. package/lib/mjs/adapter/index.d.ts +33 -0
  136. package/lib/mjs/adapter/index.d.ts.map +1 -0
  137. package/lib/mjs/adapter/index.js +73 -0
  138. package/lib/mjs/adapter/index.js.map +1 -0
  139. package/lib/mjs/checks.d.ts +5 -0
  140. package/lib/mjs/checks.d.ts.map +1 -0
  141. package/lib/mjs/checks.js +16 -0
  142. package/lib/mjs/checks.js.map +1 -0
  143. package/lib/mjs/http/from-fs-path.d.ts +15 -0
  144. package/lib/mjs/http/from-fs-path.d.ts.map +1 -0
  145. package/lib/mjs/http/from-fs-path.js +40 -0
  146. package/lib/mjs/http/from-fs-path.js.map +1 -0
  147. package/lib/mjs/http/index.d.ts +3 -0
  148. package/lib/mjs/http/index.d.ts.map +1 -0
  149. package/lib/mjs/http/index.js +3 -0
  150. package/lib/mjs/http/index.js.map +1 -0
  151. package/lib/mjs/http/upload.d.ts +29 -0
  152. package/lib/mjs/http/upload.d.ts.map +1 -0
  153. package/lib/mjs/http/upload.js +64 -0
  154. package/lib/mjs/http/upload.js.map +1 -0
  155. package/lib/mjs/index.d.ts +9 -0
  156. package/lib/mjs/index.d.ts.map +1 -0
  157. package/lib/mjs/index.js +9 -0
  158. package/lib/mjs/index.js.map +1 -0
  159. package/lib/mjs/middleware/decide.d.ts +32 -0
  160. package/lib/mjs/middleware/decide.d.ts.map +1 -0
  161. package/lib/mjs/middleware/decide.js +42 -0
  162. package/lib/mjs/middleware/decide.js.map +1 -0
  163. package/lib/mjs/middleware/index.d.ts +53 -0
  164. package/lib/mjs/middleware/index.d.ts.map +1 -0
  165. package/lib/mjs/middleware/index.js +231 -0
  166. package/lib/mjs/middleware/index.js.map +1 -0
  167. package/lib/mjs/middleware/owner.d.ts +10 -0
  168. package/lib/mjs/middleware/owner.d.ts.map +1 -0
  169. package/lib/mjs/middleware/owner.js +16 -0
  170. package/lib/mjs/middleware/owner.js.map +1 -0
  171. package/lib/mjs/middleware/signed-url.d.ts +22 -0
  172. package/lib/mjs/middleware/signed-url.d.ts.map +1 -0
  173. package/lib/mjs/middleware/signed-url.js +31 -0
  174. package/lib/mjs/middleware/signed-url.js.map +1 -0
  175. package/lib/mjs/migrations/AuthzFsAcl_2026_10_17_00_00_00.d.ts +8 -0
  176. package/lib/mjs/migrations/AuthzFsAcl_2026_10_17_00_00_00.d.ts.map +1 -0
  177. package/lib/mjs/migrations/AuthzFsAcl_2026_10_17_00_00_00.js +42 -0
  178. package/lib/mjs/migrations/AuthzFsAcl_2026_10_17_00_00_00.js.map +1 -0
  179. package/lib/mjs/migrations/index.d.ts +2 -0
  180. package/lib/mjs/migrations/index.d.ts.map +1 -0
  181. package/lib/mjs/migrations/index.js +2 -0
  182. package/lib/mjs/migrations/index.js.map +1 -0
  183. package/lib/mjs/package.json +1 -0
  184. package/lib/mjs/permissions/index.d.ts +3 -0
  185. package/lib/mjs/permissions/index.d.ts.map +1 -0
  186. package/lib/mjs/permissions/index.js +4 -0
  187. package/lib/mjs/permissions/index.js.map +1 -0
  188. package/lib/mjs/refs/index.d.ts +3 -0
  189. package/lib/mjs/refs/index.d.ts.map +1 -0
  190. package/lib/mjs/refs/index.js +3 -0
  191. package/lib/mjs/refs/index.js.map +1 -0
  192. package/lib/mjs/refs/refs.d.ts +34 -0
  193. package/lib/mjs/refs/refs.d.ts.map +1 -0
  194. package/lib/mjs/refs/refs.js +71 -0
  195. package/lib/mjs/refs/refs.js.map +1 -0
  196. package/lib/tsconfig.cjs.tsbuildinfo +1 -0
  197. package/lib/tsconfig.mjs.tsbuildinfo +1 -0
  198. package/package.json +74 -4
@@ -0,0 +1,231 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { AuthzConfigError, AuthzService, SYSTEM, currentPrincipal, definite, engineLog, thrownError } from '@spinajs/authz';
11
+ import { Configuration } from '@spinajs/configuration';
12
+ import { DI, Injectable } from '@spinajs/di';
13
+ import { InvalidArgument } from '@spinajs/exceptions';
14
+ import { FsMiddleware, normalizeFsPath } from '@spinajs/fs';
15
+ import { fsAccessConfig } from '../access-config/index.js';
16
+ import { FS_ACL_LIMITS, fileAclStore } from '../acl/shared.js';
17
+ import { fsRowOf } from '../refs/index.js';
18
+ import { decideFs, domainNow, domainService, refOf, validNow, warnDenied } from './decide.js';
19
+ import { ownerOf } from './owner.js';
20
+ import { askedUntil, signingUntil } from './signed-url.js';
21
+ export { FS_NO_OWNER_TYPES } from './owner.js';
22
+ export { DEFAULT_SIGNED_URL_TTL_SECONDS } from './signed-url.js';
23
+ const PLAN = Symbol('authz-fs.plan');
24
+ const OFF = Object.freeze({ mode: 'off', domain: 'root' });
25
+ const MOVES = new Set(['move', 'rename']);
26
+ const writes = (t) => t.access.includes('write');
27
+ const deletes = (t) => t.access.includes('delete');
28
+ const where = (t) => `${t.fs.Name}:${t.path}`;
29
+ /** No row can sit at a longer path, nor under it. */
30
+ const holdsRows = (t) => t.path.length <= FS_ACL_LIMITS.path;
31
+ /**
32
+ * Whether anything answers at the target's path, whatever its kind: a file, a directory, or keys under it as a
33
+ * prefix. On a key store (S3) a key and the prefix of the same name share one ACL path, so a key written there must
34
+ * neither clear the folder's rows nor claim them.
35
+ */
36
+ async function occupied(ctx, t) {
37
+ return (await ctx.exists({ ...t, kind: 'file' })) || (await ctx.isDir(t)) || (await ctx.hasEntries(t));
38
+ }
39
+ /**
40
+ * Checks every target of every fs action with the `authz.fs.<name>` entry of the target's own filesystem (fs
41
+ * middleware design §2.1) and keeps the file ACL in step with what the action did.
42
+ */
43
+ let AuthzFsMiddleware = class AuthzFsMiddleware extends FsMiddleware {
44
+ constructor(options = {}) {
45
+ super();
46
+ this.options = options;
47
+ this.order = 100;
48
+ }
49
+ isEnabled(target) {
50
+ return this.configOf(target).mode !== 'off';
51
+ }
52
+ async before(ctx) {
53
+ const asked = ctx.action === 'signedUrl' ? askedUntil(ctx.args[0]) : undefined;
54
+ const enabled = ctx.targets.map((target) => ({ target, config: this.configOf(target.fs) })).filter((t) => t.config.mode !== 'off');
55
+ for (const { target } of enabled) {
56
+ if (writes(target) && target.path.length > FS_ACL_LIMITS.path)
57
+ throw new InvalidArgument(`${target.fs.Name}: a path of ${target.path.length} characters is longer than the ${FS_ACL_LIMITS.path} the file ACL holds`, 'path');
58
+ }
59
+ const principal = (this.options.principal ?? currentPrincipal)();
60
+ const checked = [];
61
+ for (const { target, config } of enabled)
62
+ checked.push({ target, config, decisions: principal === SYSTEM ? [] : await this.decide(principal, target, config) });
63
+ if (ctx.action === 'signedUrl' && checked.length > 0)
64
+ await this.narrowSignedUrl(ctx, checked[0], asked);
65
+ // Only after every check passed: a refused action leaves the ACL alone.
66
+ const planned = [];
67
+ for (const c of checked) {
68
+ // Probed before the IO: once rm, move or rename ran, the path is gone and no provider calls it a directory.
69
+ const probed = deletes(c.target) ? await this.probeDeleted(ctx, c) : c;
70
+ if (!writes(c.target)) {
71
+ planned.push(probed);
72
+ continue;
73
+ }
74
+ const existed = await occupied(ctx, c.target);
75
+ // Nothing lives at or under a free path, so its rows are stale (an rm outside the middleware, an update that
76
+ // failed): what is created there must not inherit them.
77
+ if (!existed)
78
+ await (await this.store()).deleteTree(c.target.fs.Name, c.target.path);
79
+ planned.push({ ...probed, existed });
80
+ }
81
+ const destination = MOVES.has(ctx.action) ? ctx.targets.find(writes) : undefined;
82
+ const plan = { principal, checked: planned, ...(destination ? { destination, destinationExisted: await occupied(ctx, destination) } : {}) };
83
+ ctx.state.set(PLAN, plan);
84
+ }
85
+ async after(ctx, result) {
86
+ const plan = ctx.state.get(PLAN);
87
+ if (!plan)
88
+ return result;
89
+ try {
90
+ await this.applyRows(ctx.action, plan);
91
+ }
92
+ catch (e) {
93
+ const log = this.log;
94
+ const fields = { error: thrownError(e), action: ctx.action, paths: ctx.targets.map(where).join(', ') };
95
+ const message = 'authz.fs: ${action} on ${paths} succeeded, but the file ACL was not updated';
96
+ if (log.error)
97
+ log.error(fields, message);
98
+ else
99
+ log.warn(fields, message);
100
+ throw e;
101
+ }
102
+ return ctx.action === 'list' && Array.isArray(result) ? this.listEach(plan, result) : result;
103
+ }
104
+ get container() {
105
+ return this.options.container ?? DI.RootContainer;
106
+ }
107
+ // Without a Configuration and an authz host (tools, other packages' unit tests) there is no authz.fs entry to
108
+ // enforce. A resolved AuthzService is the host (it resolves Configuration as it boots; AuthzDomains alone is not,
109
+ // it resolves without one): once it runs, a missing Configuration must not leave every filesystem unchecked.
110
+ configOf(target) {
111
+ if (this.container.get(Configuration))
112
+ return fsAccessConfig(target.Name, this.container);
113
+ if (this.container.isResolved(AuthzService)) {
114
+ throw new AuthzConfigError('authz.fs: an authz host is resolved but Configuration is not; await DI.resolve(Configuration) first');
115
+ }
116
+ return OFF;
117
+ }
118
+ get log() {
119
+ return (this.logger ??= this.options.log ?? engineLog('authz-fs'));
120
+ }
121
+ service(domain) {
122
+ return this.options.service ? this.options.service(domain) : domainService(this.container, domain);
123
+ }
124
+ store() {
125
+ return this.options.store ? this.options.store() : fileAclStore(this.container);
126
+ }
127
+ async decide(principal, target, config) {
128
+ const service = await this.service(config.domain);
129
+ const fsName = target.fs.Name;
130
+ const ref = refOf(fsName, target.path, target.kind);
131
+ const subject = fsRowOf(fsName, target.path, target.kind);
132
+ const mode = config.mode === 'enforce' ? 'enforce' : 'audit';
133
+ const decisions = [];
134
+ for (const access of target.access)
135
+ decisions.push(await decideFs({ fsName, mode, service, log: this.log, principal, permission: `fs:${access}`, ref, subject }));
136
+ return decisions;
137
+ }
138
+ // The URL never outlives the asked until (else the default lifetime), the TTL cap or the permit; audit narrows too.
139
+ async narrowSignedUrl(ctx, c, asked) {
140
+ const { maxTtlSeconds, defaultTtlSeconds } = c.config.signedUrl ?? {};
141
+ const now = this.options.now ? validNow(this.options.now()) : await domainNow(this.container, c.config.domain);
142
+ const until = signingUntil({ asked, defaultTtlSeconds, maxTtlSeconds, now, decisions: c.decisions });
143
+ const opts = ctx.args[0] !== null && typeof ctx.args[0] === 'object' ? ctx.args[0] : {};
144
+ ctx.args[0] = { ...opts, until };
145
+ }
146
+ async probeDeleted(ctx, c) {
147
+ const dir = await ctx.isDir(c.target);
148
+ return dir ? { ...c, dir } : { ...c, dir, shared: await ctx.hasEntries(c.target) };
149
+ }
150
+ async applyRows(action, plan) {
151
+ if (action === 'rm') {
152
+ const store = await this.store();
153
+ for (const c of plan.checked.filter((c) => holdsRows(c.target))) {
154
+ if (c.dir)
155
+ await store.deleteTree(c.target.fs.Name, c.target.path);
156
+ else if (!c.shared)
157
+ await store.deletePath(c.target.fs.Name, c.target.path);
158
+ }
159
+ return;
160
+ }
161
+ if (MOVES.has(action))
162
+ return this.moveRows(plan);
163
+ for (const c of plan.checked) {
164
+ if (c.existed !== false || c.config.stampOwner !== true || c.target.path === '')
165
+ continue;
166
+ // Only a definite allow stamps: an audit-mode denial or a conditional permit must leave no owner behind.
167
+ if (c.decisions.length === 0 || !c.decisions.every(definite))
168
+ continue;
169
+ const owner = ownerOf(plan.principal, c.decisions[0]);
170
+ if (owner)
171
+ await (await this.store()).setOwnerIfAbsent(c.target.fs.Name, c.target.path, owner);
172
+ }
173
+ }
174
+ /**
175
+ * A destination that existed keeps its rows (first writer) and the source rows go; otherwise the source rows move
176
+ * there, onto another filesystem too (one table): a directory's whole tree, anything else only its own rows. No
177
+ * owner is stamped: the rows travel with the file. A key whose prefix holds keys leaves its rows to the prefix. A
178
+ * destination too long for a row gets none: the source rows go, its parents' rows cover it.
179
+ */
180
+ async moveRows(plan) {
181
+ const checked = plan.checked.find((c) => c.target.role === 'source');
182
+ const source = checked?.target;
183
+ const destination = plan.destination;
184
+ if (!source || !destination || checked?.shared === true || !holdsRows(source))
185
+ return;
186
+ if (source.fs.Name === destination.fs.Name && source.path === destination.path)
187
+ return;
188
+ const store = await this.store();
189
+ const tree = checked?.dir === true;
190
+ if (plan.destinationExisted || !holdsRows(destination))
191
+ await (tree ? store.deleteTree(source.fs.Name, source.path) : store.deletePath(source.fs.Name, source.path));
192
+ else if (tree)
193
+ await store.moveTree(source.fs.Name, source.path, destination.fs.Name, destination.path);
194
+ else
195
+ await store.movePath(source.fs.Name, source.path, destination.fs.Name, destination.path);
196
+ }
197
+ async listEach(plan, entries) {
198
+ const dir = plan.checked[0];
199
+ if (!dir || dir.config.list !== 'each' || plan.principal === SYSTEM)
200
+ return entries;
201
+ const { target, config } = dir;
202
+ const fsName = target.fs.Name;
203
+ const service = await this.service(config.domain);
204
+ const enforce = config.mode === 'enforce';
205
+ const keep = await Promise.all(entries.map(async (entry) => {
206
+ let path;
207
+ try {
208
+ // Local providers list names inside the directory, S3 whole keys.
209
+ const joined = typeof entry === 'string' && target.path !== '' && !entry.includes('/') ? `${target.path}/${entry}` : entry;
210
+ path = normalizeFsPath(joined, target.fs.BasePath);
211
+ }
212
+ catch {
213
+ return !enforce;
214
+ }
215
+ const ref = refOf(fsName, path, 'file');
216
+ const decision = await service.check({ principal: plan.principal, permission: 'fs:stat', resource: ref, subject: fsRowOf(fsName, path, 'file') });
217
+ if (definite(decision))
218
+ return true;
219
+ if (!enforce)
220
+ warnDenied(fsName, this.log, plan.principal, 'fs:stat', ref, decision);
221
+ return !enforce;
222
+ }));
223
+ return entries.filter((_, i) => keep[i]);
224
+ }
225
+ };
226
+ AuthzFsMiddleware = __decorate([
227
+ Injectable(FsMiddleware),
228
+ __metadata("design:paramtypes", [Object])
229
+ ], AuthzFsMiddleware);
230
+ export { AuthzFsMiddleware };
231
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/middleware/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Decision, Principal, PrincipalRef } from '@spinajs/authz';
2
+ /** Principal types that never own a file nor hold an ACL relation: no one in particular, or an id many share (anonymous callers, every bearer of a link). */
3
+ export declare const FS_NO_OWNER_TYPES: ReadonlySet<string>;
4
+ /**
5
+ * Who owns what an action creates: the principal the decision ran for (under 'inherit' delegation the delegate, as
6
+ * the owner relation is later evaluated for the delegate too), else the request principal; undefined for principals
7
+ * that own nothing.
8
+ */
9
+ export declare function ownerOf(principal: Principal, decision: Decision | undefined): PrincipalRef | undefined;
10
+ //# sourceMappingURL=owner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owner.d.ts","sourceRoot":"","sources":["../../../src/middleware/owner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAExE,6JAA6J;AAC7J,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAA0D,CAAC;AAE7G;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,CAKtG"}
@@ -0,0 +1,16 @@
1
+ import { SYSTEM, UNATTENDED } from '@spinajs/authz';
2
+ /** Principal types that never own a file nor hold an ACL relation: no one in particular, or an id many share (anonymous callers, every bearer of a link). */
3
+ export const FS_NO_OWNER_TYPES = new Set(['system', 'unattended', 'anonymous', 'link']);
4
+ /**
5
+ * Who owns what an action creates: the principal the decision ran for (under 'inherit' delegation the delegate, as
6
+ * the owner relation is later evaluated for the delegate too), else the request principal; undefined for principals
7
+ * that own nothing.
8
+ */
9
+ export function ownerOf(principal, decision) {
10
+ if (principal === SYSTEM || principal === UNATTENDED)
11
+ return undefined;
12
+ const ran = decision?.principal;
13
+ const who = ran !== null && typeof ran === 'object' && typeof ran.type === 'string' && typeof ran.id === 'string' ? ran : principal;
14
+ return FS_NO_OWNER_TYPES.has(who.type) || who.id === '' ? undefined : { type: who.type, id: who.id };
15
+ }
16
+ //# sourceMappingURL=owner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owner.js","sourceRoot":"","sources":["../../../src/middleware/owner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGpD,6JAA6J;AAC7J,MAAM,CAAC,MAAM,iBAAiB,GAAwB,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;AAE7G;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,SAAoB,EAAE,QAA8B;IAC1E,IAAI,SAAS,KAAK,MAAM,IAAI,SAAS,KAAK,UAAU;QAAE,OAAO,SAAS,CAAC;IACvE,MAAM,GAAG,GAAY,QAAQ,EAAE,SAAS,CAAC;IACzC,MAAM,GAAG,GAAG,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAQ,GAAoB,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAQ,GAAoB,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAE,GAAoB,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1L,OAAO,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;AACvG,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { Decision } from '@spinajs/authz';
2
+ import { DateTime } from 'luxon';
3
+ import type { Zone } from 'luxon';
4
+ /** The lifetime of a URL nobody asked an until for: the S3 signer's own default (D9 rev.). */
5
+ export declare const DEFAULT_SIGNED_URL_TTL_SECONDS = 900;
6
+ /** An asked until, read once: the middleware signs this value, never the caller's object. */
7
+ export interface AskedUntil {
8
+ readonly millis: number;
9
+ readonly zone?: Zone;
10
+ }
11
+ /** The `until` of `signedUrl(path, opts)`'s options. */
12
+ export declare function askedUntil(opts: unknown): AskedUntil | undefined;
13
+ export interface SigningTerms {
14
+ readonly asked?: AskedUntil;
15
+ readonly defaultTtlSeconds?: number;
16
+ readonly maxTtlSeconds?: number;
17
+ readonly now: Date;
18
+ readonly decisions: readonly Decision[];
19
+ }
20
+ /** min(asked, else now + defaultTtlSeconds; now + maxTtlSeconds; decision.validUntil), in the asked zone. */
21
+ export declare function signingUntil({ asked, defaultTtlSeconds, maxTtlSeconds, now, decisions }: SigningTerms): DateTime;
22
+ //# sourceMappingURL=signed-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signed-url.d.ts","sourceRoot":"","sources":["../../../src/middleware/signed-url.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAElC,8FAA8F;AAC9F,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAElD,6FAA6F;AAC7F,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;CACtB;AAED,wDAAwD;AACxD,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAShE;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;IACnB,QAAQ,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAC;CACzC;AAED,6GAA6G;AAC7G,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,iBAAkD,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,YAAY,GAAG,QAAQ,CAQjJ"}
@@ -0,0 +1,31 @@
1
+ import { InvalidArgument } from '@spinajs/exceptions';
2
+ import { DateTime } from 'luxon';
3
+ /** The lifetime of a URL nobody asked an until for: the S3 signer's own default (D9 rev.). */
4
+ export const DEFAULT_SIGNED_URL_TTL_SECONDS = 900;
5
+ /** The `until` of `signedUrl(path, opts)`'s options. */
6
+ export function askedUntil(opts) {
7
+ const asked = opts !== null && typeof opts === 'object' ? opts.until : undefined;
8
+ if (asked === undefined || asked === null)
9
+ return undefined;
10
+ const refused = () => new InvalidArgument('signedUrl: until must be a valid luxon DateTime', 'until');
11
+ // An until that cannot be compared would drop out of the minimum and widen the URL's lifetime.
12
+ if (!DateTime.isDateTime(asked) || !asked.isValid)
13
+ throw refused();
14
+ const millis = asked.toMillis();
15
+ if (!Number.isFinite(millis))
16
+ throw refused();
17
+ return { millis, zone: asked.zone };
18
+ }
19
+ /** min(asked, else now + defaultTtlSeconds; now + maxTtlSeconds; decision.validUntil), in the asked zone. */
20
+ export function signingUntil({ asked, defaultTtlSeconds = DEFAULT_SIGNED_URL_TTL_SECONDS, maxTtlSeconds, now, decisions }) {
21
+ const terms = [asked ? asked.millis : now.getTime() + defaultTtlSeconds * 1000];
22
+ if (maxTtlSeconds !== undefined)
23
+ terms.push(now.getTime() + maxTtlSeconds * 1000);
24
+ for (const d of decisions) {
25
+ const until = d.validUntil instanceof Date ? d.validUntil.getTime() : NaN;
26
+ if (Number.isFinite(until))
27
+ terms.push(until);
28
+ }
29
+ return DateTime.fromMillis(Math.min(...terms), asked?.zone ? { zone: asked.zone } : {});
30
+ }
31
+ //# sourceMappingURL=signed-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signed-url.js","sourceRoot":"","sources":["../../../src/middleware/signed-url.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGjC,8FAA8F;AAC9F,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,CAAC;AAQlD,wDAAwD;AACxD,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,MAAM,KAAK,GAAY,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAE,IAA4B,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACnH,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5D,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,eAAe,CAAC,iDAAiD,EAAE,OAAO,CAAC,CAAC;IACtG,+FAA+F;IAC/F,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO;QAAE,MAAM,OAAO,EAAE,CAAC;IACnE,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;IAChC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,MAAM,OAAO,EAAE,CAAC;IAC9C,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;AACtC,CAAC;AAUD,6GAA6G;AAC7G,MAAM,UAAU,YAAY,CAAC,EAAE,KAAK,EAAE,iBAAiB,GAAG,8BAA8B,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,EAAgB;IACrI,MAAM,KAAK,GAAa,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,iBAAiB,GAAG,IAAI,CAAC,CAAC;IAC1F,IAAI,aAAa,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,aAAa,GAAG,IAAI,CAAC,CAAC;IAClF,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,YAAY,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QAC1E,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAC1F,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { OrmMigration } from '@spinajs/orm';
2
+ import type { OrmDriver } from '@spinajs/orm';
3
+ /** fs_acl of the fs middleware design §3.1 (OrmFileAclStore). */
4
+ export declare class AuthzFsAcl_2026_10_17_00_00_00 extends OrmMigration {
5
+ up(connection: OrmDriver): Promise<void>;
6
+ down(connection: OrmDriver): Promise<void>;
7
+ }
8
+ //# sourceMappingURL=AuthzFsAcl_2026_10_17_00_00_00.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthzFsAcl_2026_10_17_00_00_00.d.ts","sourceRoot":"","sources":["../../../src/migrations/AuthzFsAcl_2026_10_17_00_00_00.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAA8B,MAAM,cAAc,CAAC;AACnF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAI9C,iEAAiE;AACjE,qBACa,8BAA+B,SAAQ,YAAY;IACjD,EAAE,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBpD;IAEY,IAAI,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtD;CACF"}
@@ -0,0 +1,42 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Migration, OrmMigration, extractMigrationDescriptor } from '@spinajs/orm';
8
+ import { fsAclConfig } from '../access-config/acl-config.js';
9
+ /** fs_acl of the fs middleware design §3.1 (OrmFileAclStore). */
10
+ let AuthzFsAcl_2026_10_17_00_00_00 = class AuthzFsAcl_2026_10_17_00_00_00 extends OrmMigration {
11
+ async up(connection) {
12
+ await connection.schema().createTable('fs_acl', (table) => {
13
+ table.string('id', 36).notNull().primaryKey();
14
+ // byte-for-byte keys, so case variants of a path, a subject key or a relation stay apart
15
+ for (const [name, length] of [
16
+ ['fs', 64],
17
+ ['path', 512],
18
+ ['path_hash', 64],
19
+ ['subject_key', 200],
20
+ ['relation', 64],
21
+ ]) {
22
+ table.string(name, length).notNull().exact();
23
+ }
24
+ table.dateTime('expires_at');
25
+ table.string('granted_by', 100);
26
+ table.dateTime('created_at').notNull();
27
+ });
28
+ // path_hash, not path: 392 characters stay under InnoDB's 3072-byte key limit in utf8mb4 (path alone is 2048 bytes).
29
+ await connection.index().unique().table('fs_acl').name('fs_acl_uq').columns(['fs', 'path_hash', 'subject_key', 'relation']);
30
+ await connection.index().table('fs_acl').name('fs_acl_path').columns(['fs', 'path_hash', 'relation']);
31
+ }
32
+ async down(connection) {
33
+ await connection.schema().dropTable('fs_acl');
34
+ }
35
+ };
36
+ AuthzFsAcl_2026_10_17_00_00_00 = __decorate([
37
+ Migration('default')
38
+ ], AuthzFsAcl_2026_10_17_00_00_00);
39
+ export { AuthzFsAcl_2026_10_17_00_00_00 };
40
+ // Read when the migrations run, so the table lands on the connection OrmFileAclStore uses.
41
+ Object.defineProperty(extractMigrationDescriptor(AuthzFsAcl_2026_10_17_00_00_00), 'Connection', { get: () => fsAclConfig().connection, enumerable: true, configurable: true });
42
+ //# sourceMappingURL=AuthzFsAcl_2026_10_17_00_00_00.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthzFsAcl_2026_10_17_00_00_00.js","sourceRoot":"","sources":["../../../src/migrations/AuthzFsAcl_2026_10_17_00_00_00.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAGnF,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAE7D,iEAAiE;AAE1D,IAAM,8BAA8B,GAApC,MAAM,8BAA+B,SAAQ,YAAY;IACvD,KAAK,CAAC,EAAE,CAAC,UAAqB;QACnC,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YACxD,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,CAAC;YAC9C,yFAAyF;YACzF,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI;gBAC3B,CAAC,IAAI,EAAE,EAAE,CAAC;gBACV,CAAC,MAAM,EAAE,GAAG,CAAC;gBACb,CAAC,WAAW,EAAE,EAAE,CAAC;gBACjB,CAAC,aAAa,EAAE,GAAG,CAAC;gBACpB,CAAC,UAAU,EAAE,EAAE,CAAC;aACR,EAAE,CAAC;gBACX,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC;YAC/C,CAAC;YACD,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;YAC7B,KAAK,CAAC,MAAM,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YAChC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;QACzC,CAAC,CAAC,CAAC;QACH,qHAAqH;QACrH,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC;QAC5H,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;IACxG,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,UAAqB;QACrC,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAChD,CAAC;CACF,CAAA;AA1BY,8BAA8B;IAD1C,SAAS,CAAC,SAAS,CAAC;GACR,8BAA8B,CA0B1C;;AAED,2FAA2F;AAC3F,MAAM,CAAC,cAAc,CAAC,0BAA0B,CAAC,8BAA8B,CAAE,EAAE,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './AuthzFsAcl_2026_10_17_00_00_00.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/migrations/index.ts"],"names":[],"mappings":"AAAA,cAAc,qCAAqC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './AuthzFsAcl_2026_10_17_00_00_00.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/migrations/index.ts"],"names":[],"mappings":"AAAA,cAAc,qCAAqC,CAAC"}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,3 @@
1
+ import type { PermissionDef } from '@spinajs/authz';
2
+ export declare const FS_PERMISSIONS: readonly Omit<PermissionDef, 'source'>[];
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/permissions/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAMpD,eAAO,MAAM,cAAc,EAAE,SAAS,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,EAAmd,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { FS_RESOURCE_TYPES } from '../refs/index.js';
2
+ const fsPermission = (action, description, implies) => Object.freeze({ name: `fs:${action}`, resource: 'fs', action, types: FS_RESOURCE_TYPES, ...(implies ? { implies: Object.freeze([...implies]) } : {}), description });
3
+ export const FS_PERMISSIONS = Object.freeze([fsPermission('read', "Read a file's content", ['fs:stat']), fsPermission('stat', 'Check that a path exists and read its stats'), fsPermission('list', 'List the entries of a directory'), fsPermission('write', 'Create or change files and directories', ['fs:stat']), fsPermission('delete', 'Delete files and directories'), fsPermission('share', 'Create a signed URL for a file'), fsPermission('manage', 'Change the file ACL rows of a path (FsAcl)')]);
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/permissions/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,MAAM,YAAY,GAAG,CAAC,MAAc,EAAE,WAAmB,EAAE,OAA2B,EAAiC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;AAE/R,MAAM,CAAC,MAAM,cAAc,GAA6C,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,uBAAuB,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,MAAM,EAAE,6CAA6C,CAAC,EAAE,YAAY,CAAC,MAAM,EAAE,iCAAiC,CAAC,EAAE,YAAY,CAAC,OAAO,EAAE,wCAAwC,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,QAAQ,EAAE,8BAA8B,CAAC,EAAE,YAAY,CAAC,OAAO,EAAE,gCAAgC,CAAC,EAAE,YAAY,CAAC,QAAQ,EAAE,4CAA4C,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { normalizeFsPath } from '@spinajs/fs';
2
+ export * from './refs.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/refs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,cAAc,WAAW,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { normalizeFsPath } from '@spinajs/fs';
2
+ export * from './refs.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/refs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,cAAc,WAAW,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { ResourceRef } from '@spinajs/authz';
2
+ import type { FsPathKind } from '@spinajs/fs';
3
+ export type { FsPathKind };
4
+ export type FsRefType = 'fs' | FsPathKind;
5
+ export declare const FS_RESOURCE_TYPES: readonly FsRefType[];
6
+ export interface ParsedFsRef {
7
+ readonly fs: string;
8
+ /** Normalised; '' for the filesystem root. */
9
+ readonly path: string;
10
+ readonly type: FsRefType;
11
+ }
12
+ /** `{ type: 'fs', id: fsName }` for the root, else `{ type: kind, id: '<fsName>:<normalised path>' }`. */
13
+ export declare function fsRef(fsName: string, path: string, kind: FsPathKind): ResourceRef;
14
+ /** undefined for a ref that is not an fs ref, or whose id is not in the form fsRef builds. */
15
+ export declare function parseFsRef(ref: ResourceRef): ParsedFsRef | undefined;
16
+ /** The subject row of an fs ref: what `resource.*` conditions and relation resolvers read (design §13). */
17
+ export interface FsRow {
18
+ /** The ref id: `attribute(row, 'id')` equals it. */
19
+ readonly id: string;
20
+ readonly type: FsRefType;
21
+ readonly fs: string;
22
+ /** Normalised; '' for the filesystem root. */
23
+ readonly path: string;
24
+ }
25
+ /** The row of a ref fsRef builds; null for a ref parseFsRef refuses. */
26
+ export declare function fsRow(ref: ResourceRef): FsRow | null;
27
+ /** The row of an already normalised path, with no second normalisation; '' gives the fs row. */
28
+ export declare function fsRowOf(fsName: string, normalised: string, type: FsRefType): FsRow;
29
+ /**
30
+ * `[self, parent dirs nearest first, fs, GLOBAL]`, null for a ref parseFsRef refuses. This does not know which
31
+ * filesystems exist: an fs name no provider has still gets a chain.
32
+ */
33
+ export declare function fsAncestors(ref: ResourceRef): readonly ResourceRef[] | null;
34
+ //# sourceMappingURL=refs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refs.d.ts","sourceRoot":"","sources":["../../../src/refs/refs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIlD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAI9C,YAAY,EAAE,UAAU,EAAE,CAAC;AAC3B,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,UAAU,CAAC;AAE1C,eAAO,MAAM,iBAAiB,EAAE,SAAS,SAAS,EAAkD,CAAC;AAErG,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;CAC1B;AAKD,0GAA0G;AAC1G,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,WAAW,CAKjF;AAED,8FAA8F;AAC9F,wBAAgB,UAAU,CAAC,GAAG,EAAE,WAAW,GAAG,WAAW,GAAG,SAAS,CAiBpE;AAED,2GAA2G;AAC3G,MAAM,WAAW,KAAK;IACpB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wEAAwE;AACxE,wBAAgB,KAAK,CAAC,GAAG,EAAE,WAAW,GAAG,KAAK,GAAG,IAAI,CAGpD;AAED,gGAAgG;AAChG,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,KAAK,CAElF;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,WAAW,GAAG,SAAS,WAAW,EAAE,GAAG,IAAI,CAgB3E"}
@@ -0,0 +1,71 @@
1
+ import { GLOBAL } from '@spinajs/authz';
2
+ import { _check_arg, _one_of } from '@spinajs/util';
3
+ import { normalizeFsPath } from '@spinajs/fs';
4
+ import { checkFsName } from '../checks.js';
5
+ export const FS_RESOURCE_TYPES = Object.freeze(['fs', 'dir', 'file']);
6
+ // The first ':' of a file or dir id ends the fs name, so a name must not hold one.
7
+ const isFsName = (name) => typeof name === 'string' && name.length > 0 && !name.includes(':');
8
+ /** `{ type: 'fs', id: fsName }` for the root, else `{ type: kind, id: '<fsName>:<normalised path>' }`. */
9
+ export function fsRef(fsName, path, kind) {
10
+ checkFsName(fsName);
11
+ _check_arg(_one_of(['file', 'dir']))(kind, 'kind');
12
+ const normalised = normalizeFsPath(path);
13
+ return normalised === '' ? { type: 'fs', id: fsName } : { type: kind, id: `${fsName}:${normalised}` };
14
+ }
15
+ /** undefined for a ref that is not an fs ref, or whose id is not in the form fsRef builds. */
16
+ export function parseFsRef(ref) {
17
+ if (!ref || typeof ref.id !== 'string') {
18
+ return undefined;
19
+ }
20
+ if (ref.type === 'fs') {
21
+ return isFsName(ref.id) ? { fs: ref.id, path: '', type: 'fs' } : undefined;
22
+ }
23
+ if (ref.type !== 'file' && ref.type !== 'dir') {
24
+ return undefined;
25
+ }
26
+ const at = ref.id.indexOf(':');
27
+ const fs = ref.id.slice(0, at);
28
+ const path = ref.id.slice(at + 1);
29
+ if (at <= 0 || path === '' || !isCanonical(path)) {
30
+ return undefined;
31
+ }
32
+ return { fs, path, type: ref.type };
33
+ }
34
+ /** The row of a ref fsRef builds; null for a ref parseFsRef refuses. */
35
+ export function fsRow(ref) {
36
+ const parsed = parseFsRef(ref);
37
+ return parsed ? fsRowOf(parsed.fs, parsed.path, parsed.type) : null;
38
+ }
39
+ /** The row of an already normalised path, with no second normalisation; '' gives the fs row. */
40
+ export function fsRowOf(fsName, normalised, type) {
41
+ return normalised === '' ? Object.freeze({ id: fsName, type: 'fs', fs: fsName, path: '' }) : Object.freeze({ id: `${fsName}:${normalised}`, type, fs: fsName, path: normalised });
42
+ }
43
+ /**
44
+ * `[self, parent dirs nearest first, fs, GLOBAL]`, null for a ref parseFsRef refuses. This does not know which
45
+ * filesystems exist: an fs name no provider has still gets a chain.
46
+ */
47
+ export function fsAncestors(ref) {
48
+ const parsed = parseFsRef(ref);
49
+ if (!parsed) {
50
+ return null;
51
+ }
52
+ const chain = [];
53
+ if (parsed.type !== 'fs') {
54
+ chain.push({ type: parsed.type, id: `${parsed.fs}:${parsed.path}` });
55
+ const segments = parsed.path.split('/');
56
+ for (let n = segments.length - 1; n > 0; n--) {
57
+ chain.push({ type: 'dir', id: `${parsed.fs}:${segments.slice(0, n).join('/')}` });
58
+ }
59
+ }
60
+ chain.push({ type: 'fs', id: parsed.fs }, GLOBAL);
61
+ return chain;
62
+ }
63
+ function isCanonical(path) {
64
+ try {
65
+ return normalizeFsPath(path) === path;
66
+ }
67
+ catch {
68
+ return false;
69
+ }
70
+ }
71
+ //# sourceMappingURL=refs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refs.js","sourceRoot":"","sources":["../../../src/refs/refs.ts"],"names":[],"mappings":"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"}