UNPKG

n8n

Version:

n8n Workflow Automation Tool

245 lines 12 kB
"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 __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MeController = exports.isApiEnabledMiddleware = exports.API_KEY_PREFIX = void 0; const validator_1 = __importDefault(require("validator")); const class_transformer_1 = require("class-transformer"); const crypto_1 = require("crypto"); const auth_service_1 = require("../auth/auth.service"); const decorators_1 = require("../decorators"); const password_utility_1 = require("../services/password.utility"); const GenericHelpers_1 = require("../GenericHelpers"); const requests_1 = require("../requests"); const samlHelpers_1 = require("../sso/saml/samlHelpers"); const user_service_1 = require("../services/user.service"); const Logger_1 = require("../Logger"); const ExternalHooks_1 = require("../ExternalHooks"); const bad_request_error_1 = require("../errors/response-errors/bad-request.error"); const user_repository_1 = require("../databases/repositories/user.repository"); const PublicApi_1 = require("../PublicApi"); const event_service_1 = require("../events/event.service"); const mfa_service_1 = require("../Mfa/mfa.service"); const invalid_mfa_code_error_1 = require("../errors/response-errors/invalid-mfa-code.error"); exports.API_KEY_PREFIX = 'n8n_api_'; const isApiEnabledMiddleware = (_, res, next) => { if ((0, PublicApi_1.isApiEnabled)()) { next(); } else { res.status(404).end(); } }; exports.isApiEnabledMiddleware = isApiEnabledMiddleware; let MeController = class MeController { constructor(logger, externalHooks, authService, userService, passwordUtility, userRepository, eventService, mfaService) { this.logger = logger; this.externalHooks = externalHooks; this.authService = authService; this.userService = userService; this.passwordUtility = passwordUtility; this.userRepository = userRepository; this.eventService = eventService; this.mfaService = mfaService; } async updateCurrentUser(req, res) { const { id: userId, email: currentEmail } = req.user; const payload = (0, class_transformer_1.plainToInstance)(requests_1.UserUpdatePayload, req.body, { excludeExtraneousValues: true }); const { email } = payload; if (!email) { this.logger.debug('Request to update user email failed because of missing email in payload', { userId, payload, }); throw new bad_request_error_1.BadRequestError('Email is mandatory'); } if (!validator_1.default.isEmail(email)) { this.logger.debug('Request to update user email failed because of invalid email in payload', { userId, invalidEmail: email, }); throw new bad_request_error_1.BadRequestError('Invalid email address'); } await (0, GenericHelpers_1.validateEntity)(payload); if ((0, samlHelpers_1.isSamlLicensedAndEnabled)()) { if (email !== currentEmail) { this.logger.debug('Request to update user failed because SAML user may not change their email', { userId, payload, }); throw new bad_request_error_1.BadRequestError('SAML user may not change their email'); } } await this.externalHooks.run('user.profile.beforeUpdate', [userId, currentEmail, payload]); const preUpdateUser = await this.userRepository.findOneByOrFail({ id: userId }); await this.userService.update(userId, payload); const user = await this.userRepository.findOneOrFail({ where: { id: userId }, }); this.logger.info('User updated successfully', { userId }); this.authService.issueCookie(res, user, req.browserId); const fieldsChanged = Object.keys(payload).filter((key) => payload[key] !== preUpdateUser[key]); this.eventService.emit('user-updated', { user, fieldsChanged }); const publicUser = await this.userService.toPublic(user); await this.externalHooks.run('user.profile.update', [currentEmail, publicUser]); return publicUser; } async updatePassword(req, res) { const { user } = req; const { currentPassword, newPassword, mfaCode } = req.body; if ((0, samlHelpers_1.isSamlLicensedAndEnabled)()) { this.logger.debug('Attempted to change password for user, while SAML is enabled', { userId: user.id, }); throw new bad_request_error_1.BadRequestError('With SAML enabled, users need to use their SAML provider to change passwords'); } if (typeof currentPassword !== 'string' || typeof newPassword !== 'string') { throw new bad_request_error_1.BadRequestError('Invalid payload.'); } if (!user.password) { throw new bad_request_error_1.BadRequestError('Requesting user not set up.'); } const isCurrentPwCorrect = await this.passwordUtility.compare(currentPassword, user.password); if (!isCurrentPwCorrect) { throw new bad_request_error_1.BadRequestError('Provided current password is incorrect.'); } const validPassword = this.passwordUtility.validate(newPassword); if (user.mfaEnabled) { if (typeof mfaCode !== 'string') { throw new bad_request_error_1.BadRequestError('Two-factor code is required to change password.'); } const isMfaTokenValid = await this.mfaService.validateMfa(user.id, mfaCode, undefined); if (!isMfaTokenValid) { throw new invalid_mfa_code_error_1.InvalidMfaCodeError(); } } user.password = await this.passwordUtility.hash(validPassword); const updatedUser = await this.userRepository.save(user, { transaction: false }); this.logger.info('Password updated successfully', { userId: user.id }); this.authService.issueCookie(res, updatedUser, req.browserId); this.eventService.emit('user-updated', { user: updatedUser, fieldsChanged: ['password'] }); await this.externalHooks.run('user.password.update', [updatedUser.email, updatedUser.password]); return { success: true }; } async storeSurveyAnswers(req) { const { body: personalizationAnswers } = req; if (!personalizationAnswers) { this.logger.debug('Request to store user personalization survey failed because of empty payload', { userId: req.user.id, }); throw new bad_request_error_1.BadRequestError('Personalization answers are mandatory'); } await (0, GenericHelpers_1.validateRecordNoXss)(personalizationAnswers); await this.userRepository.save({ id: req.user.id, personalizationAnswers, }, { transaction: false }); this.logger.info('User survey updated successfully', { userId: req.user.id }); this.eventService.emit('user-submitted-personalization-survey', { userId: req.user.id, answers: personalizationAnswers, }); return { success: true }; } async createAPIKey(req) { const apiKey = `n8n_api_${(0, crypto_1.randomBytes)(40).toString('hex')}`; await this.userService.update(req.user.id, { apiKey }); this.eventService.emit('public-api-key-created', { user: req.user, publicApi: false }); return { apiKey }; } async getAPIKey(req) { const apiKey = this.redactApiKey(req.user.apiKey); return { apiKey }; } async deleteAPIKey(req) { await this.userService.update(req.user.id, { apiKey: null }); this.eventService.emit('public-api-key-deleted', { user: req.user, publicApi: false }); return { success: true }; } async updateCurrentUserSettings(req) { const payload = (0, class_transformer_1.plainToInstance)(requests_1.UserSettingsUpdatePayload, req.body, { excludeExtraneousValues: true, }); await (0, GenericHelpers_1.validateEntity)(payload); const { id } = req.user; await this.userService.updateSettings(id, payload); const user = await this.userRepository.findOneOrFail({ select: ['settings'], where: { id }, }); return user.settings; } redactApiKey(apiKey) { if (!apiKey) return; const keepLength = 5; return (exports.API_KEY_PREFIX + apiKey.slice(exports.API_KEY_PREFIX.length, exports.API_KEY_PREFIX.length + keepLength) + '*'.repeat(apiKey.length - exports.API_KEY_PREFIX.length - keepLength)); } }; exports.MeController = MeController; __decorate([ (0, decorators_1.Patch)('/'), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], MeController.prototype, "updateCurrentUser", null); __decorate([ (0, decorators_1.Patch)('/password', { rateLimit: true }), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], MeController.prototype, "updatePassword", null); __decorate([ (0, decorators_1.Post)('/survey'), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], MeController.prototype, "storeSurveyAnswers", null); __decorate([ (0, decorators_1.Post)('/api-key', { middlewares: [exports.isApiEnabledMiddleware] }), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], MeController.prototype, "createAPIKey", null); __decorate([ (0, decorators_1.Get)('/api-key', { middlewares: [exports.isApiEnabledMiddleware] }), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], MeController.prototype, "getAPIKey", null); __decorate([ (0, decorators_1.Delete)('/api-key', { middlewares: [exports.isApiEnabledMiddleware] }), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], MeController.prototype, "deleteAPIKey", null); __decorate([ (0, decorators_1.Patch)('/settings'), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], MeController.prototype, "updateCurrentUserSettings", null); exports.MeController = MeController = __decorate([ (0, decorators_1.RestController)('/me'), __metadata("design:paramtypes", [Logger_1.Logger, ExternalHooks_1.ExternalHooks, auth_service_1.AuthService, user_service_1.UserService, password_utility_1.PasswordUtility, user_repository_1.UserRepository, event_service_1.EventService, mfa_service_1.MfaService]) ], MeController); //# sourceMappingURL=me.controller.js.map