Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 169x 169x 1x 1x 172x 172x 172x 172x 170x 170x 170x 170x 170x 170x 2x 2x 1x 1x 1x 1x 1x 1x | import debug from 'debug';
import {User, UserDto, ProfilePic, UserRequest} from '@models';
import ModelToDtoConverter from '@util/model-to-dto-converter';
import {UsernameAlreadyExistsError} from '@errors';
import {UniqueConstraintError} from 'sequelize';
import {convertUserToJwtPayload} from '@app/routes/auth/jwt/jwt-util';
import generatePic from '@util/generate-profile-pic';
import config from '@config';
import {Router, RequestHandler} from 'express';
import nodemailer from 'nodemailer';
import hbs from 'nodemailer-express-handlebars-plaintext-inline-ccs';
import exhbs from 'express-handlebars';
import {Options} from 'nodemailer/lib/sendmail-transport';
import db from '@db';
/**
* Log method for normal debug logging
*/
const log = debug('group-car:sign-up:controller:log');
/**
* Log method for error logging
*/
const error = debug('group-car:sign-up:controller:error');
const picDim = config.user.pb.dimensions;
/**
* This controller decides if the request should be handled by
* {@link signUpUserRequestHandler} or {@link signUpController}.
* @param req - Request
* @param res - Response
* @param next - Next
*/
export const signUpSwitchController: RequestHandler = async (
req,
res,
next,
) => {
/*
* Depending on the mode, either forward arguments
* to signUpUserRequestHandler
* or signUpController
*/
Iif (config.user.signUpThroughRequest) {
// Check if a user with that username already exists
await signUpUserRequestHandler(req, res, next);
} else {
await signUpController(req, res, next);
}
};
/**
* Handles the sign up request if the server
* doesn't allow direct user creation.
* Instead this handler will create a {@link UserRequest}
* and send an email to the configured receiver.
* @param req - Request
* @param res - Response
* @param next - Next
*/
export const signUpUserRequestHandler: RequestHandler = async (
req,
res,
next,
) => {
const user = await User.findByUsername(req.body.username);
let profilePictureBuffer: Buffer;
if (user === null) {
profilePictureBuffer = await generatePic(
picDim,
req.body.username,
req.body.offset ?? 0,
);
} else {
throw new UsernameAlreadyExistsError(req.body.username);
}
// Store request
const userRequest = await UserRequest.create({
username: req.body.username,
password: req.body.password,
profilePic: profilePictureBuffer,
email: req.body.email,
});
// Send email to admin
try {
const transporter = nodemailer.createTransport(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
config.mail.accountRequest?.options as any);
transporter.use('compile', hbs({
viewEngine: exhbs.create({
layoutsDir: 'app/views/layouts',
partialsDir: 'app/views/partials',
}),
templatesDir: 'app/views',
plaintextOptions: {
uppercaseHeadings: false,
},
viewPath: 'app/views',
}));
await transporter.sendMail({
from: '"my-group-car.de" <mygroupcar@gmail.com',
to: config.mail.accountRequest?.receiver,
subject: `Account creation request for ${req.body.username}`,
template: 'request-email',
context: {
id: userRequest.id,
username: userRequest.username,
timestamp: new Date().toLocaleString(),
serverType: process.env.SERVER_TYPE,
},
} as unknown as Options);
} catch (e) {
// Only report error.
// The actual request was done, just sending the email failed.
error('Could not send the email: %o', e);
}
res.status(202)
.send({message: 'Request was sent successfully. ' +
'You will be notified if the request was accepted'});
};
/**
* Signs the user up.
*
* Creates a new user with the given properties.
* @param req - Http request, information about user in `req.body`
* @param res - Http response
* @param _next - The next request handler
*/
export const signUpController: RequestHandler = async (req, res, _next) => {
const transaction = await db.transaction();
log('Create new user for "%s"', req.body.username);
try {
const user = await User.create({
username: req.body.username,
email: req.body.email,
password: req.body.password,
}, {transaction});
const profilePictureBuffer = await generatePic(
picDim,
req.body.username,
req.body.offset ?? 0,
);
await ProfilePic.create({
data: profilePictureBuffer,
userId: user.id,
}, {transaction});
// If everything executing successfully, commit transaction
await transaction.commit();
log('User "%s" successfully created', req.body.username);
res.setJwtToken(convertUserToJwtPayload(user), user.username);
res.status(201).send(ModelToDtoConverter
.convert<UserDto>(user.get({plain: true}), UserDto));
} catch (err) {
await transaction.rollback();
// Handle unique constraints error differently
if (err instanceof UniqueConstraintError) {
error('Couldn\'t create user "%s", because username already exists',
req.body.username);
throw new UsernameAlreadyExistsError(req.body.username);
} else {
// Rethrow
error('Couldn\'t create user "%s"', req.body.username);
throw err;
}
}
};
const signUpRouter = Router().use(
'',
signUpSwitchController,
);
export default signUpRouter;
|