n8n
Version:
n8n Workflow Automation Tool
264 lines • 13.7 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var UsersController_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.UsersController = void 0;
const class_transformer_1 = require("class-transformer");
const auth_service_1 = require("../auth/auth.service");
const User_1 = require("../databases/entities/User");
const decorators_1 = require("../decorators");
const requests_1 = require("../requests");
const AuthIdentity_1 = require("../databases/entities/AuthIdentity");
const sharedCredentials_repository_1 = require("../databases/repositories/sharedCredentials.repository");
const sharedWorkflow_repository_1 = require("../databases/repositories/sharedWorkflow.repository");
const user_repository_1 = require("../databases/repositories/user.repository");
const user_service_1 = require("../services/user.service");
const middlewares_1 = require("../middlewares");
const Logger_1 = require("../Logger");
const forbidden_error_1 = require("../errors/response-errors/forbidden.error");
const not_found_error_1 = require("../errors/response-errors/not-found.error");
const bad_request_error_1 = require("../errors/response-errors/bad-request.error");
const ExternalHooks_1 = require("../ExternalHooks");
const GenericHelpers_1 = require("../GenericHelpers");
const project_repository_1 = require("../databases/repositories/project.repository");
const Project_1 = require("../databases/entities/Project");
const workflow_service_1 = require("../workflows/workflow.service");
const credentials_service_1 = require("../credentials/credentials.service");
const project_service_1 = require("../services/project.service");
const event_service_1 = require("../events/event.service");
let UsersController = UsersController_1 = class UsersController {
constructor(logger, externalHooks, sharedCredentialsRepository, sharedWorkflowRepository, userRepository, authService, userService, projectRepository, workflowService, credentialsService, projectService, eventService) {
this.logger = logger;
this.externalHooks = externalHooks;
this.sharedCredentialsRepository = sharedCredentialsRepository;
this.sharedWorkflowRepository = sharedWorkflowRepository;
this.userRepository = userRepository;
this.authService = authService;
this.userService = userService;
this.projectRepository = projectRepository;
this.workflowService = workflowService;
this.credentialsService = credentialsService;
this.projectService = projectService;
this.eventService = eventService;
}
removeSupplementaryFields(publicUsers, listQueryOptions) {
const { take, select, filter } = listQueryOptions;
if (take && select && !(select === null || select === void 0 ? void 0 : select.id)) {
for (const user of publicUsers)
delete user.id;
}
if (filter === null || filter === void 0 ? void 0 : filter.isOwner) {
for (const user of publicUsers)
delete user.role;
}
if (select) {
for (const user of publicUsers) {
delete user.isOwner;
delete user.isPending;
delete user.signInType;
}
}
return publicUsers;
}
async listUsers(req) {
const { listQueryOptions } = req;
const findManyOptions = await this.userRepository.toFindManyOptions(listQueryOptions);
const users = await this.userRepository.find(findManyOptions);
const publicUsers = await Promise.all(users.map(async (u) => await this.userService.toPublic(u, { withInviteUrl: true, inviterId: req.user.id })));
return listQueryOptions
? this.removeSupplementaryFields(publicUsers, listQueryOptions)
: publicUsers;
}
async getUserPasswordResetLink(req) {
const user = await this.userRepository.findOneOrFail({
where: { id: req.params.id },
});
if (!user) {
throw new not_found_error_1.NotFoundError('User not found');
}
if (req.user.role === 'global:admin' && user.role === 'global:owner') {
throw new forbidden_error_1.ForbiddenError('Admin cannot reset password of global owner');
}
const link = this.authService.generatePasswordResetUrl(user);
return { link };
}
async updateUserSettings(req) {
const payload = (0, class_transformer_1.plainToInstance)(requests_1.UserSettingsUpdatePayload, req.body, {
excludeExtraneousValues: true,
});
const id = req.params.id;
await this.userService.updateSettings(id, payload);
const user = await this.userRepository.findOneOrFail({
select: ['settings'],
where: { id },
});
return user.settings;
}
async deleteUser(req) {
const { id: idToDelete } = req.params;
if (req.user.id === idToDelete) {
this.logger.debug('Request to delete a user failed because it attempted to delete the requesting user', { userId: req.user.id });
throw new bad_request_error_1.BadRequestError('Cannot delete your own user');
}
const { transferId } = req.query;
const userToDelete = await this.userRepository.findOneBy({ id: idToDelete });
if (!userToDelete) {
throw new not_found_error_1.NotFoundError('Request to delete a user failed because the user to delete was not found in DB');
}
if (userToDelete.role === 'global:owner') {
throw new forbidden_error_1.ForbiddenError('Instance owner cannot be deleted.');
}
const personalProjectToDelete = await this.projectRepository.getPersonalProjectForUserOrFail(userToDelete.id);
if (transferId === personalProjectToDelete.id) {
throw new bad_request_error_1.BadRequestError('Request to delete a user failed because the user to delete and the transferee are the same user');
}
let transfereeId;
if (transferId) {
const transfereePersonalProject = await this.projectRepository.findOneBy({ id: transferId });
if (!transfereePersonalProject) {
throw new not_found_error_1.NotFoundError('Request to delete a user failed because the transferee project was not found in DB');
}
const transferee = await this.userRepository.findOneByOrFail({
projectRelations: {
projectId: transfereePersonalProject.id,
role: 'project:personalOwner',
},
});
transfereeId = transferee.id;
await this.userService.getManager().transaction(async (trx) => {
await this.workflowService.transferAll(personalProjectToDelete.id, transfereePersonalProject.id, trx);
await this.credentialsService.transferAll(personalProjectToDelete.id, transfereePersonalProject.id, trx);
});
await this.projectService.clearCredentialCanUseExternalSecretsCache(transfereePersonalProject.id);
}
const [ownedSharedWorkflows, ownedSharedCredentials] = await Promise.all([
this.sharedWorkflowRepository.find({
select: { workflowId: true },
where: { projectId: personalProjectToDelete.id, role: 'workflow:owner' },
}),
this.sharedCredentialsRepository.find({
relations: { credentials: true },
where: { projectId: personalProjectToDelete.id, role: 'credential:owner' },
}),
]);
const ownedCredentials = ownedSharedCredentials.map(({ credentials }) => credentials);
for (const { workflowId } of ownedSharedWorkflows) {
await this.workflowService.delete(userToDelete, workflowId);
}
for (const credential of ownedCredentials) {
await this.credentialsService.delete(credential);
}
await this.userService.getManager().transaction(async (trx) => {
await trx.delete(AuthIdentity_1.AuthIdentity, { userId: userToDelete.id });
await trx.delete(Project_1.Project, { id: personalProjectToDelete.id });
await trx.delete(User_1.User, { id: userToDelete.id });
});
this.eventService.emit('user-deleted', {
user: req.user,
publicApi: false,
targetUserOldStatus: userToDelete.isPending ? 'invited' : 'active',
targetUserId: idToDelete,
migrationStrategy: transferId ? 'transfer_data' : 'delete_data',
migrationUserId: transfereeId,
});
await this.externalHooks.run('user.deleted', [await this.userService.toPublic(userToDelete)]);
return { success: true };
}
async changeGlobalRole(req) {
const { NO_ADMIN_ON_OWNER, NO_USER, NO_OWNER_ON_OWNER } = UsersController_1.ERROR_MESSAGES.CHANGE_ROLE;
const payload = (0, class_transformer_1.plainToInstance)(requests_1.UserRoleChangePayload, req.body, {
excludeExtraneousValues: true,
});
await (0, GenericHelpers_1.validateEntity)(payload);
const targetUser = await this.userRepository.findOne({
where: { id: req.params.id },
});
if (targetUser === null) {
throw new not_found_error_1.NotFoundError(NO_USER);
}
if (req.user.role === 'global:admin' && targetUser.role === 'global:owner') {
throw new forbidden_error_1.ForbiddenError(NO_ADMIN_ON_OWNER);
}
if (req.user.role === 'global:owner' && targetUser.role === 'global:owner') {
throw new forbidden_error_1.ForbiddenError(NO_OWNER_ON_OWNER);
}
await this.userService.update(targetUser.id, { role: payload.newRoleName });
this.eventService.emit('user-changed-role', {
userId: req.user.id,
targetUserId: targetUser.id,
targetUserNewRole: payload.newRoleName,
publicApi: false,
});
const projects = await this.projectService.getUserOwnedOrAdminProjects(targetUser.id);
await Promise.all(projects.map(async (p) => await this.projectService.clearCredentialCanUseExternalSecretsCache(p.id)));
return { success: true };
}
};
exports.UsersController = UsersController;
UsersController.ERROR_MESSAGES = {
CHANGE_ROLE: {
NO_USER: 'Target user not found',
NO_ADMIN_ON_OWNER: 'Admin cannot change role on global owner',
NO_OWNER_ON_OWNER: 'Owner cannot change role on global owner',
},
};
__decorate([
(0, decorators_1.Get)('/', { middlewares: middlewares_1.listQueryMiddleware }),
(0, decorators_1.GlobalScope)('user:list'),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "listUsers", null);
__decorate([
(0, decorators_1.Get)('/:id/password-reset-link'),
(0, decorators_1.GlobalScope)('user:resetPassword'),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "getUserPasswordResetLink", null);
__decorate([
(0, decorators_1.Patch)('/:id/settings'),
(0, decorators_1.GlobalScope)('user:update'),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "updateUserSettings", null);
__decorate([
(0, decorators_1.Delete)('/:id'),
(0, decorators_1.GlobalScope)('user:delete'),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "deleteUser", null);
__decorate([
(0, decorators_1.Patch)('/:id/role'),
(0, decorators_1.GlobalScope)('user:changeRole'),
(0, decorators_1.Licensed)('feat:advancedPermissions'),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "changeGlobalRole", null);
exports.UsersController = UsersController = UsersController_1 = __decorate([
(0, decorators_1.RestController)('/users'),
__metadata("design:paramtypes", [Logger_1.Logger,
ExternalHooks_1.ExternalHooks,
sharedCredentials_repository_1.SharedCredentialsRepository,
sharedWorkflow_repository_1.SharedWorkflowRepository,
user_repository_1.UserRepository,
auth_service_1.AuthService,
user_service_1.UserService,
project_repository_1.ProjectRepository,
workflow_service_1.WorkflowService,
credentials_service_1.CredentialsService,
project_service_1.ProjectService,
event_service_1.EventService])
], UsersController);
//# sourceMappingURL=users.controller.js.map
;