tale-js-sdk 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/acl/index.d.ts +170 -0
- package/dist/acl/index.js +747 -0
- package/dist/acl/types.d.ts +208 -0
- package/dist/acl/types.js +1 -0
- package/dist/auth/index.d.ts +2 -134
- package/dist/auth/index.js +120 -96
- package/dist/auth/types.d.ts +122 -0
- package/dist/auth/types.js +1 -0
- package/dist/common/types.d.ts +82 -0
- package/dist/common/types.js +2 -0
- package/dist/errors.js +18 -18
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/rbac/acl.d.ts +152 -0
- package/dist/rbac/acl.js +723 -0
- package/dist/rbac/index.d.ts +2 -0
- package/dist/rbac/index.js +2 -0
- package/dist/rbac/rbac.d.ts +198 -0
- package/dist/rbac/rbac.js +984 -0
- package/dist/rbac/types.d.ts +356 -0
- package/dist/rbac/types.js +1 -0
- package/dist/rbac/user-group.d.ts +122 -0
- package/dist/rbac/user-group.js +570 -0
- package/dist/status.js +3 -3
- package/dist/token.d.ts +1 -1
- package/dist/token.js +5 -4
- package/dist/user/index.d.ts +165 -142
- package/dist/user/index.js +511 -59
- package/dist/user/types.d.ts +149 -0
- package/dist/user/types.js +1 -0
- package/dist/user-group/index.d.ts +230 -0
- package/dist/user-group/index.js +560 -0
- package/dist/user-group/types.d.ts +64 -0
- package/dist/user-group/types.js +1 -0
- package/package.json +4 -3
- package/dist/auth.d.ts +0 -271
- package/dist/auth.js +0 -461
- package/dist/client.d.ts +0 -20
- package/dist/client.js +0 -62
- package/dist/info.d.ts +0 -9
- package/dist/info.js +0 -18
- package/dist/package.json +0 -36
- package/dist/src/index.d.ts +0 -1
- package/dist/src/index.js +0 -1
- package/dist/src/info.d.ts +0 -6
- package/dist/src/info.js +0 -4
- package/dist/user.d.ts +0 -242
- package/dist/user.js +0 -331
|
@@ -0,0 +1,984 @@
|
|
|
1
|
+
import { getAppToken } from '../token.js';
|
|
2
|
+
import { ApiError, ConfigurationError, NetworkError } from '../errors.js';
|
|
3
|
+
// ===== 角色管理 =====
|
|
4
|
+
/**
|
|
5
|
+
* Creates a new role in the Tale application.
|
|
6
|
+
*
|
|
7
|
+
* @param roleData - Role data to create the new role
|
|
8
|
+
* @param options - Optional configuration for the request
|
|
9
|
+
* @returns Promise resolving to the created role information
|
|
10
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
11
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
12
|
+
* @throws {NetworkError} When network request fails
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { createRole } from '@tale/client';
|
|
17
|
+
*
|
|
18
|
+
* try {
|
|
19
|
+
* const result = await createRole({
|
|
20
|
+
* role_name: 'Admin',
|
|
21
|
+
* role_type: 'system',
|
|
22
|
+
* privilege_ids: ['privilege1', 'privilege2'],
|
|
23
|
+
* remark: 'System administrator role'
|
|
24
|
+
* });
|
|
25
|
+
* console.log('Role created:', result.role.role_id);
|
|
26
|
+
* } catch (error) {
|
|
27
|
+
* console.error('Failed to create role:', error.message);
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export async function createRole(roleData, options) {
|
|
32
|
+
// Validate required fields
|
|
33
|
+
if (!roleData.role_name || roleData.role_name.trim() === '') {
|
|
34
|
+
throw new ApiError('role_name is required for role creation', 400, '9400');
|
|
35
|
+
}
|
|
36
|
+
// Use provided app token or get one from token service
|
|
37
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
38
|
+
// Determine base URL
|
|
39
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
40
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
41
|
+
if (!base) {
|
|
42
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
43
|
+
}
|
|
44
|
+
const url = String(base).replace(/\/+$/, '') + '/rbac/v1/roles';
|
|
45
|
+
let response;
|
|
46
|
+
try {
|
|
47
|
+
response = await globalThis.fetch(url, {
|
|
48
|
+
method: 'POST',
|
|
49
|
+
headers: {
|
|
50
|
+
'Content-Type': 'application/json',
|
|
51
|
+
'x-t-token': token,
|
|
52
|
+
},
|
|
53
|
+
body: JSON.stringify(roleData),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
throw new NetworkError(`Failed to create role: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
58
|
+
}
|
|
59
|
+
let json;
|
|
60
|
+
try {
|
|
61
|
+
const responseJson = await response.json();
|
|
62
|
+
json = responseJson;
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
throw new ApiError(`Failed to parse role creation response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
66
|
+
}
|
|
67
|
+
// Handle API errors
|
|
68
|
+
if (json.code !== 200) {
|
|
69
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'Role creation failed';
|
|
70
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
71
|
+
}
|
|
72
|
+
// Validate response structure
|
|
73
|
+
if (!json.data || !json.data.role) {
|
|
74
|
+
throw new ApiError('Invalid role creation response: missing role data', response.status);
|
|
75
|
+
}
|
|
76
|
+
return json.data;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Updates an existing role by ID.
|
|
80
|
+
*
|
|
81
|
+
* @param roleId - Role ID to update
|
|
82
|
+
* @param updateData - Role information to update
|
|
83
|
+
* @param options - Optional configuration for the request
|
|
84
|
+
* @returns Promise resolving to the updated role information
|
|
85
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
86
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
87
|
+
* @throws {NetworkError} When network request fails
|
|
88
|
+
*/
|
|
89
|
+
export async function updateRole(roleId, updateData, options) {
|
|
90
|
+
// Validate required fields
|
|
91
|
+
if (!roleId || roleId.trim() === '') {
|
|
92
|
+
throw new ApiError('role_id is required for role update', 400, '9400');
|
|
93
|
+
}
|
|
94
|
+
// Use provided app token or get one from token service
|
|
95
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
96
|
+
// Determine base URL
|
|
97
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
98
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
99
|
+
if (!base) {
|
|
100
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
101
|
+
}
|
|
102
|
+
const url = String(base).replace(/\/+$/, '') + `/rbac/v1/roles/${encodeURIComponent(roleId)}`;
|
|
103
|
+
let response;
|
|
104
|
+
try {
|
|
105
|
+
response = await globalThis.fetch(url, {
|
|
106
|
+
method: 'PUT',
|
|
107
|
+
headers: {
|
|
108
|
+
'Content-Type': 'application/json',
|
|
109
|
+
'x-t-token': token,
|
|
110
|
+
},
|
|
111
|
+
body: JSON.stringify(updateData),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
throw new NetworkError(`Failed to update role: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
116
|
+
}
|
|
117
|
+
let json;
|
|
118
|
+
try {
|
|
119
|
+
const responseJson = await response.json();
|
|
120
|
+
json = responseJson;
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
throw new ApiError(`Failed to parse role update response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
124
|
+
}
|
|
125
|
+
// Handle API errors
|
|
126
|
+
if (json.code !== 200) {
|
|
127
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'Role update failed';
|
|
128
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
129
|
+
}
|
|
130
|
+
// Validate response structure
|
|
131
|
+
if (!json.data || !json.data.role) {
|
|
132
|
+
throw new ApiError('Invalid role update response: missing role data', response.status);
|
|
133
|
+
}
|
|
134
|
+
return json.data;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Deletes a role by ID.
|
|
138
|
+
*
|
|
139
|
+
* @param roleId - Role ID to delete
|
|
140
|
+
* @param options - Optional configuration for the request
|
|
141
|
+
* @returns Promise resolving to the deletion result
|
|
142
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
143
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
144
|
+
* @throws {NetworkError} When network request fails
|
|
145
|
+
*/
|
|
146
|
+
export async function deleteRole(roleId, options) {
|
|
147
|
+
// Validate required fields
|
|
148
|
+
if (!roleId || roleId.trim() === '') {
|
|
149
|
+
throw new ApiError('role_id is required for role deletion', 400, '9400');
|
|
150
|
+
}
|
|
151
|
+
// Use provided app token or get one from token service
|
|
152
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
153
|
+
// Determine base URL
|
|
154
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
155
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
156
|
+
if (!base) {
|
|
157
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
158
|
+
}
|
|
159
|
+
const url = String(base).replace(/\/+$/, '') + `/rbac/v1/roles/${encodeURIComponent(roleId)}`;
|
|
160
|
+
let response;
|
|
161
|
+
try {
|
|
162
|
+
response = await globalThis.fetch(url, {
|
|
163
|
+
method: 'DELETE',
|
|
164
|
+
headers: {
|
|
165
|
+
'Content-Type': 'application/json',
|
|
166
|
+
'x-t-token': token,
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
throw new NetworkError(`Failed to delete role: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
172
|
+
}
|
|
173
|
+
let json;
|
|
174
|
+
try {
|
|
175
|
+
const responseJson = await response.json();
|
|
176
|
+
json = responseJson;
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
throw new ApiError(`Failed to parse role deletion response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
180
|
+
}
|
|
181
|
+
// Handle API errors
|
|
182
|
+
if (json.code !== 200) {
|
|
183
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'Role deletion failed';
|
|
184
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
185
|
+
}
|
|
186
|
+
// Validate response structure
|
|
187
|
+
if (!json.data || json.data.deleted !== true) {
|
|
188
|
+
throw new ApiError('Invalid role deletion response: deletion not confirmed', response.status);
|
|
189
|
+
}
|
|
190
|
+
return json.data;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Retrieves role information by ID.
|
|
194
|
+
*
|
|
195
|
+
* @param roleId - Role ID to query
|
|
196
|
+
* @param options - Optional configuration for the request
|
|
197
|
+
* @returns Promise resolving to the role information
|
|
198
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
199
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
200
|
+
* @throws {NetworkError} When network request fails
|
|
201
|
+
*/
|
|
202
|
+
export async function getRoleById(roleId, options) {
|
|
203
|
+
// Validate required fields
|
|
204
|
+
if (!roleId || roleId.trim() === '') {
|
|
205
|
+
throw new ApiError('role_id is required for role query', 400, '9400');
|
|
206
|
+
}
|
|
207
|
+
// Use provided app token or get one from token service
|
|
208
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
209
|
+
// Determine base URL
|
|
210
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
211
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
212
|
+
if (!base) {
|
|
213
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
214
|
+
}
|
|
215
|
+
const url = String(base).replace(/\/+$/, '') + `/rbac/v1/roles/${encodeURIComponent(roleId)}`;
|
|
216
|
+
let response;
|
|
217
|
+
try {
|
|
218
|
+
response = await globalThis.fetch(url, {
|
|
219
|
+
method: 'GET',
|
|
220
|
+
headers: {
|
|
221
|
+
'Content-Type': 'application/json',
|
|
222
|
+
'x-t-token': token,
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
throw new NetworkError(`Failed to get role: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
228
|
+
}
|
|
229
|
+
let json;
|
|
230
|
+
try {
|
|
231
|
+
const responseJson = await response.json();
|
|
232
|
+
json = responseJson;
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
throw new ApiError(`Failed to parse role response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
236
|
+
}
|
|
237
|
+
// Handle API errors
|
|
238
|
+
if (json.code !== 200) {
|
|
239
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'Role retrieval failed';
|
|
240
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
241
|
+
}
|
|
242
|
+
// Validate response structure
|
|
243
|
+
if (!json.data || !json.data.role) {
|
|
244
|
+
throw new ApiError('Invalid role response: missing role data', response.status);
|
|
245
|
+
}
|
|
246
|
+
return json.data;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Lists roles with pagination and filtering.
|
|
250
|
+
*
|
|
251
|
+
* @param options - Optional parameters for pagination, filtering, and configuration
|
|
252
|
+
* @returns Promise resolving to paginated role list with metadata
|
|
253
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
254
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
255
|
+
* @throws {NetworkError} When network request fails
|
|
256
|
+
*/
|
|
257
|
+
export async function listRoles(options) {
|
|
258
|
+
// Use provided app token or get one from token service
|
|
259
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
260
|
+
// Determine base URL
|
|
261
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
262
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
263
|
+
if (!base) {
|
|
264
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
265
|
+
}
|
|
266
|
+
// Build URL with query parameters
|
|
267
|
+
const url = new URL(String(base).replace(/\/+$/, '') + '/rbac/v1/roles');
|
|
268
|
+
// Add query parameters with defaults
|
|
269
|
+
const queryParams = {
|
|
270
|
+
page: 0,
|
|
271
|
+
size: 20,
|
|
272
|
+
sort_by: 'created_at',
|
|
273
|
+
sort_direction: 'desc',
|
|
274
|
+
...options
|
|
275
|
+
};
|
|
276
|
+
// Add parameters to URL
|
|
277
|
+
if (queryParams.page !== undefined) {
|
|
278
|
+
url.searchParams.append('page', String(queryParams.page));
|
|
279
|
+
}
|
|
280
|
+
if (queryParams.size !== undefined) {
|
|
281
|
+
url.searchParams.append('size', String(queryParams.size));
|
|
282
|
+
}
|
|
283
|
+
if (queryParams.role_type) {
|
|
284
|
+
url.searchParams.append('role_type', queryParams.role_type);
|
|
285
|
+
}
|
|
286
|
+
if (queryParams.sort_by) {
|
|
287
|
+
url.searchParams.append('sort_by', queryParams.sort_by);
|
|
288
|
+
}
|
|
289
|
+
if (queryParams.sort_direction) {
|
|
290
|
+
url.searchParams.append('sort_direction', queryParams.sort_direction);
|
|
291
|
+
}
|
|
292
|
+
let response;
|
|
293
|
+
try {
|
|
294
|
+
response = await globalThis.fetch(url.toString(), {
|
|
295
|
+
method: 'GET',
|
|
296
|
+
headers: {
|
|
297
|
+
'Content-Type': 'application/json',
|
|
298
|
+
'x-t-token': token,
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
throw new NetworkError(`Failed to list roles: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
304
|
+
}
|
|
305
|
+
let json;
|
|
306
|
+
try {
|
|
307
|
+
const responseJson = await response.json();
|
|
308
|
+
json = responseJson;
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
throw new ApiError(`Failed to parse roles list response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
312
|
+
}
|
|
313
|
+
// Handle API errors
|
|
314
|
+
if (json.code !== 200) {
|
|
315
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'Roles list retrieval failed';
|
|
316
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
317
|
+
}
|
|
318
|
+
// Validate response structure
|
|
319
|
+
if (!json.data || !Array.isArray(json.data.content)) {
|
|
320
|
+
throw new ApiError('Invalid roles list response: missing required data', response.status);
|
|
321
|
+
}
|
|
322
|
+
return json.data;
|
|
323
|
+
}
|
|
324
|
+
// ===== 权限管理 =====
|
|
325
|
+
/**
|
|
326
|
+
* Creates a new privilege in the Tale application.
|
|
327
|
+
*
|
|
328
|
+
* @param privilegeData - Privilege data to create the new privilege
|
|
329
|
+
* @param options - Optional configuration for the request
|
|
330
|
+
* @returns Promise resolving to the created privilege information
|
|
331
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
332
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
333
|
+
* @throws {NetworkError} When network request fails
|
|
334
|
+
*/
|
|
335
|
+
export async function createPrivilege(privilegeData, options) {
|
|
336
|
+
// Validate required fields
|
|
337
|
+
if (!privilegeData.privilege_name || privilegeData.privilege_name.trim() === '') {
|
|
338
|
+
throw new ApiError('privilege_name is required for privilege creation', 400, '9400');
|
|
339
|
+
}
|
|
340
|
+
// Use provided app token or get one from token service
|
|
341
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
342
|
+
// Determine base URL
|
|
343
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
344
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
345
|
+
if (!base) {
|
|
346
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
347
|
+
}
|
|
348
|
+
const url = String(base).replace(/\/+$/, '') + '/rbac/v1/privileges';
|
|
349
|
+
let response;
|
|
350
|
+
try {
|
|
351
|
+
response = await globalThis.fetch(url, {
|
|
352
|
+
method: 'POST',
|
|
353
|
+
headers: {
|
|
354
|
+
'Content-Type': 'application/json',
|
|
355
|
+
'x-t-token': token,
|
|
356
|
+
},
|
|
357
|
+
body: JSON.stringify(privilegeData),
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
catch (error) {
|
|
361
|
+
throw new NetworkError(`Failed to create privilege: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
362
|
+
}
|
|
363
|
+
let json;
|
|
364
|
+
try {
|
|
365
|
+
const responseJson = await response.json();
|
|
366
|
+
json = responseJson;
|
|
367
|
+
}
|
|
368
|
+
catch (error) {
|
|
369
|
+
throw new ApiError(`Failed to parse privilege creation response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
370
|
+
}
|
|
371
|
+
// Handle API errors
|
|
372
|
+
if (json.code !== 200) {
|
|
373
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'Privilege creation failed';
|
|
374
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
375
|
+
}
|
|
376
|
+
// Validate response structure
|
|
377
|
+
if (!json.data || !json.data.privilege) {
|
|
378
|
+
throw new ApiError('Invalid privilege creation response: missing privilege data', response.status);
|
|
379
|
+
}
|
|
380
|
+
return json.data;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Updates an existing privilege by ID.
|
|
384
|
+
*
|
|
385
|
+
* @param privilegeId - Privilege ID to update
|
|
386
|
+
* @param updateData - Privilege information to update
|
|
387
|
+
* @param options - Optional configuration for the request
|
|
388
|
+
* @returns Promise resolving to the updated privilege information
|
|
389
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
390
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
391
|
+
* @throws {NetworkError} When network request fails
|
|
392
|
+
*/
|
|
393
|
+
export async function updatePrivilege(privilegeId, updateData, options) {
|
|
394
|
+
// Validate required fields
|
|
395
|
+
if (!privilegeId || privilegeId.trim() === '') {
|
|
396
|
+
throw new ApiError('privilege_id is required for privilege update', 400, '9400');
|
|
397
|
+
}
|
|
398
|
+
// Use provided app token or get one from token service
|
|
399
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
400
|
+
// Determine base URL
|
|
401
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
402
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
403
|
+
if (!base) {
|
|
404
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
405
|
+
}
|
|
406
|
+
const url = String(base).replace(/\/+$/, '') + `/rbac/v1/privileges/${encodeURIComponent(privilegeId)}`;
|
|
407
|
+
let response;
|
|
408
|
+
try {
|
|
409
|
+
response = await globalThis.fetch(url, {
|
|
410
|
+
method: 'PUT',
|
|
411
|
+
headers: {
|
|
412
|
+
'Content-Type': 'application/json',
|
|
413
|
+
'x-t-token': token,
|
|
414
|
+
},
|
|
415
|
+
body: JSON.stringify(updateData),
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
catch (error) {
|
|
419
|
+
throw new NetworkError(`Failed to update privilege: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
420
|
+
}
|
|
421
|
+
let json;
|
|
422
|
+
try {
|
|
423
|
+
const responseJson = await response.json();
|
|
424
|
+
json = responseJson;
|
|
425
|
+
}
|
|
426
|
+
catch (error) {
|
|
427
|
+
throw new ApiError(`Failed to parse privilege update response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
428
|
+
}
|
|
429
|
+
// Handle API errors
|
|
430
|
+
if (json.code !== 200) {
|
|
431
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'Privilege update failed';
|
|
432
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
433
|
+
}
|
|
434
|
+
// Validate response structure
|
|
435
|
+
if (!json.data || !json.data.privilege) {
|
|
436
|
+
throw new ApiError('Invalid privilege update response: missing privilege data', response.status);
|
|
437
|
+
}
|
|
438
|
+
return json.data;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Deletes a privilege by ID.
|
|
442
|
+
*
|
|
443
|
+
* @param privilegeId - Privilege ID to delete
|
|
444
|
+
* @param options - Optional configuration for the request
|
|
445
|
+
* @returns Promise resolving to the deletion result
|
|
446
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
447
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
448
|
+
* @throws {NetworkError} When network request fails
|
|
449
|
+
*/
|
|
450
|
+
export async function deletePrivilege(privilegeId, options) {
|
|
451
|
+
// Validate required fields
|
|
452
|
+
if (!privilegeId || privilegeId.trim() === '') {
|
|
453
|
+
throw new ApiError('privilege_id is required for privilege deletion', 400, '9400');
|
|
454
|
+
}
|
|
455
|
+
// Use provided app token or get one from token service
|
|
456
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
457
|
+
// Determine base URL
|
|
458
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
459
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
460
|
+
if (!base) {
|
|
461
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
462
|
+
}
|
|
463
|
+
const url = String(base).replace(/\/+$/, '') + `/rbac/v1/privileges/${encodeURIComponent(privilegeId)}`;
|
|
464
|
+
let response;
|
|
465
|
+
try {
|
|
466
|
+
response = await globalThis.fetch(url, {
|
|
467
|
+
method: 'DELETE',
|
|
468
|
+
headers: {
|
|
469
|
+
'Content-Type': 'application/json',
|
|
470
|
+
'x-t-token': token,
|
|
471
|
+
},
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
catch (error) {
|
|
475
|
+
throw new NetworkError(`Failed to delete privilege: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
476
|
+
}
|
|
477
|
+
let json;
|
|
478
|
+
try {
|
|
479
|
+
const responseJson = await response.json();
|
|
480
|
+
json = responseJson;
|
|
481
|
+
}
|
|
482
|
+
catch (error) {
|
|
483
|
+
throw new ApiError(`Failed to parse privilege deletion response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
484
|
+
}
|
|
485
|
+
// Handle API errors
|
|
486
|
+
if (json.code !== 200) {
|
|
487
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'Privilege deletion failed';
|
|
488
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
489
|
+
}
|
|
490
|
+
// Validate response structure
|
|
491
|
+
if (!json.data || json.data.deleted !== true) {
|
|
492
|
+
throw new ApiError('Invalid privilege deletion response: deletion not confirmed', response.status);
|
|
493
|
+
}
|
|
494
|
+
return json.data;
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Retrieves privilege information by ID.
|
|
498
|
+
*
|
|
499
|
+
* @param privilegeId - Privilege ID to query
|
|
500
|
+
* @param options - Optional configuration for the request
|
|
501
|
+
* @returns Promise resolving to the privilege information
|
|
502
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
503
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
504
|
+
* @throws {NetworkError} When network request fails
|
|
505
|
+
*/
|
|
506
|
+
export async function getPrivilegeById(privilegeId, options) {
|
|
507
|
+
// Validate required fields
|
|
508
|
+
if (!privilegeId || privilegeId.trim() === '') {
|
|
509
|
+
throw new ApiError('privilege_id is required for privilege query', 400, '9400');
|
|
510
|
+
}
|
|
511
|
+
// Use provided app token or get one from token service
|
|
512
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
513
|
+
// Determine base URL
|
|
514
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
515
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
516
|
+
if (!base) {
|
|
517
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
518
|
+
}
|
|
519
|
+
const url = String(base).replace(/\/+$/, '') + `/rbac/v1/privileges/${encodeURIComponent(privilegeId)}`;
|
|
520
|
+
let response;
|
|
521
|
+
try {
|
|
522
|
+
response = await globalThis.fetch(url, {
|
|
523
|
+
method: 'GET',
|
|
524
|
+
headers: {
|
|
525
|
+
'Content-Type': 'application/json',
|
|
526
|
+
'x-t-token': token,
|
|
527
|
+
},
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
catch (error) {
|
|
531
|
+
throw new NetworkError(`Failed to get privilege: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
532
|
+
}
|
|
533
|
+
let json;
|
|
534
|
+
try {
|
|
535
|
+
const responseJson = await response.json();
|
|
536
|
+
json = responseJson;
|
|
537
|
+
}
|
|
538
|
+
catch (error) {
|
|
539
|
+
throw new ApiError(`Failed to parse privilege response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
540
|
+
}
|
|
541
|
+
// Handle API errors
|
|
542
|
+
if (json.code !== 200) {
|
|
543
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'Privilege retrieval failed';
|
|
544
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
545
|
+
}
|
|
546
|
+
// Validate response structure
|
|
547
|
+
if (!json.data || !json.data.privilege) {
|
|
548
|
+
throw new ApiError('Invalid privilege response: missing privilege data', response.status);
|
|
549
|
+
}
|
|
550
|
+
return json.data;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Lists privileges with pagination and filtering.
|
|
554
|
+
*
|
|
555
|
+
* @param options - Optional parameters for pagination, filtering, and configuration
|
|
556
|
+
* @returns Promise resolving to paginated privilege list with metadata
|
|
557
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
558
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
559
|
+
* @throws {NetworkError} When network request fails
|
|
560
|
+
*/
|
|
561
|
+
export async function listPrivileges(options) {
|
|
562
|
+
// Use provided app token or get one from token service
|
|
563
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
564
|
+
// Determine base URL
|
|
565
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
566
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
567
|
+
if (!base) {
|
|
568
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
569
|
+
}
|
|
570
|
+
// Build URL with query parameters
|
|
571
|
+
const url = new URL(String(base).replace(/\/+$/, '') + '/rbac/v1/privileges');
|
|
572
|
+
// Add query parameters with defaults
|
|
573
|
+
const queryParams = {
|
|
574
|
+
page: 0,
|
|
575
|
+
size: 20,
|
|
576
|
+
sort_by: 'created_at',
|
|
577
|
+
sort_direction: 'desc',
|
|
578
|
+
...options
|
|
579
|
+
};
|
|
580
|
+
// Add parameters to URL
|
|
581
|
+
if (queryParams.page !== undefined) {
|
|
582
|
+
url.searchParams.append('page', String(queryParams.page));
|
|
583
|
+
}
|
|
584
|
+
if (queryParams.size !== undefined) {
|
|
585
|
+
url.searchParams.append('size', String(queryParams.size));
|
|
586
|
+
}
|
|
587
|
+
if (queryParams.privilege_type) {
|
|
588
|
+
url.searchParams.append('privilege_type', queryParams.privilege_type);
|
|
589
|
+
}
|
|
590
|
+
if (queryParams.sort_by) {
|
|
591
|
+
url.searchParams.append('sort_by', queryParams.sort_by);
|
|
592
|
+
}
|
|
593
|
+
if (queryParams.sort_direction) {
|
|
594
|
+
url.searchParams.append('sort_direction', queryParams.sort_direction);
|
|
595
|
+
}
|
|
596
|
+
let response;
|
|
597
|
+
try {
|
|
598
|
+
response = await globalThis.fetch(url.toString(), {
|
|
599
|
+
method: 'GET',
|
|
600
|
+
headers: {
|
|
601
|
+
'Content-Type': 'application/json',
|
|
602
|
+
'x-t-token': token,
|
|
603
|
+
},
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
catch (error) {
|
|
607
|
+
throw new NetworkError(`Failed to list privileges: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
608
|
+
}
|
|
609
|
+
let json;
|
|
610
|
+
try {
|
|
611
|
+
const responseJson = await response.json();
|
|
612
|
+
json = responseJson;
|
|
613
|
+
}
|
|
614
|
+
catch (error) {
|
|
615
|
+
throw new ApiError(`Failed to parse privileges list response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
616
|
+
}
|
|
617
|
+
// Handle API errors
|
|
618
|
+
if (json.code !== 200) {
|
|
619
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'Privileges list retrieval failed';
|
|
620
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
621
|
+
}
|
|
622
|
+
// Validate response structure
|
|
623
|
+
if (!json.data || !Array.isArray(json.data.content)) {
|
|
624
|
+
throw new ApiError('Invalid privileges list response: missing required data', response.status);
|
|
625
|
+
}
|
|
626
|
+
return json.data;
|
|
627
|
+
}
|
|
628
|
+
// ===== 用户角色和权限分配 =====
|
|
629
|
+
/**
|
|
630
|
+
* Assigns roles to a user.
|
|
631
|
+
*
|
|
632
|
+
* @param userId - User ID to assign roles to
|
|
633
|
+
* @param assignmentData - Role assignment data
|
|
634
|
+
* @param options - Optional configuration for the request
|
|
635
|
+
* @returns Promise resolving to the assigned roles
|
|
636
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
637
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
638
|
+
* @throws {NetworkError} When network request fails
|
|
639
|
+
*/
|
|
640
|
+
export async function assignRolesToUser(userId, assignmentData, options) {
|
|
641
|
+
// Validate required fields
|
|
642
|
+
if (!userId || userId.trim() === '') {
|
|
643
|
+
throw new ApiError('user_id is required for role assignment', 400, '9400');
|
|
644
|
+
}
|
|
645
|
+
if (!assignmentData.role_ids || assignmentData.role_ids.length === 0) {
|
|
646
|
+
throw new ApiError('role_ids is required for role assignment', 400, '9400');
|
|
647
|
+
}
|
|
648
|
+
// Use provided app token or get one from token service
|
|
649
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
650
|
+
// Determine base URL
|
|
651
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
652
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
653
|
+
if (!base) {
|
|
654
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
655
|
+
}
|
|
656
|
+
const url = String(base).replace(/\/+$/, '') + `/rbac/v1/user/${encodeURIComponent(userId)}/roles`;
|
|
657
|
+
let response;
|
|
658
|
+
try {
|
|
659
|
+
response = await globalThis.fetch(url, {
|
|
660
|
+
method: 'POST',
|
|
661
|
+
headers: {
|
|
662
|
+
'Content-Type': 'application/json',
|
|
663
|
+
'x-t-token': token,
|
|
664
|
+
},
|
|
665
|
+
body: JSON.stringify(assignmentData),
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
catch (error) {
|
|
669
|
+
throw new NetworkError(`Failed to assign roles to user: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
670
|
+
}
|
|
671
|
+
let json;
|
|
672
|
+
try {
|
|
673
|
+
const responseJson = await response.json();
|
|
674
|
+
json = responseJson;
|
|
675
|
+
}
|
|
676
|
+
catch (error) {
|
|
677
|
+
throw new ApiError(`Failed to parse role assignment response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
678
|
+
}
|
|
679
|
+
// Handle API errors
|
|
680
|
+
if (json.code !== 200) {
|
|
681
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'Role assignment failed';
|
|
682
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
683
|
+
}
|
|
684
|
+
// Validate response structure
|
|
685
|
+
if (!json.data || !json.data.roles) {
|
|
686
|
+
throw new ApiError('Invalid role assignment response: missing roles data', response.status);
|
|
687
|
+
}
|
|
688
|
+
return json.data;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Unassigns roles from a user.
|
|
692
|
+
*
|
|
693
|
+
* @param userId - User ID to unassign roles from
|
|
694
|
+
* @param unassignmentData - Role unassignment data
|
|
695
|
+
* @param options - Optional configuration for the request
|
|
696
|
+
* @returns Promise resolving to the unassignment result
|
|
697
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
698
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
699
|
+
* @throws {NetworkError} When network request fails
|
|
700
|
+
*/
|
|
701
|
+
export async function unassignRolesFromUser(userId, unassignmentData, options) {
|
|
702
|
+
// Validate required fields
|
|
703
|
+
if (!userId || userId.trim() === '') {
|
|
704
|
+
throw new ApiError('user_id is required for role unassignment', 400, '9400');
|
|
705
|
+
}
|
|
706
|
+
if (!unassignmentData.role_ids || unassignmentData.role_ids.length === 0) {
|
|
707
|
+
throw new ApiError('role_ids is required for role unassignment', 400, '9400');
|
|
708
|
+
}
|
|
709
|
+
// Use provided app token or get one from token service
|
|
710
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
711
|
+
// Determine base URL
|
|
712
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
713
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
714
|
+
if (!base) {
|
|
715
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
716
|
+
}
|
|
717
|
+
const url = String(base).replace(/\/+$/, '') + `/rbac/v1/user/${encodeURIComponent(userId)}/roles`;
|
|
718
|
+
let response;
|
|
719
|
+
try {
|
|
720
|
+
response = await globalThis.fetch(url, {
|
|
721
|
+
method: 'DELETE',
|
|
722
|
+
headers: {
|
|
723
|
+
'Content-Type': 'application/json',
|
|
724
|
+
'x-t-token': token,
|
|
725
|
+
},
|
|
726
|
+
body: JSON.stringify(unassignmentData),
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
catch (error) {
|
|
730
|
+
throw new NetworkError(`Failed to unassign roles from user: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
731
|
+
}
|
|
732
|
+
let json;
|
|
733
|
+
try {
|
|
734
|
+
const responseJson = await response.json();
|
|
735
|
+
json = responseJson;
|
|
736
|
+
}
|
|
737
|
+
catch (error) {
|
|
738
|
+
throw new ApiError(`Failed to parse role unassignment response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
739
|
+
}
|
|
740
|
+
// Handle API errors
|
|
741
|
+
if (json.code !== 200) {
|
|
742
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'Role unassignment failed';
|
|
743
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
744
|
+
}
|
|
745
|
+
// Validate response structure
|
|
746
|
+
if (!json.data || json.data.unassigned !== true) {
|
|
747
|
+
throw new ApiError('Invalid role unassignment response: unassignment not confirmed', response.status);
|
|
748
|
+
}
|
|
749
|
+
return json.data;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Assigns privileges to a user.
|
|
753
|
+
*
|
|
754
|
+
* @param userId - User ID to assign privileges to
|
|
755
|
+
* @param assignmentData - Privilege assignment data
|
|
756
|
+
* @param options - Optional configuration for the request
|
|
757
|
+
* @returns Promise resolving to the assigned privileges
|
|
758
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
759
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
760
|
+
* @throws {NetworkError} When network request fails
|
|
761
|
+
*/
|
|
762
|
+
export async function assignPrivilegesToUser(userId, assignmentData, options) {
|
|
763
|
+
// Validate required fields
|
|
764
|
+
if (!userId || userId.trim() === '') {
|
|
765
|
+
throw new ApiError('user_id is required for privilege assignment', 400, '9400');
|
|
766
|
+
}
|
|
767
|
+
if (!assignmentData.privilege_ids || assignmentData.privilege_ids.length === 0) {
|
|
768
|
+
throw new ApiError('privilege_ids is required for privilege assignment', 400, '9400');
|
|
769
|
+
}
|
|
770
|
+
// Use provided app token or get one from token service
|
|
771
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
772
|
+
// Determine base URL
|
|
773
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
774
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
775
|
+
if (!base) {
|
|
776
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
777
|
+
}
|
|
778
|
+
const url = String(base).replace(/\/+$/, '') + `/rbac/v1/user/${encodeURIComponent(userId)}/privileges`;
|
|
779
|
+
let response;
|
|
780
|
+
try {
|
|
781
|
+
response = await globalThis.fetch(url, {
|
|
782
|
+
method: 'POST',
|
|
783
|
+
headers: {
|
|
784
|
+
'Content-Type': 'application/json',
|
|
785
|
+
'x-t-token': token,
|
|
786
|
+
},
|
|
787
|
+
body: JSON.stringify(assignmentData),
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
catch (error) {
|
|
791
|
+
throw new NetworkError(`Failed to assign privileges to user: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
792
|
+
}
|
|
793
|
+
let json;
|
|
794
|
+
try {
|
|
795
|
+
const responseJson = await response.json();
|
|
796
|
+
json = responseJson;
|
|
797
|
+
}
|
|
798
|
+
catch (error) {
|
|
799
|
+
throw new ApiError(`Failed to parse privilege assignment response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
800
|
+
}
|
|
801
|
+
// Handle API errors
|
|
802
|
+
if (json.code !== 200) {
|
|
803
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'Privilege assignment failed';
|
|
804
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
805
|
+
}
|
|
806
|
+
// Validate response structure
|
|
807
|
+
if (!json.data || !json.data.privileges) {
|
|
808
|
+
throw new ApiError('Invalid privilege assignment response: missing privileges data', response.status);
|
|
809
|
+
}
|
|
810
|
+
return json.data;
|
|
811
|
+
}
|
|
812
|
+
/**
|
|
813
|
+
* Unassigns privileges from a user.
|
|
814
|
+
*
|
|
815
|
+
* @param userId - User ID to unassign privileges from
|
|
816
|
+
* @param unassignmentData - Privilege unassignment data
|
|
817
|
+
* @param options - Optional configuration for the request
|
|
818
|
+
* @returns Promise resolving to the unassignment result
|
|
819
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
820
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
821
|
+
* @throws {NetworkError} When network request fails
|
|
822
|
+
*/
|
|
823
|
+
export async function unassignPrivilegesFromUser(userId, unassignmentData, options) {
|
|
824
|
+
// Validate required fields
|
|
825
|
+
if (!userId || userId.trim() === '') {
|
|
826
|
+
throw new ApiError('user_id is required for privilege unassignment', 400, '9400');
|
|
827
|
+
}
|
|
828
|
+
if (!unassignmentData.privilege_ids || unassignmentData.privilege_ids.length === 0) {
|
|
829
|
+
throw new ApiError('privilege_ids is required for privilege unassignment', 400, '9400');
|
|
830
|
+
}
|
|
831
|
+
// Use provided app token or get one from token service
|
|
832
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
833
|
+
// Determine base URL
|
|
834
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
835
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
836
|
+
if (!base) {
|
|
837
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
838
|
+
}
|
|
839
|
+
const url = String(base).replace(/\/+$/, '') + `/rbac/v1/user/${encodeURIComponent(userId)}/privileges`;
|
|
840
|
+
let response;
|
|
841
|
+
try {
|
|
842
|
+
response = await globalThis.fetch(url, {
|
|
843
|
+
method: 'DELETE',
|
|
844
|
+
headers: {
|
|
845
|
+
'Content-Type': 'application/json',
|
|
846
|
+
'x-t-token': token,
|
|
847
|
+
},
|
|
848
|
+
body: JSON.stringify(unassignmentData),
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
catch (error) {
|
|
852
|
+
throw new NetworkError(`Failed to unassign privileges from user: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
853
|
+
}
|
|
854
|
+
let json;
|
|
855
|
+
try {
|
|
856
|
+
const responseJson = await response.json();
|
|
857
|
+
json = responseJson;
|
|
858
|
+
}
|
|
859
|
+
catch (error) {
|
|
860
|
+
throw new ApiError(`Failed to parse privilege unassignment response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
861
|
+
}
|
|
862
|
+
// Handle API errors
|
|
863
|
+
if (json.code !== 200) {
|
|
864
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'Privilege unassignment failed';
|
|
865
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
866
|
+
}
|
|
867
|
+
// Validate response structure
|
|
868
|
+
if (!json.data || json.data.unassigned !== true) {
|
|
869
|
+
throw new ApiError('Invalid privilege unassignment response: unassignment not confirmed', response.status);
|
|
870
|
+
}
|
|
871
|
+
return json.data;
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* Gets the roles assigned to a user.
|
|
875
|
+
*
|
|
876
|
+
* @param userId - User ID to query
|
|
877
|
+
* @param options - Optional configuration for the request
|
|
878
|
+
* @returns Promise resolving to the user's roles
|
|
879
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
880
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
881
|
+
* @throws {NetworkError} When network request fails
|
|
882
|
+
*/
|
|
883
|
+
export async function getUserRoles(userId, options) {
|
|
884
|
+
// Validate required fields
|
|
885
|
+
if (!userId || userId.trim() === '') {
|
|
886
|
+
throw new ApiError('user_id is required for user roles query', 400, '9400');
|
|
887
|
+
}
|
|
888
|
+
// Use provided app token or get one from token service
|
|
889
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
890
|
+
// Determine base URL
|
|
891
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
892
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
893
|
+
if (!base) {
|
|
894
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
895
|
+
}
|
|
896
|
+
const url = String(base).replace(/\/+$/, '') + `/rbac/v1/user/${encodeURIComponent(userId)}/roles`;
|
|
897
|
+
let response;
|
|
898
|
+
try {
|
|
899
|
+
response = await globalThis.fetch(url, {
|
|
900
|
+
method: 'GET',
|
|
901
|
+
headers: {
|
|
902
|
+
'Content-Type': 'application/json',
|
|
903
|
+
'x-t-token': token,
|
|
904
|
+
},
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
catch (error) {
|
|
908
|
+
throw new NetworkError(`Failed to get user roles: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
909
|
+
}
|
|
910
|
+
let json;
|
|
911
|
+
try {
|
|
912
|
+
const responseJson = await response.json();
|
|
913
|
+
json = responseJson;
|
|
914
|
+
}
|
|
915
|
+
catch (error) {
|
|
916
|
+
throw new ApiError(`Failed to parse user roles response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
917
|
+
}
|
|
918
|
+
// Handle API errors
|
|
919
|
+
if (json.code !== 200) {
|
|
920
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'User roles retrieval failed';
|
|
921
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
922
|
+
}
|
|
923
|
+
// Validate response structure
|
|
924
|
+
if (!json.data || !json.data.roles) {
|
|
925
|
+
throw new ApiError('Invalid user roles response: missing roles data', response.status);
|
|
926
|
+
}
|
|
927
|
+
return json.data;
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* Gets the privileges assigned to a user.
|
|
931
|
+
*
|
|
932
|
+
* @param userId - User ID to query
|
|
933
|
+
* @param options - Optional configuration for the request
|
|
934
|
+
* @returns Promise resolving to the user's privileges
|
|
935
|
+
* @throws {ConfigurationError} When required environment variables are missing
|
|
936
|
+
* @throws {ApiError} When API request fails or returns invalid response
|
|
937
|
+
* @throws {NetworkError} When network request fails
|
|
938
|
+
*/
|
|
939
|
+
export async function getUserPrivileges(userId, options) {
|
|
940
|
+
// Validate required fields
|
|
941
|
+
if (!userId || userId.trim() === '') {
|
|
942
|
+
throw new ApiError('user_id is required for user privileges query', 400, '9400');
|
|
943
|
+
}
|
|
944
|
+
// Use provided app token or get one from token service
|
|
945
|
+
const token = options?.appToken ?? await getAppToken(options);
|
|
946
|
+
// Determine base URL
|
|
947
|
+
const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
|
|
948
|
+
const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
|
|
949
|
+
if (!base) {
|
|
950
|
+
throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
|
|
951
|
+
}
|
|
952
|
+
const url = String(base).replace(/\/+$/, '') + `/rbac/v1/user/${encodeURIComponent(userId)}/privileges`;
|
|
953
|
+
let response;
|
|
954
|
+
try {
|
|
955
|
+
response = await globalThis.fetch(url, {
|
|
956
|
+
method: 'GET',
|
|
957
|
+
headers: {
|
|
958
|
+
'Content-Type': 'application/json',
|
|
959
|
+
'x-t-token': token,
|
|
960
|
+
},
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
catch (error) {
|
|
964
|
+
throw new NetworkError(`Failed to get user privileges: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
965
|
+
}
|
|
966
|
+
let json;
|
|
967
|
+
try {
|
|
968
|
+
const responseJson = await response.json();
|
|
969
|
+
json = responseJson;
|
|
970
|
+
}
|
|
971
|
+
catch (error) {
|
|
972
|
+
throw new ApiError(`Failed to parse user privileges response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
|
|
973
|
+
}
|
|
974
|
+
// Handle API errors
|
|
975
|
+
if (json.code !== 200) {
|
|
976
|
+
const errorMsg = typeof json.msg === 'string' ? json.msg : 'User privileges retrieval failed';
|
|
977
|
+
throw new ApiError(errorMsg, response.status, json.code);
|
|
978
|
+
}
|
|
979
|
+
// Validate response structure
|
|
980
|
+
if (!json.data || !json.data.privileges) {
|
|
981
|
+
throw new ApiError('Invalid user privileges response: missing privileges data', response.status);
|
|
982
|
+
}
|
|
983
|
+
return json.data;
|
|
984
|
+
}
|