@aalis/plugin-authority 0.1.1 → 0.2.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/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # @aalis/plugin-authority
2
2
 
3
- 运行时插件
4
-
3
+ 权限系统:纯能力委托图、跨平台身份绑定、受限能力临时委托
5
4
  ## 角色
6
5
 
7
6
  运行时插件
@@ -0,0 +1,54 @@
1
+ import type { ConfigManager, Logger } from '@aalis/core';
2
+ import type { AccessConfirmHandler, AccessRequest, AuthorityService, AuthorityUserEntry, AuthorizeRequest, TemporaryGrant, UserCapabilityOverrides, UserIdentity } from '@aalis/plugin-authority-api';
3
+ import type { StorageService } from '@aalis/plugin-storage-api';
4
+ export declare class AuthorityManager implements AuthorityService {
5
+ private readonly config;
6
+ private readonly logger;
7
+ private store;
8
+ private confirmHandlers;
9
+ private tempGrants;
10
+ private grantSeq;
11
+ /** 临时放行策略(restrictedPolicy)的开启时间戳(运行时态,不持久化;重启即失效) */
12
+ private policyEnabledAt;
13
+ constructor(config: ConfigManager, logger: Logger, storage: StorageService);
14
+ init(): Promise<void>;
15
+ isOwner(platform: string, userId?: string): boolean;
16
+ /** 解析用户能力来源:被绑身份的 grant 以主账户为真源,deny 取自身∪主账户并集 */
17
+ private resolve;
18
+ /** 一条能力是否为 restricted(命中内置 + config.restrictedCapabilities) */
19
+ private isRestrictedCap;
20
+ authorize(identity: {
21
+ platform: string;
22
+ userId?: string;
23
+ }, request: AuthorizeRequest): string | null;
24
+ setUserCapabilities(granter: UserIdentity | null, target: UserIdentity, caps: UserCapabilityOverrides): void;
25
+ removeUser(platform: string, userId: string): void;
26
+ listDelegatees(granter: UserIdentity | null): AuthorityUserEntry[];
27
+ setConfirmHandler(platform: string, handler: AccessConfirmHandler): void;
28
+ /**
29
+ * 该请求是否已被(白名单/会话内临时委托)放行(内部用,requestAccess 调用)。
30
+ * restrictedPolicy 白名单是管理员全局策略;会话临时授予按 capability + sessionId 匹配
31
+ * (一次会话的临时批准不跨会话泄漏到其他会话)。
32
+ */
33
+ private isTemporarilyAllowed;
34
+ requestAccess(request: AccessRequest): Promise<boolean>;
35
+ listTemporaryGrants(): TemporaryGrant[];
36
+ revokeTemporaryGrant(id: string): boolean;
37
+ markPolicyEnabled(): void;
38
+ private normalizeDecision;
39
+ private consumeTempGrant;
40
+ private createTempGrant;
41
+ private pruneTempGrants;
42
+ listUsers(): AuthorityUserEntry[];
43
+ setPassword(platform: string, userId: string, password: string): Promise<void>;
44
+ verifyPassword(platform: string, userId: string, password: string): Promise<boolean>;
45
+ hasPassword(platform: string, userId: string): boolean;
46
+ createBindCode(platform: string, userId: string): {
47
+ code: string;
48
+ expiresAt: number;
49
+ };
50
+ consumeBindCode(code: string, identity: UserIdentity): UserIdentity;
51
+ unlinkIdentity(platform: string, userId: string): boolean;
52
+ save(): void;
53
+ }
54
+ //# sourceMappingURL=authority-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authority-manager.d.ts","sourceRoot":"","sources":["../src/authority-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EACV,oBAAoB,EAEpB,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAEhB,cAAc,EACd,uBAAuB,EACvB,YAAY,EACb,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AA+BhE,qBAAa,gBAAiB,YAAW,gBAAgB;IASrD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IATzB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,eAAe,CAA2C;IAClE,OAAO,CAAC,UAAU,CAAqC;IACvD,OAAO,CAAC,QAAQ,CAAK;IACrB,sDAAsD;IACtD,OAAO,CAAC,eAAe,CAAuB;gBAG3B,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,MAAM,EAC/B,OAAO,EAAE,cAAc;IAKzB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO;IAOnD,kDAAkD;IAClD,OAAO,CAAC,OAAO;IAWf,+DAA+D;IAC/D,OAAO,CAAC,eAAe;IAOvB,SAAS,CAAC,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI;IA4BpG,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,uBAAuB,GAAG,IAAI;IAkC5G,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAIlD,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,GAAG,kBAAkB,EAAE;IAWlE,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAIxE;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAmBtB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IAiB7D,mBAAmB,IAAI,cAAc,EAAE;IAKvC,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAMzC,iBAAiB,IAAI,IAAI;IAIzB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,eAAe;IAQvB,SAAS,IAAI,kBAAkB,EAAE;IA8BjC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAG9E,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAGpF,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAGtD,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAGrF,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,YAAY;IAGnE,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAGzD,IAAI,IAAI,IAAI;CAGb"}
@@ -0,0 +1,288 @@
1
+ import { hasCapability, matchAnyCap, rejectedDelegations } from './capability-model.js';
2
+ import { UserStore } from './user-store.js';
3
+ // ════════════════════════════════════════════════════════════
4
+ // AuthorityManager —— 纯能力委托模型的 AuthorityService 实现(策略层)
5
+ //
6
+ // owner=`*`;用户有效能力 = (public ∪ 授予的 restricted) − denied;
7
+ // 委托子集约束(非 owner 只能授予自己持有的);restricted 能力的临时委托。
8
+ // 数据层(users.json v3 / 绑定 / 密码)委托给 UserStore;纯判定见 capability-model。
9
+ // ════════════════════════════════════════════════════════════
10
+ /** 内置受限能力:写用户表 / 计划任务 / 源码根 —— 默认禁、仅 owner 或被授予者可触达 */
11
+ const BUILTIN_RESTRICTED = [
12
+ 'storage:path:data:/users.json:write',
13
+ 'storage:path:data:/users.json:delete',
14
+ 'storage:path:data:/scheduler-jobs.json:write',
15
+ 'storage:path:data:/scheduler-jobs.json:delete',
16
+ 'storage:aalis:write',
17
+ 'storage:aalis:delete',
18
+ ];
19
+ export class AuthorityManager {
20
+ config;
21
+ logger;
22
+ store;
23
+ confirmHandlers = new Map();
24
+ tempGrants = new Map();
25
+ grantSeq = 0;
26
+ /** 临时放行策略(restrictedPolicy)的开启时间戳(运行时态,不持久化;重启即失效) */
27
+ policyEnabledAt = null;
28
+ constructor(config, logger, storage) {
29
+ this.config = config;
30
+ this.logger = logger;
31
+ this.store = new UserStore(storage, this.logger.child('authority'));
32
+ }
33
+ init() {
34
+ return this.store.load();
35
+ }
36
+ // ── owner ─────────────────────────────────────────────────
37
+ isOwner(platform, userId) {
38
+ if (!userId)
39
+ return false;
40
+ if ((platform === 'webui' || platform === 'cli') && userId === 'console')
41
+ return true;
42
+ const owners = this.config.get('owners') ?? [];
43
+ return owners.some((o) => o.platform === platform && o.userId === userId);
44
+ }
45
+ /** 解析用户能力来源:被绑身份的 grant 以主账户为真源,deny 取自身∪主账户并集 */
46
+ resolve(platform, userId) {
47
+ const isOwner = this.isOwner(platform, userId);
48
+ const ownKey = userId ? `${platform}:${userId}` : undefined;
49
+ const ownRecord = ownKey ? this.store.get(ownKey) : undefined;
50
+ const accountKey = ownKey ? this.store.accountOf(ownKey) : undefined;
51
+ const accountRecord = accountKey ? this.store.get(accountKey) : undefined;
52
+ const grants = (accountKey ? accountRecord?.caps?.grant : ownRecord?.caps?.grant) ?? [];
53
+ const denies = [...(ownRecord?.caps?.deny ?? []), ...(accountRecord?.caps?.deny ?? [])];
54
+ return { isOwner, grants, denies };
55
+ }
56
+ /** 一条能力是否为 restricted(命中内置 + config.restrictedCapabilities) */
57
+ isRestrictedCap(cap) {
58
+ if (matchAnyCap(BUILTIN_RESTRICTED, cap))
59
+ return true;
60
+ const extra = this.config.get('restrictedCapabilities') ?? [];
61
+ return matchAnyCap(extra, cap);
62
+ }
63
+ // ── 能力统一闸(静态判定;临时委托在 requestAccess)──────────
64
+ authorize(identity, request) {
65
+ const res = this.resolve(identity.platform, identity.userId);
66
+ const denied = this.config.get('deniedCapabilities') ?? [];
67
+ const check = (cap, restricted) => {
68
+ // 全局硬禁用:连 owner 都压过
69
+ if (matchAnyCap(denied, cap))
70
+ return `已被系统禁用: ${cap}`;
71
+ // 复用纯模型:deny > owner > (public→放行) > granted
72
+ const ok = hasCapability({ isOwner: res.isOwner, publicCaps: restricted ? [] : [cap], grants: res.grants, denies: res.denies }, cap);
73
+ if (ok)
74
+ return null;
75
+ return restricted ? `权限不足: "${cap}" 需授予后使用` : `已被禁止: ${cap}`;
76
+ };
77
+ // 主能力:可见性由调用方传入(已应用 visibilityOverrides)
78
+ const primary = check(request.capability, request.visibility === 'restricted');
79
+ if (primary)
80
+ return primary;
81
+ // 资源能力:受限性由 restrictedCapabilities 判定
82
+ for (const cap of request.resourceCapabilities ?? []) {
83
+ const rejection = check(cap, this.isRestrictedCap(cap));
84
+ if (rejection)
85
+ return rejection;
86
+ }
87
+ return null;
88
+ }
89
+ // ── 委托(子集约束)────────────────────────────────────────
90
+ setUserCapabilities(granter, target, caps) {
91
+ const normalize = (list) => {
92
+ const cleaned = [...new Set((list ?? []).map(p => p.trim()).filter(Boolean))];
93
+ return cleaned.length > 0 ? cleaned : undefined;
94
+ };
95
+ const grant = normalize(caps.grant);
96
+ const deny = normalize(caps.deny);
97
+ // 子集约束:非 owner 授予方只能授予自己持有的能力(单调递减防越权)
98
+ if (granter && !this.isOwner(granter.platform, granter.userId)) {
99
+ const gRes = this.resolve(granter.platform, granter.userId);
100
+ const bad = rejectedDelegations({ isOwner: false, publicCaps: [], grants: gRes.grants, denies: gRes.denies }, grant ?? []);
101
+ if (bad.length > 0) {
102
+ throw new Error(`越权:你不持有这些能力,无法授予:${bad.join('、')}`);
103
+ }
104
+ }
105
+ const key = `${target.platform}:${target.userId}`;
106
+ const existing = this.store.get(key);
107
+ const grantedBy = granter ? `${granter.platform}:${granter.userId}` : existing?.grantedBy;
108
+ const next = { ...existing, caps: grant || deny ? { grant, deny } : undefined, grantedBy };
109
+ if (!next.caps && !next.secret && !next.links) {
110
+ this.store.delete(key);
111
+ }
112
+ else {
113
+ this.store.set(key, next);
114
+ }
115
+ this.logger.debug(`设置能力委托: ${key} grant=${grant?.length ?? 0} deny=${deny?.length ?? 0} by=${grantedBy ?? '-'}`);
116
+ }
117
+ removeUser(platform, userId) {
118
+ if (this.store.delete(`${platform}:${userId}`))
119
+ this.logger.debug(`删除用户记录: ${platform}:${userId}`);
120
+ }
121
+ listDelegatees(granter) {
122
+ const granterKey = granter ? `${granter.platform}:${granter.userId}` : null;
123
+ return this.listUsers().filter(u => {
124
+ const entry = this.store.get(`${u.platform}:${u.userId}`);
125
+ // owner(null)列顶层:无 grantedBy 且非 owner 自身的用户
126
+ if (granterKey === null)
127
+ return !entry?.grantedBy && !u.isOwner;
128
+ return entry?.grantedBy === granterKey;
129
+ });
130
+ }
131
+ // ── 临时能力委托(restricted 能力的时限/限次放行)──────────────
132
+ setConfirmHandler(platform, handler) {
133
+ this.confirmHandlers.set(platform, handler);
134
+ }
135
+ /**
136
+ * 该请求是否已被(白名单/会话内临时委托)放行(内部用,requestAccess 调用)。
137
+ * restrictedPolicy 白名单是管理员全局策略;会话临时授予按 capability + sessionId 匹配
138
+ * (一次会话的临时批准不跨会话泄漏到其他会话)。
139
+ */
140
+ isTemporarilyAllowed(request) {
141
+ const policy = this.config.get('restrictedPolicy');
142
+ if (policy?.allow && policy.allow.length > 0) {
143
+ if (!policy.duration ||
144
+ policy.duration <= 0 ||
145
+ (this.policyEnabledAt && (Date.now() - this.policyEnabledAt) / 1000 <= policy.duration)) {
146
+ if (matchAnyCap(policy.allow, request.capability))
147
+ return true;
148
+ }
149
+ }
150
+ this.pruneTempGrants();
151
+ for (const g of this.tempGrants.values()) {
152
+ if (g.sessionId !== request.sessionId)
153
+ continue;
154
+ if (g.capability === request.capability || matchAnyCap([g.capability], request.capability))
155
+ return true;
156
+ }
157
+ return false;
158
+ }
159
+ async requestAccess(request) {
160
+ if (this.isTemporarilyAllowed(request)) {
161
+ this.consumeTempGrant(request);
162
+ return true;
163
+ }
164
+ const handler = this.confirmHandlers.get(request.platform);
165
+ if (!handler)
166
+ return false;
167
+ try {
168
+ const decision = this.normalizeDecision(await handler(request));
169
+ if (decision.allowed && decision.grant?.scope === 'session')
170
+ this.createTempGrant(request, decision);
171
+ return decision.allowed;
172
+ }
173
+ catch (err) {
174
+ this.logger.warn(`临时委托确认回调异常: ${err}`);
175
+ return false;
176
+ }
177
+ }
178
+ listTemporaryGrants() {
179
+ this.pruneTempGrants();
180
+ return [...this.tempGrants.values()].map(g => ({ ...g }));
181
+ }
182
+ revokeTemporaryGrant(id) {
183
+ const ok = this.tempGrants.delete(id);
184
+ if (ok)
185
+ this.logger.info(`已撤销临时能力委托: ${id}`);
186
+ return ok;
187
+ }
188
+ markPolicyEnabled() {
189
+ this.policyEnabledAt = Date.now();
190
+ }
191
+ normalizeDecision(result) {
192
+ return typeof result === 'boolean' ? { allowed: result } : result;
193
+ }
194
+ consumeTempGrant(request) {
195
+ for (const g of this.tempGrants.values()) {
196
+ if (g.capability !== request.capability)
197
+ continue;
198
+ if (g.sessionId !== request.sessionId)
199
+ continue;
200
+ g.used++;
201
+ if (g.maxUses && g.used >= g.maxUses)
202
+ this.tempGrants.delete(g.id);
203
+ return;
204
+ }
205
+ }
206
+ createTempGrant(request, decision) {
207
+ const spec = decision.grant;
208
+ if (!spec || spec.scope !== 'session')
209
+ return;
210
+ this.pruneTempGrants();
211
+ const durationSeconds = Math.max(1, Math.min(spec.durationSeconds ?? 600, 3600));
212
+ const grant = {
213
+ id: `grant_${this.grantSeq++}_${Date.now()}`,
214
+ capability: request.capability,
215
+ name: request.name,
216
+ type: request.type,
217
+ sessionId: request.sessionId,
218
+ platform: request.platform,
219
+ userId: request.userId,
220
+ expiresAt: Date.now() + durationSeconds * 1000,
221
+ maxUses: spec.maxUses,
222
+ used: 0,
223
+ createdAt: Date.now(),
224
+ };
225
+ this.tempGrants.set(grant.id, grant);
226
+ this.logger.info(`创建临时能力委托: ${grant.capability} session=${grant.sessionId} ${durationSeconds}s grant=${grant.id}`);
227
+ }
228
+ pruneTempGrants() {
229
+ const now = Date.now();
230
+ for (const [id, g] of this.tempGrants) {
231
+ if (g.expiresAt <= now || (g.maxUses && g.used >= g.maxUses))
232
+ this.tempGrants.delete(id);
233
+ }
234
+ }
235
+ // ── 列表 ──────────────────────────────────────────────────
236
+ listUsers() {
237
+ const result = [];
238
+ for (const [key, record] of this.store.entries()) {
239
+ const idx = key.indexOf(':');
240
+ const platform = key.slice(0, idx);
241
+ const userId = key.slice(idx + 1);
242
+ result.push({
243
+ platform,
244
+ userId,
245
+ isOwner: this.isOwner(platform, userId),
246
+ grant: record.caps?.grant,
247
+ deny: record.caps?.deny,
248
+ grantedBy: record.grantedBy,
249
+ hasPassword: record.secret ? true : undefined,
250
+ links: record.links,
251
+ linkedTo: this.store.accountOf(key),
252
+ });
253
+ }
254
+ // 无自身记录的被绑身份也可见
255
+ for (const [identityKey, accountKey] of this.store.links()) {
256
+ if (this.store.get(identityKey))
257
+ continue;
258
+ const idx = identityKey.indexOf(':');
259
+ const platform = identityKey.slice(0, idx);
260
+ const userId = identityKey.slice(idx + 1);
261
+ result.push({ platform, userId, isOwner: this.isOwner(platform, userId), linkedTo: accountKey });
262
+ }
263
+ return result;
264
+ }
265
+ // ── 密码 / 绑定(委托给 UserStore)──────────────────────────
266
+ setPassword(platform, userId, password) {
267
+ return this.store.setPassword(platform, userId, password);
268
+ }
269
+ verifyPassword(platform, userId, password) {
270
+ return this.store.verifyPassword(platform, userId, password);
271
+ }
272
+ hasPassword(platform, userId) {
273
+ return this.store.hasPassword(platform, userId);
274
+ }
275
+ createBindCode(platform, userId) {
276
+ return this.store.createBindCode(platform, userId);
277
+ }
278
+ consumeBindCode(code, identity) {
279
+ return this.store.consumeBindCode(code, identity);
280
+ }
281
+ unlinkIdentity(platform, userId) {
282
+ return this.store.unlinkIdentity(platform, userId);
283
+ }
284
+ save() {
285
+ this.store.save();
286
+ }
287
+ }
288
+ //# sourceMappingURL=authority-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authority-manager.js","sourceRoot":"","sources":["../src/authority-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /** 单条能力 glob 匹配:`*` 通配任意字符段。pattern 为 glob,value 为具体能力串。 */
2
+ export declare function capMatches(pattern: string, value: string): boolean;
3
+ /** value 是否被 patterns 中任一 glob 命中。 */
4
+ export declare function matchAnyCap(patterns: readonly string[], value: string): boolean;
5
+ /**
6
+ * 用户的能力解析输入。
7
+ * - publicCaps:全局声明为 public 的能力集(来自各操作声明,所有人默认拥有)。
8
+ * - grants:该用户被授予的 restricted 能力 glob(委托加)。
9
+ * - denies:该用户被禁用的能力 glob(委托减,最高优先)。
10
+ * - isOwner:owner = `*`,拥有一切。
11
+ */
12
+ export interface CapabilityResolution {
13
+ isOwner: boolean;
14
+ publicCaps: readonly string[];
15
+ grants: readonly string[];
16
+ denies: readonly string[];
17
+ }
18
+ /**
19
+ * 用户对某具体能力是否有效。优先级:deny > owner(*) > public > granted(restricted)。
20
+ * 注意 deny 高于 owner——owner 也可被显式 deny 某能力(如临时收回)。
21
+ */
22
+ export declare function hasCapability(res: CapabilityResolution, cap: string): boolean;
23
+ /**
24
+ * 委托子集约束:授予方把 requested 能力委托给下层是否合法。
25
+ * owner 可委托一切;非 owner 只能委托「自己当前有效持有」的能力(防越权放大)。
26
+ * 返回越权(不可委托)的能力项;空数组 = 全部合法。
27
+ *
28
+ * 语义:具体能力按 hasCapability 判定;委托更宽的 glob(超出自己持有的)会被拒。
29
+ */
30
+ export declare function rejectedDelegations(granter: CapabilityResolution, requested: readonly string[]): string[];
31
+ //# sourceMappingURL=capability-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-model.d.ts","sourceRoot":"","sources":["../src/capability-model.ts"],"names":[],"mappings":"AAWA,4DAA4D;AAC5D,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAKlE;AAMD,sCAAsC;AACtC,wBAAgB,WAAW,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAG/E;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,oBAAoB,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAI7E;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAGzG"}
@@ -0,0 +1,53 @@
1
+ // ════════════════════════════════════════════════════════════
2
+ // 纯能力委托模型 —— feat/auth-capability 重构基石(纯函数,无副作用,便于单测)
3
+ //
4
+ // 用「能力 + 默认可见性 public/restricted + 委托加减」替代数字等级:
5
+ // - 能力是 glob 标识(tool:x / command:x / storage:path:...:write / *)。
6
+ // - 作者为每个操作声明默认可见性:public(默认所有人可用)/ restricted(默认禁,需授予)。
7
+ // - 用户有效能力 = owner ? 全部 : (所有 public ∪ 被授予的 restricted) − 被禁用的;deny 优先。
8
+ // - 委托子集约束:非 owner 授予方只能把「自己当前有效持有」的能力委托给下层,
9
+ // 单调递减、天然防越权。owner = `*`,可委托一切。
10
+ // ════════════════════════════════════════════════════════════
11
+ /** 单条能力 glob 匹配:`*` 通配任意字符段。pattern 为 glob,value 为具体能力串。 */
12
+ export function capMatches(pattern, value) {
13
+ if (pattern === '*' || pattern === value)
14
+ return true;
15
+ if (!pattern.includes('*'))
16
+ return false;
17
+ const re = new RegExp(`^${pattern.split('*').map(escapeRegExp).join('.*')}$`);
18
+ return re.test(value);
19
+ }
20
+ function escapeRegExp(s) {
21
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
22
+ }
23
+ /** value 是否被 patterns 中任一 glob 命中。 */
24
+ export function matchAnyCap(patterns, value) {
25
+ for (const p of patterns)
26
+ if (capMatches(p, value))
27
+ return true;
28
+ return false;
29
+ }
30
+ /**
31
+ * 用户对某具体能力是否有效。优先级:deny > owner(*) > public > granted(restricted)。
32
+ * 注意 deny 高于 owner——owner 也可被显式 deny 某能力(如临时收回)。
33
+ */
34
+ export function hasCapability(res, cap) {
35
+ if (matchAnyCap(res.denies, cap))
36
+ return false;
37
+ if (res.isOwner)
38
+ return true;
39
+ return matchAnyCap(res.publicCaps, cap) || matchAnyCap(res.grants, cap);
40
+ }
41
+ /**
42
+ * 委托子集约束:授予方把 requested 能力委托给下层是否合法。
43
+ * owner 可委托一切;非 owner 只能委托「自己当前有效持有」的能力(防越权放大)。
44
+ * 返回越权(不可委托)的能力项;空数组 = 全部合法。
45
+ *
46
+ * 语义:具体能力按 hasCapability 判定;委托更宽的 glob(超出自己持有的)会被拒。
47
+ */
48
+ export function rejectedDelegations(granter, requested) {
49
+ if (granter.isOwner)
50
+ return [];
51
+ return requested.filter(cap => !hasCapability(granter, cap));
52
+ }
53
+ //# sourceMappingURL=capability-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-model.js","sourceRoot":"","sources":["../src/capability-model.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,sDAAsD;AACtD,EAAE;AACF,gDAAgD;AAChD,oEAAoE;AACpE,2DAA2D;AAC3D,0EAA0E;AAC1E,+CAA+C;AAC/C,oCAAoC;AACpC,+DAA+D;AAE/D,4DAA4D;AAC5D,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,KAAa;IACvD,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IACtD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACzC,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9E,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC7B,OAAO,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,WAAW,CAAC,QAA2B,EAAE,KAAa;IACpE,KAAK,MAAM,CAAC,IAAI,QAAQ;QAAE,IAAI,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;IAChE,OAAO,KAAK,CAAC;AACf,CAAC;AAgBD;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,GAAyB,EAAE,GAAW;IAClE,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,GAAG,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC7B,OAAO,WAAW,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAA6B,EAAE,SAA4B;IAC7F,IAAI,OAAO,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAC/B,OAAO,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;AAC/D,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,91 +1,6 @@
1
- import type { ConfigManager, Context, Logger, PluginModule } from '@aalis/core';
2
- import type { UserIdentity } from '@aalis/plugin-authority-api';
3
- import { type StorageService } from '@aalis/plugin-storage-api';
4
- import type { AuthorityService, AuthorityUserEntry, AuthorizeRequest, DangerousConfirmHandler, DangerousConfirmRequest, DangerousGrant, UserCapabilityOverrides } from './types.js';
5
- export type { AuthorityService, DangerousConfirmHandler, DangerousConfirmRequest, DangerousConfirmResult, DangerousGrant, DangerousGrantRequest, } from './types.js';
6
- export declare class AuthorityManager implements AuthorityService {
7
- private users;
8
- /** 反向绑定索引:被绑平台身份键 → 主账户键(从 users[].links 重建) */
9
- private linkIndex;
10
- /** 待消费绑定码(内存态) */
11
- private bindCodes;
12
- private config;
13
- private logger;
14
- private storage;
15
- private fileUri;
16
- private dirty;
17
- private saveChain;
18
- private confirmHandlers;
19
- private dangerousGrants;
20
- private grantSeq;
21
- /**
22
- * dangerous 策略的开启时间(运行时状态,不序列化到 config)。
23
- * 进程重启后重置为 null,对限时策略而言等同于「重启即失效」。
24
- */
25
- private dangerousEnabledAt;
26
- constructor(config: ConfigManager, logger: Logger, storage: StorageService);
27
- getAuthority(platform: string, userId?: string): number;
28
- setAuthority(platform: string, userId: string, level: number): void;
29
- removeUser(platform: string, userId: string): void;
30
- /** 从 users[].links 重建反向索引(表很小,全量重建即可) */
31
- private rebuildLinkIndex;
32
- createBindCode(platform: string, userId: string): {
33
- code: string;
34
- expiresAt: number;
35
- };
36
- consumeBindCode(code: string, identity: UserIdentity): UserIdentity;
37
- unlinkIdentity(platform: string, userId: string): boolean;
38
- setPassword(platform: string, userId: string, password: string): Promise<void>;
39
- verifyPassword(platform: string, userId: string, password: string): Promise<boolean>;
40
- hasPassword(platform: string, userId: string): boolean;
41
- setUserCapabilities(platform: string, userId: string, overrides: UserCapabilityOverrides): void;
42
- /**
43
- * capability 中心统一闸。裁决优先级(per-capability):
44
- * 全局 permissionPolicy > 用户 deny > 用户 grant > 角色链等级门槛。
45
- *
46
- * 等级门槛 = max(declaredAuthority, requiredAuthorityFor([cap]))——
47
- * 即"操作声明的基础等级"与"capability 归属角色包"取较高者,只升不降。
48
- */
49
- authorize(identity: {
50
- platform: string;
51
- userId?: string;
52
- }, request: AuthorizeRequest): string | null;
53
- isDangerousAllowed(name: string, permissions?: string[]): boolean;
54
- /** 刷新 dangerous 策略启动时间戳(运行时状态) */
55
- markDangerousEnabled(): void;
56
- /** 清除 dangerous 策略启动时间戳 */
57
- clearDangerousEnabled(): void;
58
- setConfirmHandler(platform: string, handler: DangerousConfirmHandler): void;
59
- confirmDangerous(request: DangerousConfirmRequest): Promise<boolean>;
60
- /**
61
- * 计算一组细粒度权限所要求的最低权限等级(参数级动态提权)。
62
- *
63
- * 例如 file_write 写普通文件只需声明的 authority:3,但写 data:/users.json
64
- * (用户权限表)或 data:/scheduler-jobs.json(计划任务,可注入 owner 身份的
65
- * actor)这类敏感文件、或写 aalis:/ 源码根(重启后即任意代码执行)时要求
66
- * owner 等级,防止低权限用户借文件写入自我提权。
67
- *
68
- * 默认保护清单可被 config.permissionAuthority 覆盖/扩展(同模式取配置值,
69
- * 新模式叠加;命中多个模式时取最大要求)。只提高门槛,不降低声明值。
70
- */
71
- /** 参数级提权完整清单(内置保护 + config.permissionAuthority 合并后;展示与裁决共用同一真源) */
72
- getEscalationMap(): Record<string, number>;
73
- requiredAuthorityFor(permissions: string[]): number;
74
- checkPermissionPolicy(permissions: string[]): string | null;
75
- private matchAny;
76
- private matchPattern;
77
- listDangerousGrants(): DangerousGrant[];
78
- revokeDangerousGrant(id: string): boolean;
79
- private normalizeConfirmResult;
80
- private consumeDangerousGrant;
81
- private createDangerousGrant;
82
- private pruneDangerousGrants;
83
- private samePermissions;
84
- isOwner(platform: string, userId?: string): boolean;
85
- listUsers(): AuthorityUserEntry[];
86
- save(): void;
87
- init(): Promise<void>;
88
- }
1
+ import type { Context, PluginModule } from '@aalis/core';
2
+ export type { AuthorityService } from '@aalis/plugin-authority-api';
3
+ export { AuthorityManager } from './authority-manager.js';
89
4
  export declare const name = "@aalis/plugin-authority";
90
5
  export declare const displayName = "\u6743\u9650\u7BA1\u7406";
91
6
  export declare const subsystem = "authority";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAgBrE,YAAY,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAI1D,eAAO,MAAM,IAAI,4BAA4B,CAAC;AAC9C,eAAO,MAAM,WAAW,6BAAS,CAAC;AAClC,eAAO,MAAM,SAAS,cAAc,CAAC;AACrC,eAAO,MAAM,QAAQ,UAAgB,CAAC;AACtC,eAAO,MAAM,MAAM;;CAElB,CAAC;AAoCF,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAwIzF;AAUD,eAAO,MAAM,OAAO,EAAE,YAAY,CAAC,SAAS,CAgV3C,CAAC;AAIF,eAAO,MAAM,WAAW,EAAE,YAAY,CAAC,aAAa,CAGnD,CAAC"}