@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
JavaScript
"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,
});
}
};