n8n
Version:
n8n Workflow Automation Tool
262 lines • 13.7 kB
JavaScript
"use strict";
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 __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var UsersController_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.UsersController = void 0;
const api_types_1 = require("@n8n/api-types");
const n8n_core_1 = require("n8n-core");
const auth_service_1 = require("../auth/auth.service");
const credentials_service_1 = require("../credentials/credentials.service");
const auth_identity_1 = require("../databases/entities/auth-identity");
const project_1 = require("../databases/entities/project");
const user_1 = require("../databases/entities/user");
const project_repository_1 = require("../databases/repositories/project.repository");
const shared_credentials_repository_1 = require("../databases/repositories/shared-credentials.repository");
const shared_workflow_repository_1 = require("../databases/repositories/shared-workflow.repository");
const user_repository_1 = require("../databases/repositories/user.repository");
const decorators_1 = require("../decorators");
const bad_request_error_1 = require("../errors/response-errors/bad-request.error");
const forbidden_error_1 = require("../errors/response-errors/forbidden.error");
const not_found_error_1 = require("../errors/response-errors/not-found.error");
const event_service_1 = require("../events/event.service");
const external_hooks_1 = require("../external-hooks");
const middlewares_1 = require("../middlewares");
const folder_service_1 = require("../services/folder.service");
const project_service_ee_1 = require("../services/project.service.ee");
const user_service_1 = require("../services/user.service");
const workflow_service_1 = require("../workflows/workflow.service");
let UsersController = UsersController_1 = class UsersController {
constructor(logger, externalHooks, sharedCredentialsRepository, sharedWorkflowRepository, userRepository, authService, userService, projectRepository, workflowService, credentialsService, projectService, eventService, folderService) {
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;
this.folderService = folderService;
}
removeSupplementaryFields(publicUsers, listQueryOptions) {
const { take, select, filter } = listQueryOptions;
if (take && select && !select?.id) {
for (const user of publicUsers)
delete user.id;
}
if (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, _res, payload, 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 transfereeProject = await this.projectRepository.findOneBy({ id: transferId });
if (!transfereeProject) {
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: transfereeProject.id,
},
});
transfereeId = transferee.id;
await this.userService.getManager().transaction(async (trx) => {
await this.workflowService.transferAll(personalProjectToDelete.id, transfereeProject.id, trx);
await this.credentialsService.transferAll(personalProjectToDelete.id, transfereeProject.id, trx);
await this.folderService.transferAllFoldersToProject(personalProjectToDelete.id, transfereeProject.id, trx);
});
await this.projectService.clearCredentialCanUseExternalSecretsCache(transfereeProject.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(userToDelete, credential.id);
}
await this.userService.getManager().transaction(async (trx) => {
await trx.delete(auth_identity_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, _, payload, id) {
const { NO_ADMIN_ON_OWNER, NO_USER, NO_OWNER_ON_OWNER } = UsersController_1.ERROR_MESSAGES.CHANGE_ROLE;
const targetUser = await this.userRepository.findOneBy({ 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'),
__param(2, decorators_1.Body),
__param(3, (0, decorators_1.Param)('id')),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object, api_types_1.SettingsUpdateRequestDto, String]),
__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'),
__param(2, decorators_1.Body),
__param(3, (0, decorators_1.Param)('id')),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object, api_types_1.RoleChangeRequestDto, String]),
__metadata("design:returntype", Promise)
], UsersController.prototype, "changeGlobalRole", null);
exports.UsersController = UsersController = UsersController_1 = __decorate([
(0, decorators_1.RestController)('/users'),
__metadata("design:paramtypes", [n8n_core_1.Logger,
external_hooks_1.ExternalHooks,
shared_credentials_repository_1.SharedCredentialsRepository,
shared_workflow_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_ee_1.ProjectService,
event_service_1.EventService,
folder_service_1.FolderService])
], UsersController);
//# sourceMappingURL=users.controller.js.map