UNPKG

@replyke/express

Version:

Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.

116 lines (115 loc) 5.25 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const jsonwebtoken_1 = __importDefault(require("jsonwebtoken")); const authentication_1 = require("../../../helpers/authentication"); const models_1 = require("../../../models"); const models_2 = require("../../../models"); const validateUserCreated_1 = __importDefault(require("../../../helpers/webhooks/validateUserCreated")); const reduceAuthenticatedUserDetails_1 = __importDefault(require("../../../helpers/reduceAuthenticatedUserDetails")); const config_1 = require("../../../config"); exports.default = async (req, res) => { const { email, password, name, username, avatar, bio, location, birthdate, metadata, secureMetadata, } = req.body; const projectId = req.project.id; const { sequelize, refreshTokenSecret } = (0, config_1.getCoreConfig)(); // Validate required fields if (!email || !password) { res.status(400).json({ error: "Missing required fields", code: "auth/missing-fields", }); return; } try { // Generate salt and hash for the new password const { salt, hash } = (0, authentication_1.generateSaltAndHash)(password); const newUserData = { projectId, role: "visitor", email: email.toLowerCase(), name, username: username.toLowerCase(), avatar, bio, location: location ? { type: "Point", coordinates: [location.longitude, location.latitude], } : undefined, birthdate, metadata, secureMetadata, }; const { projectId: _, ...restOfUserData } = newUserData; // Call the webhook to validate the user creation await (0, validateUserCreated_1.default)(req, res, { projectId, data: restOfUserData }); // Wrap the whole flow in a transaction to ensure consistency const result = await sequelize.transaction(async (t) => { // Create a new user const user = (await models_1.User.create({ ...newUserData, hash, salt, }, { transaction: t } // Ensure this is part of the transaction )); // Create an empty Token entry (UUID will be generated here) const refreshTokenEntry = (await models_2.Token.create({ userId: user.id, projectId, }, { transaction: t } // Ensure this is part of the transaction )); // Generate the JWT for the refresh token const refreshTokenJWT = jsonwebtoken_1.default.sign({ sub: user.id, // Subject, representing the user ID projectId, // Project ID, indicating which project this token is tied to aud: "replyke.com", // Audience, your authentication service iss: "replyke.com", // Issuer, your service jti: refreshTokenEntry.id, // Use the token ID as the JWT ID }, refreshTokenSecret, { expiresIn: "30d" } // Refresh token expires in 30 days ); // Update the Token with the generated JWT and save it refreshTokenEntry.refreshToken = refreshTokenJWT; await refreshTokenEntry.save({ transaction: t }); // Ensure this is part of the transaction // Generate the JWT for the access token const accessTokenJWT = jsonwebtoken_1.default.sign({ sub: user.id, // Subject, representing the user ID projectId, // Project ID, indicating which project this token is tied to role: "user", // User role aud: "replyke.com", // Audience, your authentication service iss: "replyke.com", // Issuer, your service }, process.env.ACCESS_TOKEN_SECRET, { expiresIn: "30m" } // Access token expiry ); return { user, refreshTokenJWT, accessTokenJWT }; // Return both user and refreshToken if needed }); // Access user and refreshToken from the transaction result if needed const { user, refreshTokenJWT, accessTokenJWT } = result; res.cookie("replyke-refresh-jwt", refreshTokenJWT, { httpOnly: true, sameSite: "none", secure: true, maxAge: 30 * 24 * 60 * 60 * 1000, path: "/", }); const reducedAuthenticatedUser = (0, reduceAuthenticatedUserDetails_1.default)({ ...user, suspensions: [], }); res.status(201).json({ success: true, accessToken: accessTokenJWT, refreshToken: refreshTokenJWT, user: reducedAuthenticatedUser, }); } catch (err) { console.error("Error signing user up: ", err); res.status(500).json({ error: "Internal server error", code: "auth/server-error", details: err.message, }); } };