"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.RolesManagementClient = void 0; var graphql_v2_1 = require("../../types/graphql.v2"); var graphqlapi_1 = require("../graphqlapi"); var utils_1 = require("../utils"); /** * @class RolesManagementClient 管理角色 * @description 此模块用于管理 Authing 角色,可以进行角色的增删改查、角色添加/删除用户、角色添加/删除策略 等操作。 * * @example * * 请使用以下方式使用该模块,而不要直接初始化该模块: * \`\`\`javascript * import { ManagementClient } from "authing-js-sdk" * const managementClient = new ManagementClient({ * userPoolId: "YOUR_USERPOOL_ID", * secret: "YOUR_USERPOOL_SECRET", * }) * managementClient.roles.list // 获取角色列表 * managementClient.roles.create // 创建角色 * managementClient.roles.listUsers // 获取角色用户列表 * \`\`\` * * @name RolesManagementClient */ var RolesManagementClient = /** @class */ (function () { function RolesManagementClient(options, graphqlClient, tokenProvider) { this.options = options; this.graphqlClient = graphqlClient; this.tokenProvider = tokenProvider; } /** * @name create * @name_zh 创建角色 * @description 创建角色 * * @param {string} code 角色唯一标志符 * @param {string} [options.description] 描述 * @param {string} [options.namespace] 该角色所在的 namespace,默认为 default * * @example * managementClient.roles.create('rolea', 'RoleA') * * @returns {Promise>} * @memberof RolesManagementClient */ RolesManagementClient.prototype.create = function (code, description, namespace) { return __awaiter(this, void 0, void 0, function () { var res; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, graphqlapi_1.addRole(this.graphqlClient, this.tokenProvider, { code: code, description: description, namespace: namespace })]; case 1: res = _a.sent(); return [2 /*return*/, res.createRole]; } }); }); }; /** * @name delete * @name_zh 删除角色 * @description 删除角色 * * @param {string} code 角色唯一标志符 * @param {string} [namespace] 角色所属的 Namespace code,默认值为 'default' * * @example * managementClient.roles.delete('rolea') * * @returns {Promise} * @memberof RolesManagementClient */ RolesManagementClient.prototype.delete = function (code, namespace) { return __awaiter(this, void 0, void 0, function () { var data; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, graphqlapi_1.deleteRole(this.graphqlClient, this.tokenProvider, { code: code, namespace: namespace })]; case 1: data = (_a.sent()).deleteRole; return [2 /*return*/, data]; } }); }); }; /** * @name deleteMany * @name_zh 批量删除角色 * @description 批量删除角色 * * @param {string[]} codeList 角色唯一标志符列表 * @param {string} [namespace] 角色所属的 Namespace,默认值为 'default' * * @example * managementClient.roles.delete(['rolea']) * * @returns {Promise} * @memberof RolesManagementClient */ RolesManagementClient.prototype.deleteMany = function (codeList, namespace) { return __awaiter(this, void 0, void 0, function () { var data; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, graphqlapi_1.deleteRoles(this.graphqlClient, this.tokenProvider, { codeList: codeList, namespace: namespace })]; case 1: data = (_a.sent()).deleteRoles; return [2 /*return*/, data]; } }); }); }; /** * @name update * @name_zh 修改角色 * @description 修改角色 * * @param {string} code 角色唯一标志符 * @param {Object} options * @param {string} options.description 描述信息 * @param {string} options.newCode 新的唯一标志符 * @param {string} options.namespace 角色所属的 Namespace,默认值为 'default' * * @example * managementClient.roles.update('rolea', {newCode: 'newcode'}) * * * @returns {Promise>} * @memberof RolesManagementClient */ RolesManagementClient.prototype.update = function (code, options) { return __awaiter(this, void 0, void 0, function () { var description, newCode, namespace, data; return __generator(this, function (_a) { switch (_a.label) { case 0: description = options.description, newCode = options.newCode, namespace = options.namespace; return [4 /*yield*/, graphqlapi_1.updateRole(this.graphqlClient, this.tokenProvider, { code: code, description: description, newCode: newCode, namespace: namespace })]; case 1: data = (_a.sent()).updateRole; return [2 /*return*/, data]; } }); }); }; /** * @deprecated 已过时, 不建议使用 */ RolesManagementClient.prototype.detail = function (code, namespace) { return __awaiter(this, void 0, void 0, function () { var data; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, graphqlapi_1.role(this.graphqlClient, this.tokenProvider, { code: code, namespace: namespace })]; case 1: data = (_a.sent()).role; return [2 /*return*/, data]; } }); }); }; /** * * @name findByCode * @name_zh 获取角色详情 * @description 获取角色详情 * * @param {string} code 角色唯一标志符 * @param {string} [namespace] 角色所属的 Namespace,默认值为 'default' * * @example` * managementClient.roles.detail('manager') * * @returns {Promise>} 角色详情 * @memberof RolesManagementClient */ RolesManagementClient.prototype.findByCode = function (code, namespace) { return __awaiter(this, void 0, void 0, function () { var data; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.detail(code, namespace)]; case 1: data = _a.sent(); return [2 /*return*/, data]; } }); }); }; /** * @name list * @name_zh 获取角色列表 * @description 获取角色列表 * * @param {Object} [options] * @param {number} [options.page=1] 页码数 * @param {number} [options.limit=10] 每页个数 * @param {string} [options.namespace] 角色所属的 Namespace,默认值为 'default' * * @example * managementClient.roles.list(2, 10) * * @returns {Promise>} * @memberof RolesManagementClient */ RolesManagementClient.prototype.list = function (options) { return __awaiter(this, void 0, void 0, function () { var _a, _b, page, _c, limit, namespace, data; return __generator(this, function (_d) { switch (_d.label) { case 0: _a = options || {}, _b = _a.page, page = _b === void 0 ? 1 : _b, _c = _a.limit, limit = _c === void 0 ? 10 : _c, namespace = _a.namespace; return [4 /*yield*/, graphqlapi_1.roles(this.graphqlClient, this.tokenProvider, { page: page, limit: limit, namespace: namespace })]; case 1: data = (_d.sent()).roles; return [2 /*return*/, data]; } }); }); }; /** * @name listUsers * @name_zh 获取角色用户列表 * @description 获取角色用户列表 * * @param {string} code 角色唯一标志符 * * @param {string} [namespace] 角色所属的 Namespace,默认值为 'default' * * @example * managementClient.roles.listUsers(code) * * @returns {Promise>} * @memberof RolesManagementClient */ RolesManagementClient.prototype.listUsers = function (code, options) { return __awaiter(this, void 0, void 0, function () { var _a, namespace, _b, withCustomData, _c, page, _d, limit, data, data, _e, totalCount, list; return __generator(this, function (_f) { switch (_f.label) { case 0: _a = options || {}, namespace = _a.namespace, _b = _a.withCustomData, withCustomData = _b === void 0 ? false : _b, _c = _a.page, page = _c === void 0 ? 1 : _c, _d = _a.limit, limit = _d === void 0 ? 10 : _d; if (!!withCustomData) return [3 /*break*/, 2]; return [4 /*yield*/, graphqlapi_1.roleWithUsers(this.graphqlClient, this.tokenProvider, { code: code, namespace: namespace, page: page, limit: limit })]; case 1: data = (_f.sent()).role; if (!data) { return [2 /*return*/, { totalCount: 0, list: [] }]; } return [2 /*return*/, data.users]; case 2: return [4 /*yield*/, graphqlapi_1.roleWithUsersWithCustomData(this.graphqlClient, this.tokenProvider, { code: code, namespace: namespace, page: page, limit: limit })]; case 3: data = (_f.sent()).role; if (!data) { return [2 /*return*/, { totalCount: 0, list: [] }]; } _e = data.users, totalCount = _e.totalCount, list = _e.list; list = list.map(function (user) { // @ts-ignore user.customData = utils_1.convertUdvToKeyValuePair(user.customData); return user; }); return [2 /*return*/, { totalCount: totalCount, list: list }]; } }); }); }; /** * @name addUsers * @name_zh 添加用户 * @description 添加用户 * * @param {string} code 角色唯一标志符 * @param {string[]} userIds 用户 ID 列表 * @param {string} [namespace] 角色所属的 Namespace,默认值为 'default' * * @example * managementClient.roles.addUsers(code, ['USERID1', 'USERID2']) * * @returns {Promise} * @memberof RolesManagementClient */ RolesManagementClient.prototype.addUsers = function (code, userIds, namespace) { return __awaiter(this, void 0, void 0, function () { var res; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, graphqlapi_1.assignRole(this.graphqlClient, this.tokenProvider, { roleCode: code, userIds: userIds, namespace: namespace })]; case 1: res = _a.sent(); return [2 /*return*/, res.assignRole]; } }); }); }; /** * @name removeUsers * @name_zh 移除用户 * * @description 移除用户 * * @param {string} code 角色唯一标志符 * @param {string[]} userIds 用户 ID 列表 * @param {string} [namespace] 角色所属的 Namespace,默认值为 'default' * * @example * managementClient.roles.removeUsers(code, ['USERID1', 'USERID2']) * * @returns {Promise} * @memberof RolesManagementClient */ RolesManagementClient.prototype.removeUsers = function (code, userIds, namespace) { return __awaiter(this, void 0, void 0, function () { var res; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, graphqlapi_1.revokeRole(this.graphqlClient, this.tokenProvider, { roleCode: code, userIds: userIds, namespace: namespace })]; case 1: res = _a.sent(); return [2 /*return*/, res.revokeRole]; } }); }); }; /** * @name listPolicies * @name_zh 获取角色策略列表 * * @description 获取角色策略列表 * * @param {string} code 角色唯一标志符 * @param {number} [page=1] 页码数 * @param {number} [limit=10] 页码个数 * @example * managementClient.roles.listPolicies('codea', 1, 10) * * @returns {Promise} * @memberof RolesManagementClient */ RolesManagementClient.prototype.listPolicies = function (code, page, limit) { if (page === void 0) { page = 1; } if (limit === void 0) { limit = 10; } return __awaiter(this, void 0, void 0, function () { var data; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, graphqlapi_1.policyAssignments(this.graphqlClient, this.tokenProvider, { targetType: graphql_v2_1.PolicyAssignmentTargetType.Role, targetIdentifier: code, page: page, limit: limit })]; case 1: data = (_a.sent()).policyAssignments; return [2 /*return*/, data]; } }); }); }; /** * @name addPolicies * @name_zh 授权策略 * * @description 给角色授权策略策略 * * @param {string} code 角色唯一标志符 * @param {string[]} policies 策略列表 * @example * managementClient.roles.addPolicies('rolea', ['PolicyA', 'PolicyB']) * * @returns {Promise} * @memberof RolesManagementClient */ RolesManagementClient.prototype.addPolicies = function (code, policies) { return __awaiter(this, void 0, void 0, function () { var res; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, graphqlapi_1.addPolicyAssignments(this.graphqlClient, this.tokenProvider, { targetType: graphql_v2_1.PolicyAssignmentTargetType.User, targetIdentifiers: [code], policies: policies })]; case 1: res = _a.sent(); return [2 /*return*/, res.addPolicyAssignments]; } }); }); }; /** * @name removePolicies * @name_zh 角色移除策略 * * @description 角色移除策略 * * @param {string} code 角色唯一标志符 * @param {string[]} policies 策略列表 * @example * managementClient.roles.removePolicies('rolea', ['PolicyA', 'PolicyB']) * * @returns {Promise} * @memberof RolesManagementClient */ RolesManagementClient.prototype.removePolicies = function (code, policies) { return __awaiter(this, void 0, void 0, function () { var res; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, graphqlapi_1.removePolicyAssignments(this.graphqlClient, this.tokenProvider, { targetType: graphql_v2_1.PolicyAssignmentTargetType.User, targetIdentifiers: [code], policies: policies })]; case 1: res = _a.sent(); return [2 /*return*/, res.removePolicyAssignments]; } }); }); }; /** * @description 获取角色被授权的所有资源 * * @param code: 角色 code * @param namespace: 角色权限组 namespace code * @param options.resourceType 资源类型 */ RolesManagementClient.prototype.listAuthorizedResources = function (code, namespace, options) { return __awaiter(this, void 0, void 0, function () { var resourceType, role, _a, list, totalCount; return __generator(this, function (_b) { switch (_b.label) { case 0: resourceType = (options || {}).resourceType; return [4 /*yield*/, graphqlapi_1.listRoleAuthorizedResources(this.graphqlClient, this.tokenProvider, { code: code, namespace: namespace, resourceType: resourceType })]; case 1: role = (_b.sent()).role; if (!role) { throw new Error('角色不存在'); } _a = role.authorizedResources, list = _a.list, totalCount = _a.totalCount; list = utils_1.formatAuthorizedResources(list); return [2 /*return*/, { list: list, totalCount: totalCount }]; } }); }); }; /** * 获取某个角色扩展字段列表 * @param roleId 角色 ID * @returns Promise<{ [key: string]: any }> */ RolesManagementClient.prototype.getUdfValue = function (roleId) { return __awaiter(this, void 0, void 0, function () { var list; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, graphqlapi_1.udv(this.graphqlClient, this.tokenProvider, { targetType: graphql_v2_1.UdfTargetType.Role, targetId: roleId })]; case 1: list = (_a.sent()).udv; return [2 /*return*/, utils_1.convertUdvToKeyValuePair(list)]; } }); }); }; /** * 获取某个角色某个扩展字段 * @param roleId 角色 ID * @param udfKey 扩展字段 Key * @returns Promise<{ [key: string]: any }> */ RolesManagementClient.prototype.getSpecificUdfValue = function (roleId, udfKey) { return __awaiter(this, void 0, void 0, function () { var list, udfMap, udfValue, key; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, graphqlapi_1.udv(this.graphqlClient, this.tokenProvider, { targetType: graphql_v2_1.UdfTargetType.Role, targetId: roleId })]; case 1: list = (_a.sent()).udv; udfMap = utils_1.convertUdvToKeyValuePair(list); udfValue = {}; for (key in udfMap) { if (udfKey === key) { udfValue[key] = udfMap[key]; } } return [2 /*return*/, udfValue]; } }); }); }; /** * 获取多个角色扩展字段列表 * @param roleId 角色 ID 列表 * @returns Promise<{ [x: string]: KeyValuePair }> */ RolesManagementClient.prototype.getUdfValueBatch = function (roleIds) { return __awaiter(this, void 0, void 0, function () { var result, ret, _i, result_1, _a, targetId, data; return __generator(this, function (_b) { switch (_b.label) { case 0: if (roleIds.length === 0) { throw new Error('empty user id list'); } return [4 /*yield*/, graphqlapi_1.udfValueBatch(this.graphqlClient, this.tokenProvider, { targetType: graphql_v2_1.UdfTargetType.Role, targetIds: roleIds })]; case 1: result = (_b.sent()).udfValueBatch; ret = {}; for (_i = 0, result_1 = result; _i < result_1.length; _i++) { _a = result_1[_i], targetId = _a.targetId, data = _a.data; ret[targetId] = utils_1.convertUdvToKeyValuePair(data); } return [2 /*return*/, ret]; } }); }); }; /** * 设置某个角色扩展字段列表 * @param roleId 角色 ID 列表 * @param data 扩展字段 */ RolesManagementClient.prototype.setUdfValue = function (roleId, data) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: if (Object.keys(data).length === 0) { throw new Error('empty udf value list'); } return [4 /*yield*/, graphqlapi_1.setUdvBatch(this.graphqlClient, this.tokenProvider, { targetType: graphql_v2_1.UdfTargetType.Role, targetId: roleId, udvList: Object.keys(data).map(function (key) { return ({ key: key, value: JSON.stringify(data[key]) }); }) })]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; /** * 设置多个角色扩展字段列表 * @param input.roleId 角色 ID 列表 * @param input.data 扩展字段 */ RolesManagementClient.prototype.setUdfValueBatch = function (input) { return __awaiter(this, void 0, void 0, function () { var params; return __generator(this, function (_a) { switch (_a.label) { case 0: if (input.length === 0) { throw new Error('empty input list'); } params = []; input.forEach(function (_a) { var userId = _a.roleId, data = _a.data; for (var _i = 0, _b = Object.keys(data); _i < _b.length; _i++) { var key = _b[_i]; params.push({ targetId: userId, key: key, value: JSON.stringify(data[key]) }); } }); return [4 /*yield*/, graphqlapi_1.setUdfValueBatch(this.graphqlClient, this.tokenProvider, { targetType: graphql_v2_1.UdfTargetType.Role, input: params })]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; /** * 删除用户的扩展字段 * @param input.roleId 角色 ID 列表 * @param input.key 扩展字段名 */ RolesManagementClient.prototype.removeUdfValue = function (roleId, key) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, graphqlapi_1.removeUdv(this.graphqlClient, this.tokenProvider, { targetType: graphql_v2_1.UdfTargetType.Role, targetId: roleId, key: key })]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; return RolesManagementClient; }()); exports.RolesManagementClient = RolesManagementClient; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUm9sZXNNYW5hZ2VtZW50Q2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9tYW5hZ2VtZW50L1JvbGVzTWFuYWdlbWVudENsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFHQSxxREFXZ0M7QUFDaEMsNENBb0J1QjtBQUV2QixrQ0FBK0U7QUFFL0U7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQkc7QUFDSDtJQUtFLCtCQUNFLE9BQWdDLEVBQ2hDLGFBQTRCLEVBQzVCLGFBQXNDO1FBRXRDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFDO1FBQ25DLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFDO0lBQ3JDLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7T0FjRztJQUNHLHNDQUFNLEdBQVosVUFDRSxJQUFZLEVBQ1osV0FBb0IsRUFDcEIsU0FBa0I7Ozs7OzRCQUVOLHFCQUFNLG9CQUFPLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsYUFBYSxFQUFFOzRCQUNoRSxJQUFJLE1BQUE7NEJBQ0osV0FBVyxhQUFBOzRCQUNYLFNBQVMsV0FBQTt5QkFDVixDQUFDLEVBQUE7O3dCQUpJLEdBQUcsR0FBRyxTQUlWO3dCQUNGLHNCQUFPLEdBQUcsQ0FBQyxVQUFVLEVBQUM7Ozs7S0FDdkI7SUFFRDs7Ozs7Ozs7Ozs7OztPQWFHO0lBQ0csc0NBQU0sR0FBWixVQUFhLElBQVksRUFBRSxTQUFrQjs7Ozs7NEJBQ2QscUJBQU0sdUJBQVUsQ0FDM0MsSUFBSSxDQUFDLGFBQWEsRUFDbEIsSUFBSSxDQUFDLGFBQWEsRUFDbEI7NEJBQ0UsSUFBSSxNQUFBOzRCQUNKLFNBQVMsV0FBQTt5QkFDVixDQUNGLEVBQUE7O3dCQVBtQixJQUFJLEdBQUssQ0FBQSxTQU81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