@aiquants/auth-react-router 0.13.0 → 0.14.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 +73 -0
- package/dist/admin.d.mts +309 -11
- package/dist/admin.d.ts +309 -11
- package/dist/admin.js +1 -1
- package/dist/admin.js.map +1 -1
- package/dist/admin.mjs +1 -1
- package/dist/admin.mjs.map +1 -1
- package/dist/styles/auth-react-router.standalone.css +1 -1
- package/package.json +12 -3
- package/src/admin/app.ts +5 -0
- package/src/admin/format.ts +10 -1
- package/src/admin/labels.ts +289 -15
- package/src/admin/server.ts +549 -37
- package/src/admin/ui.tsx +17 -4
- package/src/admin/views.tsx +913 -94
package/dist/admin.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_router from 'react-router';
|
|
2
|
-
import { AuthUser, AuthGroup, AuthGroupMember, AuthAllowlistEntry, AuthDirectoryMembershipMode, AuthDirectoryStatus } from '@aiquants/auth-core';
|
|
2
|
+
import { AuthUser, AuthGroup, AuthGroupMember, AuthAllowlistEntry, AuthDirectoryMembershipMode, AuthDirectoryStatus, AuthDirectoryCatalogSnapshot, AuthDirectoryCatalogGroup } from '@aiquants/auth-core';
|
|
3
3
|
import React__default from 'react';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -48,6 +48,32 @@ type UserAdminLabels = {
|
|
|
48
48
|
};
|
|
49
49
|
/** アクションが拒否・失敗したときの文言。 */
|
|
50
50
|
errors: {
|
|
51
|
+
/** 一覧に無い上流キーを指定した。`{key}` に受け取った値。 */
|
|
52
|
+
unknownUpstream: string;
|
|
53
|
+
/** その上流グループは既に別のローカルグループへ連携している。`{key}` / `{group}`。 */
|
|
54
|
+
alreadyLinked: string;
|
|
55
|
+
/** ディレクトリ未設定の配備で連携を求められたときの説明。 */
|
|
56
|
+
directoryDisabled: string;
|
|
57
|
+
/** 必須欄が欠けている、または読めない値だったことの説明。 */
|
|
58
|
+
invalidField: string;
|
|
59
|
+
/**
|
|
60
|
+
* Shown for an intent this screen does not perform. この画面が行わない intent への文言。
|
|
61
|
+
*
|
|
62
|
+
* ⚠️ 受け取った値を含めない。認可より手前で返るため、認証を通っていない相手にも届く。
|
|
63
|
+
*/
|
|
64
|
+
unknownIntent: string;
|
|
65
|
+
/**
|
|
66
|
+
* Operator-facing names for the form fields. 欄の、操作者に見える名前。
|
|
67
|
+
*
|
|
68
|
+
* ⚠️ `invalidField` の `{field}` に **通信上のキー** を差し込まない。日本語の文の中に
|
|
69
|
+
* `membershipMode` のような識別子が現れ、画面のどの欄を指すのか操作者には判らない。
|
|
70
|
+
* 表に無い欄はキーのまま出す (出さないより、判りにくくても出すほうがよい)。
|
|
71
|
+
*/
|
|
72
|
+
fieldNames: Record<string, string>;
|
|
73
|
+
/** 許可リストの種別が既定の 2 値でなかったことの説明。 */
|
|
74
|
+
invalidAllowlistType: string;
|
|
75
|
+
/** 想定外の失敗 (原文はサーバーのログにだけ残す)。 */
|
|
76
|
+
unexpected: string;
|
|
51
77
|
/**
|
|
52
78
|
* Shown when the actor lacks permission for the attempted operation.
|
|
53
79
|
* 操作の権限が無いときに出す文言。
|
|
@@ -56,6 +82,13 @@ type UserAdminLabels = {
|
|
|
56
82
|
* 拒否理由といった内部の語彙が、権限を持たない相手にそのまま渡る。
|
|
57
83
|
*/
|
|
58
84
|
forbidden: string;
|
|
85
|
+
/**
|
|
86
|
+
* Shown when the request body exceeds the ceiling. 本文が上限を越えたときの文言。
|
|
87
|
+
*
|
|
88
|
+
* この画面が送るのは短い文字列だけなので、越えるのは誤操作か攻撃である。どちらにも
|
|
89
|
+
* 同じ文言を返す (どこで弾かれたかを細かく教えない)。
|
|
90
|
+
*/
|
|
91
|
+
requestTooLarge: string;
|
|
59
92
|
};
|
|
60
93
|
/** シェル (タブ枠) の見出し。 */
|
|
61
94
|
heading: string;
|
|
@@ -64,6 +97,8 @@ type UserAdminLabels = {
|
|
|
64
97
|
label: string;
|
|
65
98
|
canWrite: string;
|
|
66
99
|
canRead: string;
|
|
100
|
+
/** 削除だけを持つ主体の表示 (読み書きが無いことを「権限なし」と描かない)。 */
|
|
101
|
+
canDelete: string;
|
|
67
102
|
none: string;
|
|
68
103
|
/** 未結線・取得失敗・付与ゼロのいずれも「不明」であり、許可ではない。 */
|
|
69
104
|
unknown: string;
|
|
@@ -77,6 +112,8 @@ type UserAdminLabels = {
|
|
|
77
112
|
};
|
|
78
113
|
usersView: {
|
|
79
114
|
title: string;
|
|
115
|
+
/** 並べ替えの読み上げ名。`{column}` は列名。 */
|
|
116
|
+
sortBy: string;
|
|
80
117
|
searchPlaceholder: string;
|
|
81
118
|
/** 検索欄の読み上げ名。プレースホルダは入力すると消えるため名前にならない。 */
|
|
82
119
|
searchLabel: string;
|
|
@@ -93,12 +130,65 @@ type UserAdminLabels = {
|
|
|
93
130
|
activateAria: string;
|
|
94
131
|
deactivateAria: string;
|
|
95
132
|
/** 無効化はサインインを止める。確認を取る。 */
|
|
133
|
+
/** 検索で 0 件になったときの文言 (「登録が無い」と区別する)。 */
|
|
134
|
+
emptyFiltered: string;
|
|
135
|
+
/** 一覧の絞り込み結果を読み上げるための文言。 */
|
|
136
|
+
listSummary: string;
|
|
137
|
+
/** 昇順で並べ替え中の列の読み上げ名。 */
|
|
138
|
+
sortedAscending: string;
|
|
139
|
+
/** 降順で並べ替え中の列の読み上げ名。 */
|
|
140
|
+
sortedDescending: string;
|
|
96
141
|
confirmDeactivate: string;
|
|
97
142
|
empty: string;
|
|
98
143
|
};
|
|
99
144
|
groupsView: {
|
|
100
145
|
/** 検索語に一致しないときの説明。空状態と混ぜると「消えた」と誤読される。 */
|
|
101
146
|
emptyFiltered: string;
|
|
147
|
+
/** 作成方法の切替。ローカルに作るか、上流のグループから作るか。 */
|
|
148
|
+
/** 作成方法を選ぶ操作群の読み上げ名。 */
|
|
149
|
+
createModeLabel: string;
|
|
150
|
+
createModeLocal: string;
|
|
151
|
+
createModeUpstream: string;
|
|
152
|
+
/** 上流グループを選ぶ欄。 */
|
|
153
|
+
pickUpstream: string;
|
|
154
|
+
pickUpstreamPlaceholder: string;
|
|
155
|
+
/** 選択肢 1 件の副題。`{count}` はメンバー数。 */
|
|
156
|
+
upstreamOptionMembers: string;
|
|
157
|
+
/** すでに連携済みの選択肢に付ける表示。 */
|
|
158
|
+
upstreamAlreadyLinked: string;
|
|
159
|
+
/** 候補一覧が引けなかったときの説明。`{reason}` に理由。 */
|
|
160
|
+
/** 候補は引けたが、この配備の連携プロバイダ名が決まっていないことの説明。 */
|
|
161
|
+
providerUnset: string;
|
|
162
|
+
/** 候補を選ぶまで作成できないことの説明 (押せないボタンの理由)。 */
|
|
163
|
+
pickUpstreamFirst: string;
|
|
164
|
+
/**
|
|
165
|
+
* Shown when every upstream group is already linked. 上流のすべてが連携済みのときの文言。
|
|
166
|
+
*
|
|
167
|
+
* ⚠️ この場面で「先に選べ」と言ってはならない。従いようのない指示になる。
|
|
168
|
+
*/
|
|
169
|
+
allUpstreamLinked: string;
|
|
170
|
+
/** 上流を読めたが 1 件も無かったことの説明。 */
|
|
171
|
+
catalogEmpty: string;
|
|
172
|
+
catalogUnavailable: string;
|
|
173
|
+
/** 上流へ届かないときの案内 (作成対話向け — この対話にアドレス欄は無い)。 */
|
|
174
|
+
catalogUnavailableHere: string;
|
|
175
|
+
/** 候補一覧をいつ観測したか。 */
|
|
176
|
+
catalogObservedAt: string;
|
|
177
|
+
/** 観測が配備の許す鮮度を越えている旨。 */
|
|
178
|
+
catalogStale: string;
|
|
179
|
+
/** 候補一覧を引けなかった理由の文言 (上流の例外文は使わない)。 */
|
|
180
|
+
catalogFailures: {
|
|
181
|
+
denied: string;
|
|
182
|
+
rateLimited: string;
|
|
183
|
+
upstreamError: string;
|
|
184
|
+
neverObserved: string;
|
|
185
|
+
unknown: string;
|
|
186
|
+
};
|
|
187
|
+
/** 上流から作る場合の説明 (何が起きるかを先に伝える)。 */
|
|
188
|
+
createUpstreamNotice: string;
|
|
189
|
+
/** グループのメンバー面へ移動する操作。 */
|
|
190
|
+
openMembers: string;
|
|
191
|
+
openMembersAria: string;
|
|
102
192
|
title: string;
|
|
103
193
|
searchPlaceholder: string;
|
|
104
194
|
searchLabel: string;
|
|
@@ -110,6 +200,8 @@ type UserAdminLabels = {
|
|
|
110
200
|
/** 所属人数。`{count}` を人数へ置換する。 */
|
|
111
201
|
memberCountTemplate: string;
|
|
112
202
|
confirmDelete: string;
|
|
203
|
+
/** 連携付きで作る前の確認。`{group}` / `{upstream}`。委譲は元に戻しづらい。 */
|
|
204
|
+
confirmCreateLinked: string;
|
|
113
205
|
/** 行ごとの読み上げ名。`{group}` をグループ名へ置換する。 */
|
|
114
206
|
editGroupAria: string;
|
|
115
207
|
deleteGroupAria: string;
|
|
@@ -120,8 +212,25 @@ type UserAdminLabels = {
|
|
|
120
212
|
};
|
|
121
213
|
groupMembersView: {
|
|
122
214
|
title: string;
|
|
215
|
+
/** 利用者の絞り込み。数百人の一覧を目で追わせない。 */
|
|
216
|
+
searchLabel: string;
|
|
217
|
+
searchPlaceholder: string;
|
|
218
|
+
/** 所属している人だけに絞る切替。`{count}` は該当数。 */
|
|
219
|
+
onlyMembers: string;
|
|
220
|
+
/** 絞り込み結果が空のときの説明。 */
|
|
221
|
+
emptyFiltered: string;
|
|
222
|
+
/** 一覧の要約。`{shown}` / `{total}` / `{members}`。 */
|
|
223
|
+
summary: string;
|
|
123
224
|
selectGroup: string;
|
|
124
225
|
selectPrompt: string;
|
|
226
|
+
/** グループが 1 つも無い配備での説明 (「選べ」は従えない指示になる)。 */
|
|
227
|
+
noGroups: string;
|
|
228
|
+
/** 所属だけに絞った結果 0 件になったときの説明。 */
|
|
229
|
+
emptyNoMembers: string;
|
|
230
|
+
/** 利用者が 1 人も登録されていない配備での説明。 */
|
|
231
|
+
noUsers: string;
|
|
232
|
+
/** 深いリンクが指すグループが見つからず、代替を出していることの説明。 */
|
|
233
|
+
deepLinkMissed: string;
|
|
125
234
|
actionAdd: string;
|
|
126
235
|
actionRemove: string;
|
|
127
236
|
/** 行ごとの読み上げ名。`{user}` を利用者名へ置換する。 */
|
|
@@ -169,6 +278,8 @@ type UserAdminLabels = {
|
|
|
169
278
|
syncEnabled: string;
|
|
170
279
|
syncNow: string;
|
|
171
280
|
syncQueued: string;
|
|
281
|
+
/** 同じ範囲の要求が既に待っていて、積まれなかったことの説明。 */
|
|
282
|
+
syncAlreadyPending: string;
|
|
172
283
|
/** 同期が滞っていることの警告。停止はセキュリティ事象である。 */
|
|
173
284
|
staleWarning: string;
|
|
174
285
|
disabledWarning: string;
|
|
@@ -186,6 +297,8 @@ type UserAdminLabels = {
|
|
|
186
297
|
pendingTemplate: string;
|
|
187
298
|
/** 連携先が 1 つも残っていないときの説明。 */
|
|
188
299
|
nothingToLink: string;
|
|
300
|
+
/** グループが 1 つも無い配備での説明 (「全部が連携済み」と区別する)。 */
|
|
301
|
+
noGroupsToLink: string;
|
|
189
302
|
/** 未結線の配備で操作を出さない理由。 */
|
|
190
303
|
notWiredNotice: string;
|
|
191
304
|
/** 行ごとの読み上げ名。`{group}` をグループ名へ置換する。 */
|
|
@@ -204,9 +317,21 @@ type UserAdminLabels = {
|
|
|
204
317
|
empty: string;
|
|
205
318
|
/** 連携するグループを選ぶ欄。 */
|
|
206
319
|
selectGroup: string;
|
|
320
|
+
/** 選択欄が自前で持つ文言。渡さないと英語のまま出る。 */
|
|
321
|
+
/** 選択欄の入力の手引き。 */
|
|
322
|
+
pickUpstreamPlaceholder: string;
|
|
323
|
+
pickerNoOptions: string;
|
|
324
|
+
pickerClear: string;
|
|
325
|
+
pickerToggle: string;
|
|
326
|
+
/** 選択中の値の読み上げ。`{value}`。 */
|
|
327
|
+
pickerSelected: string;
|
|
328
|
+
/** 候補件数の読み上げ。`{count}`。 */
|
|
329
|
+
pickerAvailable: string;
|
|
207
330
|
/** 上流グループのアドレス入力。 */
|
|
208
331
|
externalKeyPlaceholder: string;
|
|
209
332
|
/** 連携解除の確認。台帳と許可設定が消える。 */
|
|
333
|
+
/** 連携を作る前の確認 (元へ戻すには連携解除という別の操作が要る)。 */
|
|
334
|
+
confirmLink: string;
|
|
210
335
|
confirmUnlink: string;
|
|
211
336
|
/** 同期の一時停止・再開。 */
|
|
212
337
|
pause: string;
|
|
@@ -303,21 +428,43 @@ type UserAdminStore = {
|
|
|
303
428
|
*/
|
|
304
429
|
linkDirectoryGroup: (groupId: number, data: {
|
|
305
430
|
provider: string;
|
|
431
|
+
externalId: string;
|
|
306
432
|
externalKey: string;
|
|
307
433
|
membershipMode: AuthDirectoryMembershipMode;
|
|
308
434
|
}) => Promise<void>;
|
|
435
|
+
/**
|
|
436
|
+
* Creates a local group and links it to an upstream group as one indivisible step.
|
|
437
|
+
* ローカルグループの作成と上流への連携を、分割不可能な 1 手として行う処理。
|
|
438
|
+
*
|
|
439
|
+
* ⚠️ **途中で失敗したら何も残してはならない。** 作成だけが成功すると、運用者には「連携に
|
|
440
|
+
* 失敗した」ではなく「知らないグループが増えた」と見える。実装は 1 つのトランザクションで
|
|
441
|
+
* 行うこと (作成 → 連携の順に別々の書込を並べると、この不可分性は成立しない)。
|
|
442
|
+
*/
|
|
443
|
+
createLinkedGroup: (data: {
|
|
444
|
+
groupKey: string;
|
|
445
|
+
name: string;
|
|
446
|
+
description?: string;
|
|
447
|
+
provider: string;
|
|
448
|
+
externalId: string;
|
|
449
|
+
externalKey: string;
|
|
450
|
+
membershipMode: AuthDirectoryMembershipMode;
|
|
451
|
+
}) => Promise<AuthGroup>;
|
|
309
452
|
/** Stops following the upstream, keeping the memberships already projected. 連携の解除。 */
|
|
310
453
|
unlinkDirectoryGroup: (groupId: number) => Promise<void>;
|
|
311
454
|
/** Pauses or resumes synchronization for one group. 1 グループの同期を停止・再開する処理。 */
|
|
312
455
|
setDirectorySyncEnabled: (groupId: number, isSyncEnabled: boolean) => Promise<void>;
|
|
313
456
|
/**
|
|
314
|
-
* Queues a
|
|
457
|
+
* Queues a "sync now" request. 「今すぐ同期」の要求を積む処理。
|
|
315
458
|
*
|
|
316
|
-
*
|
|
459
|
+
* ⚠️ 戻り値を `void` にしてはならない。同じ範囲の要求が既に待っているとき、積み増さないのは
|
|
460
|
+
* 正しい (押した数だけ上流への全件走査が並ぶ) が、それを成功と区別せずに返すと、押しても
|
|
461
|
+
* 反応しない画面ができる — しかも詰まった 1 行が以後の押下すべてを飲み込む。
|
|
317
462
|
*
|
|
318
|
-
* @param groupId `null`
|
|
463
|
+
* @param groupId Target group, or `null` for the whole tenant. 対象グループ (`null` でテナント全件)。
|
|
464
|
+
* @param actor Who asked, for the audit record. 要求した主体 (監査記録用)。
|
|
465
|
+
* @returns Whether it was queued or already waiting. 積んだか、既に待っていたか。
|
|
319
466
|
*/
|
|
320
|
-
requestDirectorySync: (groupId: number | null) => Promise<
|
|
467
|
+
requestDirectorySync: (groupId: number | null, actor: string) => Promise<UserAdminSyncRequestOutcome>;
|
|
321
468
|
/** Health of the synchronization, for the header warning. 同期の健全性 (警告表示用)。 */
|
|
322
469
|
getDirectoryStatus: () => Promise<AuthDirectoryStatus>;
|
|
323
470
|
};
|
|
@@ -332,10 +479,44 @@ declare function createInMemoryUserAdminStore(initial?: {
|
|
|
332
479
|
allowlist?: AuthAllowlistEntry[];
|
|
333
480
|
}): UserAdminStore;
|
|
334
481
|
/**
|
|
335
|
-
*
|
|
336
|
-
*
|
|
337
|
-
*
|
|
482
|
+
* Normalizes an upstream key for comparison. 上流キーを比較用に正規化する処理。
|
|
483
|
+
*
|
|
484
|
+
* 前後の空白と大文字小文字を同一視する。**画面と実装で正規化がずれると**、選択欄は「未連携」と
|
|
485
|
+
* 見なすキーをサーバーが「連携済み」と見なす、といった食い違いが生まれる。1 か所に置く。
|
|
486
|
+
*
|
|
487
|
+
* @param key Raw upstream key. 生の上流キー。
|
|
488
|
+
* @returns The comparable form. 比較可能な形。
|
|
338
489
|
*/
|
|
490
|
+
declare function normalizeUpstreamKey(key: string): string;
|
|
491
|
+
/**
|
|
492
|
+
* An error whose own text is meant for the operator to read.
|
|
493
|
+
* 文面を **運用者に読ませるつもりで** 投げるエラー。
|
|
494
|
+
*
|
|
495
|
+
* ⚠️ ストアの例外文をそのまま画面へ返してはならない。ドライバの例外はスキーマ名・表名・制約名・
|
|
496
|
+
* 衝突した値・接続先をそのまま含み、それが閲覧権限しか持たない主体の画面に出る。一方で
|
|
497
|
+
* 「最後の管理者は外せません」のような業務上の拒否理由は、読めなければ操作そのものが行き詰まる。
|
|
498
|
+
* 両者は文面からは区別できないので、**投げる側が宣言する**。宣言の無い例外は一般的な文言になる。
|
|
499
|
+
*
|
|
500
|
+
* ホストのストアは、この class を継承しても `operatorFacing: true` を持たせてもよい
|
|
501
|
+
* (別パッケージのエラー型を継承できない事情に配慮した二経路である)。
|
|
502
|
+
*/
|
|
503
|
+
declare class UserAdminOperatorError extends Error {
|
|
504
|
+
/** 運用者向けであることの印。継承できない場合はこの属性だけでもよい。 */
|
|
505
|
+
readonly operatorFacing = true;
|
|
506
|
+
constructor(message: string);
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* An input problem the operator can fix, carrying a label key instead of a sentence.
|
|
510
|
+
* 運用者が直せる入力の問題。文ではなく **ラベルのキー** を運ぶ。
|
|
511
|
+
*
|
|
512
|
+
* ⚠️ メッセージを実装側で組むと、既定 (英語) の配備に日本語が出る。文言はラベルに集約し、
|
|
513
|
+
* ここでは「どの文言か」と差し替え値だけを運ぶ。
|
|
514
|
+
*/
|
|
515
|
+
declare class UserAdminInputError extends Error {
|
|
516
|
+
readonly labelKey: keyof UserAdminLabels["errors"];
|
|
517
|
+
readonly values: Record<string, string | number>;
|
|
518
|
+
constructor(labelKey: keyof UserAdminLabels["errors"], values?: Record<string, string | number>);
|
|
519
|
+
}
|
|
339
520
|
/**
|
|
340
521
|
* The only route-args field this module reads. React Router's full `LoaderFunctionArgs` satisfies it, so
|
|
341
522
|
* route wiring is unchanged — but declaring the minimum keeps callers (and tests) from fabricating fields
|
|
@@ -345,6 +526,11 @@ declare function createInMemoryUserAdminStore(initial?: {
|
|
|
345
526
|
type RouteArgs = {
|
|
346
527
|
request: Request;
|
|
347
528
|
};
|
|
529
|
+
/**
|
|
530
|
+
* The CRUD verb an operation performs. Deliberately a plain string union so this package stays
|
|
531
|
+
* independent of any particular authorization library.
|
|
532
|
+
* 操作が行う CRUD 種別。特定の認可ライブラリに依存しないよう素の文字列 union で表現する。
|
|
533
|
+
*/
|
|
348
534
|
type UserAdminAccess = "read" | "create" | "update" | "delete";
|
|
349
535
|
/**
|
|
350
536
|
* Access guard the user-admin surface is mounted behind. Deny by throwing
|
|
@@ -377,6 +563,83 @@ type UserAdminGuards = {
|
|
|
377
563
|
error: unknown;
|
|
378
564
|
}) => void;
|
|
379
565
|
};
|
|
566
|
+
/**
|
|
567
|
+
* Every intent the permission table knows. 権限表が知っている intent すべて。
|
|
568
|
+
*
|
|
569
|
+
* ⚠️ 消費側の網羅性検査のために公開する。検査側が intent を手書きで並べる形しか無いと、
|
|
570
|
+
* 実装に intent が増えても表は勝手には伸びず、**最も権限の重い新しい intent** だけが
|
|
571
|
+
* 無検査で通る状態が静かに生まれる。突き合わせる相手を実装側から提供する。
|
|
572
|
+
*
|
|
573
|
+
* @returns Intent names, in declaration order. 宣言順の intent 名。
|
|
574
|
+
*/
|
|
575
|
+
declare function userAdminIntents(): string[];
|
|
576
|
+
/**
|
|
577
|
+
* The CRUD verbs one intent requires. 1 つの intent が要求する CRUD 種別。
|
|
578
|
+
*
|
|
579
|
+
* ⚠️ 消費側が権限表を検査できるようにするために公開する。表そのものは公開しない — 書き換え
|
|
580
|
+
* 可能な参照を渡すと、検査の対象が実行時に差し替えられる形になる。
|
|
581
|
+
*
|
|
582
|
+
* @param intent - Intent name. intent 名。
|
|
583
|
+
* @returns The required verbs, or an empty list for an unknown intent. 要求する種別 (未知なら空)。
|
|
584
|
+
*/
|
|
585
|
+
declare function userAdminAccessFor(intent: string): readonly UserAdminAccess[];
|
|
586
|
+
/**
|
|
587
|
+
* One upstream group as the picker shows it. 選択欄に出す上流グループ 1 件。
|
|
588
|
+
*
|
|
589
|
+
* ⚠️ **別名ではなく `@aiquants/auth-core` の型そのものである。** この形は上流アダプタ・永続化層・
|
|
590
|
+
* 管理 UI の 3 層を通る。層ごとに「同じ意味の別の型」を宣言すると、構造的部分型のせいでどの境界も
|
|
591
|
+
* 通ってしまい、上流へ足した欄が途中で黙って捨てられる (実測: 別々に宣言していた間は、必須欄を
|
|
592
|
+
* 足しても読み手側の境界で `tsc --strict` が 0 を返した)。欄の集合は `auth-core` の型テストが固定
|
|
593
|
+
* しているので、足すときは 3 層すべての受け渡しを見直すことになる。
|
|
594
|
+
*
|
|
595
|
+
* 特定のディレクトリ実装 (Google 等) の型は依然として import しない — `auth-core` は上流に依存
|
|
596
|
+
* しない語彙のパッケージであり、`AuthDirectoryStatus` などを既にここから受け取っている。
|
|
597
|
+
*/
|
|
598
|
+
type UserAdminCatalogGroup = AuthDirectoryCatalogGroup;
|
|
599
|
+
/**
|
|
600
|
+
* The upstream catalog as the loader hands it to the views. loader がビューへ渡す上流の候補一覧。
|
|
601
|
+
*
|
|
602
|
+
* ⚠️ **これは利便性のための読み取りである。** 上流へ届かなくても画面は開かなければならない
|
|
603
|
+
* (グループ一覧や許可リストの閲覧は、選択欄の可否とは無関係である)。したがって失敗は
|
|
604
|
+
* `reason` として **描画可能な状態** に変換し、例外にしない。認可やサインイン判定のように
|
|
605
|
+
* 「判らないなら拒否」であるべき経路とは、意図的に扱いを変えている。
|
|
606
|
+
*/
|
|
607
|
+
type UserAdminCatalog = {
|
|
608
|
+
kind: "ready";
|
|
609
|
+
groups: UserAdminCatalogGroup[];
|
|
610
|
+
observedAt: string;
|
|
611
|
+
isStale: boolean;
|
|
612
|
+
} | {
|
|
613
|
+
kind: "unavailable";
|
|
614
|
+
reason: UserAdminCatalogFailure;
|
|
615
|
+
} | {
|
|
616
|
+
kind: "not-wired";
|
|
617
|
+
};
|
|
618
|
+
/**
|
|
619
|
+
* What the catalog port answers: the groups, and when the upstream was actually observed.
|
|
620
|
+
* 候補一覧ポートの答え。グループと、上流を実際に観測した時刻。
|
|
621
|
+
*
|
|
622
|
+
* ⚠️ `observedAt` は省略できない。この一覧は上流を直に叩いた結果とは限らず、資格情報を持つ別の
|
|
623
|
+
* プロセスが書いた写しであることが多い。時刻を伴わない一覧は「上流の現在」と区別できず、運用者は
|
|
624
|
+
* 既に消えたグループを選ぶ。`null` は **一度も観測していない** ことを意味する (空の答えではない)。
|
|
625
|
+
*/
|
|
626
|
+
type UserAdminCatalogSnapshot = AuthDirectoryCatalogSnapshot;
|
|
627
|
+
/**
|
|
628
|
+
* What a "sync now" request did. 「今すぐ同期」の要求が行ったこと。
|
|
629
|
+
*
|
|
630
|
+
* `already-pending` は失敗ではない — 同じ範囲の要求が既に待っている。ただし **成功でもない**:
|
|
631
|
+
* 何も積まれていないので、待っている行が誰にも拾われなければ何も起きない。
|
|
632
|
+
*/
|
|
633
|
+
type UserAdminSyncRequestOutcome = "queued" | "already-pending";
|
|
634
|
+
/**
|
|
635
|
+
* Why the upstream catalog could not be listed, classified for display.
|
|
636
|
+
* 上流の候補一覧を引けなかった理由を、表示のために分類したもの。
|
|
637
|
+
*
|
|
638
|
+
* ⚠️ **上流の例外文をそのまま画面へ出してはならない。** サービスアカウントのアドレス、借用先、
|
|
639
|
+
* 内部 URL、資格情報の断片が混じり得る。管理面を開けるだけの主体に、それらを読ませる理由は無い。
|
|
640
|
+
* 原文は `console.error` へ出し、画面にはこの分類に対応する自前の文言を出す。
|
|
641
|
+
*/
|
|
642
|
+
type UserAdminCatalogFailure = "denied" | "rateLimited" | "upstreamError" | "neverObserved" | "unknown";
|
|
380
643
|
/**
|
|
381
644
|
* Neutral per-resource permission summary the admin shell renders in its header badge.
|
|
382
645
|
* 管理シェルのヘッダーバッジが描画する、リソース単位の中立な権限サマリ。
|
|
@@ -399,6 +662,26 @@ type UserAdminAppConfig = {
|
|
|
399
662
|
* 必須。省略を許すとユーザー名簿と全更新操作が無防備に露出するため、型で強制する。
|
|
400
663
|
*/
|
|
401
664
|
guards: UserAdminGuards;
|
|
665
|
+
/**
|
|
666
|
+
* Names who is acting, for audit columns. 監査列に残す「誰が」を解決する処理。
|
|
667
|
+
*
|
|
668
|
+
* ⚠️ 省略すると、要求を積んだ主体が記録されない。同期要求の表は「誰がいつ何を要求し、結果が
|
|
669
|
+
* どうだったか」を残すために在り、その `requested_by` が定数だと、乱発を疑ったときに誰の
|
|
670
|
+
* ものか判らない — 乱発こそがこの intent に `update` を要求した理由である。
|
|
671
|
+
*/
|
|
672
|
+
resolveActor?: (request: Request) => Promise<string> | string;
|
|
673
|
+
/**
|
|
674
|
+
* Lists the upstream groups the operator may link to. 連携先の候補を列挙するポート。
|
|
675
|
+
*
|
|
676
|
+
* 任意である。注入しない配備では選択欄を出さず、上流キーの手入力に留まる — 上流へ問い合わせる
|
|
677
|
+
* 資格情報を web 側へ置かない構成を選べるようにするためである (同期ジョブだけが鍵を持つ形)。
|
|
678
|
+
*
|
|
679
|
+
* ⚠️ **失敗しても画面を落としてはならない。** 例外は loader が捕まえて
|
|
680
|
+
* `{ kind: "unavailable" }` へ写す。ここが落ちると、グループ一覧すら開けなくなる。
|
|
681
|
+
*/
|
|
682
|
+
directoryCatalog?: {
|
|
683
|
+
listGroups: (request: Request) => Promise<UserAdminCatalogSnapshot>;
|
|
684
|
+
};
|
|
402
685
|
/**
|
|
403
686
|
* Per-request self-permission lookup for the header annotation. Resolving to a map of
|
|
404
687
|
* {@link UserAdminPermission} shows the badge; rejecting shows an explicit "unknown" badge — never a
|
|
@@ -424,13 +707,14 @@ type UserAdminAppConfig = {
|
|
|
424
707
|
declare function createUserAdminApp(config: UserAdminAppConfig): {
|
|
425
708
|
loader: ({ request }: RouteArgs) => Promise<{
|
|
426
709
|
resourceLabels: Record<string, string> | undefined;
|
|
427
|
-
segment:
|
|
710
|
+
segment: "users" | "groups" | "allowlist" | "directory" | "group_members";
|
|
428
711
|
users: AuthUser[];
|
|
429
712
|
groups: AuthGroup[];
|
|
430
713
|
groupMembers: AuthGroupMember[];
|
|
431
714
|
allowlist: AuthAllowlistEntry[];
|
|
432
715
|
directoryStatus: AuthDirectoryStatus;
|
|
433
716
|
myPermissions: Record<string, UserAdminPermission | undefined> | null;
|
|
717
|
+
catalog: UserAdminCatalog;
|
|
434
718
|
labels: UserAdminLabels;
|
|
435
719
|
}>;
|
|
436
720
|
action: ({ request }: RouteArgs) => Promise<react_router.UNSAFE_DataWithResponseInit<{
|
|
@@ -438,7 +722,10 @@ declare function createUserAdminApp(config: UserAdminAppConfig): {
|
|
|
438
722
|
error: string;
|
|
439
723
|
}> | {
|
|
440
724
|
ok: boolean;
|
|
441
|
-
|
|
725
|
+
syncRequest?: undefined;
|
|
726
|
+
} | {
|
|
727
|
+
ok: boolean;
|
|
728
|
+
syncRequest: UserAdminSyncRequestOutcome;
|
|
442
729
|
} | {
|
|
443
730
|
ok: boolean;
|
|
444
731
|
error: string;
|
|
@@ -458,6 +745,15 @@ type UserAdminShellProps = {
|
|
|
458
745
|
*/
|
|
459
746
|
declare function UserAdminShell({ children, renderHeader }: UserAdminShellProps): React__default.JSX.Element;
|
|
460
747
|
|
|
748
|
+
/**
|
|
749
|
+
* @module admin/views
|
|
750
|
+
* @description The five tab views of the user administration screen.
|
|
751
|
+
* ユーザー管理画面を構成する 5 つのタブビュー。
|
|
752
|
+
*
|
|
753
|
+
* 一覧・検索・所属・許可リスト・ディレクトリ連携を描く。データはすべて loader から渡され、
|
|
754
|
+
* 書き込みはビュー唯一の fetcher (`useSubmitThen`) を通す。
|
|
755
|
+
*/
|
|
756
|
+
|
|
461
757
|
type UserAdminLoaderData = {
|
|
462
758
|
segment: string;
|
|
463
759
|
users: AuthUser[];
|
|
@@ -465,6 +761,8 @@ type UserAdminLoaderData = {
|
|
|
465
761
|
groupMembers: AuthGroupMember[];
|
|
466
762
|
allowlist: AuthAllowlistEntry[];
|
|
467
763
|
directoryStatus: AuthDirectoryStatus;
|
|
764
|
+
/** 上流の候補一覧。選択欄を出す面でのみ `ready` になる。 */
|
|
765
|
+
catalog: UserAdminCatalog;
|
|
468
766
|
labels?: UserAdminLabels;
|
|
469
767
|
};
|
|
470
768
|
declare function UsersView(): React__default.JSX.Element;
|
|
@@ -499,4 +797,4 @@ type AuthUserAdminAppViewProps = UserAdminShellProps;
|
|
|
499
797
|
*/
|
|
500
798
|
declare function AuthUserAdminAppView({ renderHeader }?: AuthUserAdminAppViewProps): React__default.JSX.Element;
|
|
501
799
|
|
|
502
|
-
export { AllowlistView, AuthUserAdminAppView, type AuthUserAdminAppViewProps, DirectoryView, GroupMembersView, GroupsView, type PartialUserAdminLabels, type UserAdminAccess, type UserAdminAppConfig, type UserAdminGuards, type UserAdminLabels, type UserAdminLoaderData, type UserAdminPermission, UserAdminShell, type UserAdminShellProps, type UserAdminStore, UsersView, createInMemoryUserAdminStore, createUserAdminApp, defaultUserAdminLabels, jaUserAdminLabels, resolveUserAdminLabels };
|
|
800
|
+
export { AllowlistView, AuthUserAdminAppView, type AuthUserAdminAppViewProps, DirectoryView, GroupMembersView, GroupsView, type PartialUserAdminLabels, type UserAdminAccess, type UserAdminAppConfig, type UserAdminCatalog, type UserAdminCatalogFailure, type UserAdminCatalogGroup, type UserAdminCatalogSnapshot, type UserAdminGuards, UserAdminInputError, type UserAdminLabels, type UserAdminLoaderData, UserAdminOperatorError, type UserAdminPermission, UserAdminShell, type UserAdminShellProps, type UserAdminStore, type UserAdminSyncRequestOutcome, UsersView, createInMemoryUserAdminStore, createUserAdminApp, defaultUserAdminLabels, jaUserAdminLabels, normalizeUpstreamKey, resolveUserAdminLabels, userAdminAccessFor, userAdminIntents };
|