UNPKG

acebase-server

Version:

AceBase realtime database server (webserver endpoint to allow remote connections)

143 lines 7.28 kB
"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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.addRoute = exports.SignupError = void 0; const user_1 = require("../schema/user"); const validate_1 = require("../shared/validate"); const password_1 = require("../shared/password"); const acebase_core_1 = require("acebase-core"); const tokens_1 = require("../shared/tokens"); const error_1 = require("../shared/error"); const admin_1 = require("../shared/admin"); class SignupError extends Error { constructor(code, message) { super(message); this.code = code; } } exports.SignupError = SignupError; const addRoute = (env) => { env.router.post(`/auth/${env.db.name}/signup`, (req, res) => __awaiter(void 0, void 0, void 0, function* () { var _a, _b, _c, _d, _e, _f, _g, _h; const LOG_ACTION = 'auth.signup'; const LOG_DETAILS = { ip: req.ip, uid: (_b = (_a = req.user) === null || _a === void 0 ? void 0 : _a.uid) !== null && _b !== void 0 ? _b : null }; if (!env.config.auth.allowUserSignup && !(0, admin_1.isAdmin)(req.user)) { env.log.error(LOG_ACTION, 'user_signup_disabled', LOG_DETAILS); return (0, error_1.sendUnauthorizedError)(res, 'admin_only', 'Only admins are allowed to create users'); } // Create user if it doesn't exist yet. // TODO: Rate-limit nr of signups per IP to prevent abuse const details = req.body; if (typeof details.display_name === 'string' && typeof details.displayName !== 'string') { // Allow display_name to be sent also (which is used in update endpoint) details.displayName = details.display_name; } // Check if sent details are ok let err; if (!details.username && !details.email) { err = { code: 'missing_details', message: 'No username or email provided' }; } else if (details.email && !(0, validate_1.isValidEmail)(details.email)) { err = validate_1.invalidEmailError; } else if (details.email && !(yield (0, validate_1.isValidNewEmailAddress)(env.authRef, details.email))) { err = validate_1.emailExistsError; } else if (details.username && !(0, validate_1.isValidUsername)(details.username)) { err = validate_1.invalidUsernameError; } else if (details.username && !(yield (0, validate_1.isValidNewUsername)(env.authRef, details.username))) { err = validate_1.usernameExistsError; } else if (!(0, validate_1.isValidDisplayName)(details.displayName)) { err = validate_1.invalidDisplayNameError; } else if (!(0, validate_1.isValidPassword)(details.password)) { err = validate_1.invalidPasswordError; } else if (!(0, validate_1.isValidSettings)(details.settings)) { err = validate_1.invalidSettingsError; } else if (details.picture && !(0, validate_1.isValidPicture)(details.picture)) { err = validate_1.invalidPictureError; } if (err === validate_1.emailExistsError || err === validate_1.usernameExistsError) { env.log.error(LOG_ACTION, 'conflict', Object.assign(Object.assign({}, LOG_DETAILS), { username: details.username, email: details.email })); res.statusCode = 409; // conflict return res.send(validate_1.emailOrUsernameExistsError); } else if (err) { // Log failure env.log.error(LOG_ACTION, (_c = err.code) !== null && _c !== void 0 ? _c : 'unexpected', LOG_DETAILS); res.statusCode = 422; // Unprocessable Entity return res.send(err); } try { // Ok, create user const pwd = (0, password_1.createPasswordHash)(details.password); const user = { uid: null, username: (_d = details.username) !== null && _d !== void 0 ? _d : null, email: (_e = details.email) !== null && _e !== void 0 ? _e : null, email_verified: false, display_name: details.displayName, password: pwd.hash, password_salt: pwd.salt, created: new Date(), created_ip: req.ip, access_token: acebase_core_1.ID.generate(), access_token_created: new Date(), last_signin: new Date(), last_signin_ip: req.ip, picture: (_f = details.picture) !== null && _f !== void 0 ? _f : null, settings: (_g = details.settings) !== null && _g !== void 0 ? _g : {}, }; const userRef = yield env.authRef.push(user); user.uid = userRef.key; LOG_DETAILS.uid = user.uid; // Log success env.log.event(LOG_ACTION, LOG_DETAILS); // Cache the user env.authCache.set(user.uid, user); // Request welcome e-mail to be sent const request = { type: 'user_signup', user: { uid: user.uid, username: user.username, email: user.email, displayName: user.display_name, settings: user.settings, }, date: user.created, ip: user.created_ip, provider: 'acebase', activationCode: (0, tokens_1.createSignedPublicToken)({ uid: user.uid }, env.tokenSalt), emailVerified: false, }; (_h = env.config.email) === null || _h === void 0 ? void 0 : _h.send(request).catch(err => { env.log.error(LOG_ACTION + '.email', 'unexpected', Object.assign(Object.assign({}, LOG_DETAILS), { request }), err); }); // Return the positive news res.send({ access_token: (0, admin_1.isAdmin)(req.user) ? '' : (0, tokens_1.createPublicAccessToken)(user.uid, req.ip, user.access_token, env.tokenSalt), user: (0, user_1.getPublicAccountDetails)(user), }); } catch (err) { env.log.error(LOG_ACTION, 'unexpected', Object.assign(Object.assign({}, LOG_DETAILS), { message: err instanceof Error ? err.message : err.toString(), username: details.username, email: details.email })); (0, error_1.sendUnexpectedError)(res, err); } })); }; exports.addRoute = addRoute; exports.default = exports.addRoute; //# sourceMappingURL=auth-signup.js.map