auth0-tenant-to-tenant-user-migration-tool
Version:
Auth0 tenant to tenant user migration tool
122 lines • 6.63 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.migrateUserRoles = void 0;
const request_prerequiste_data_1 = require("../utils/request-prerequiste-data");
const get_management_token_1 = require("../utils/get-management-token");
const get_roles_1 = __importDefault(require("../utils/get-roles"));
const assign_roles_to_user_1 = __importDefault(require("../utils/assign-roles-to-user"));
const get_users_in_role_1 = __importDefault(require("../utils/get-users-in-role"));
const get_user_by_email_1 = __importDefault(require("../utils/get-user-by-email"));
const get_user_roles_1 = __importDefault(require("../utils/get-user-roles"));
const create_role_1 = __importDefault(require("../utils/create-role"));
const with_graceful_exit_1 = __importDefault(require("../utils/with-graceful-exit"));
const logger_1 = __importDefault(require("../utils/logger"));
const getTokens = async () => {
const { domain: sourceDomain, clientId: sourceClientId, clientSecret: sourceClientSecret, } = await (0, request_prerequiste_data_1.requestAuthOConfiguration)('source');
const { domain: destinationDomain, clientId: destinationClientId, clientSecret: destinationClientSecret, } = await (0, request_prerequiste_data_1.requestAuthOConfiguration)('destination');
const [sourceToken, destinationToken] = await Promise.all([
(0, get_management_token_1.getManagementToken)(sourceDomain, sourceClientId, sourceClientSecret),
(0, get_management_token_1.getManagementToken)(destinationDomain, destinationClientId, destinationClientSecret),
]);
return { sourceDomain, destinationDomain, sourceToken, destinationToken };
};
const getMatchingRoles = async (sourceDomain, destinationDomain, sourceToken, destinationToken) => {
const [sourceRoles, destinationRoles] = (await Promise.all([
(0, get_roles_1.default)(sourceDomain, sourceToken),
(0, get_roles_1.default)(destinationDomain, destinationToken),
]));
const rolesToMigrate = sourceRoles.reduce((acc, srcRole) => {
const match = destinationRoles.find((destRole) => srcRole.name === destRole.name);
acc.push({
name: srcRole.name,
description: match?.description ?? srcRole.description,
sourceRoleId: srcRole.id,
destinationRoleId: match?.id ?? '',
});
return acc;
}, []);
return (0, request_prerequiste_data_1.selectRolesToMigrate)(rolesToMigrate);
};
const buildUserRoleMap = async (selectedRoles, sourceDomain, destinationDomain, sourceToken, destinationToken) => {
const userRoleMap = new Map();
const missingUsers = [];
for (const role of selectedRoles) {
try {
logger_1.default.info(`Processing role: ${role.name}`);
const destinationRole = !role.destinationRoleId
? (await (0, create_role_1.default)({
roleName: role.name,
roleDescription: role.description,
token: destinationToken,
domain: destinationDomain,
}))
: { id: role.destinationRoleId, name: role.name, description: role.description };
const usersInRole = await (0, get_users_in_role_1.default)(sourceDomain, sourceToken, role.sourceRoleId);
for (const user of usersInRole) {
const { email, user_id: sourceUserId } = user;
if (!email || missingUsers.includes(sourceUserId))
continue;
let destinationUser = null;
try {
destinationUser = await (0, get_user_by_email_1.default)(destinationDomain, destinationToken, email);
}
catch {
missingUsers.push(sourceUserId);
continue;
}
if (!destinationUser?.user_id) {
missingUsers.push(sourceUserId);
continue;
}
const destinationUserId = destinationUser.user_id;
const currentUserRoles = await (0, get_user_roles_1.default)(destinationDomain, destinationToken, destinationUserId);
const alreadyHasRole = currentUserRoles.some((r) => r.name === role.name);
if (alreadyHasRole)
continue;
const existingRoles = userRoleMap.get(destinationUserId) || [];
userRoleMap.set(destinationUserId, [...new Set([...existingRoles, destinationRole.id])]);
}
}
catch (err) {
logger_1.default.error(`Error processing role ${role.name}:`, err);
}
}
return userRoleMap;
};
const assignRolesInBatches = async (userRoleMap, destinationDomain, destinationToken, batchSize = 10) => {
const entries = Array.from(userRoleMap.entries());
const total = entries.length;
let completed = 0;
for (let i = 0; i < total; i += batchSize) {
const batch = entries.slice(i, i + batchSize);
await Promise.all(batch.map(([userId, roleIds]) => (0, assign_roles_to_user_1.default)(destinationDomain, destinationToken, userId, roleIds)
.then(() => {
completed++;
logger_1.default.info(`Assigned roles to user ${userId} (${completed}/${total})`);
})
.catch((err) => {
completed++;
logger_1.default.error(`Failed to assign roles to user ${userId} (${completed}/${total}):`, err);
})));
}
};
const migrateUserRoles = async () => {
const { sourceDomain, destinationDomain, sourceToken, destinationToken } = await getTokens();
const selectedRoles = await getMatchingRoles(sourceDomain, destinationDomain, sourceToken, destinationToken);
const userRoleMap = await buildUserRoleMap(selectedRoles, sourceDomain, destinationDomain, sourceToken, destinationToken);
logger_1.default.info(`Assigning roles to ${userRoleMap.size} users...`);
await assignRolesInBatches(userRoleMap, destinationDomain, destinationToken);
logger_1.default.info('Migration complete.');
};
exports.migrateUserRoles = migrateUserRoles;
const setupMigrateUserRolesCommand = (program) => {
program
.command('migrate-user-roles')
.description('Migrate user roles between tenants')
.action((0, with_graceful_exit_1.default)(exports.migrateUserRoles));
};
exports.default = setupMigrateUserRolesCommand;
//# sourceMappingURL=migrate-user-roles.js.map