|
3 | 3 | const { v4: uuidv4 } = require('uuid'); |
4 | 4 | const invariant = require('tiny-invariant'); |
5 | 5 |
|
6 | | -const { userTable, passwordTable } = require('../../schema/schema'); |
| 6 | +const { userTable, passwordTable, profileTable } = require('../../schema/schema'); |
7 | 7 | const { db } = require('../drizzle'); |
8 | 8 | const { createProfile } = require('../profile/profile'); |
9 | 9 | const { eq } = require('drizzle-orm'); |
10 | 10 | const ModelError = require('../modelError'); |
11 | 11 | const { checkPassword, validatePassword, passwordHasher } = require('../password/utils'); |
| 12 | +const IsEmail = require('isemail'); |
| 13 | + |
| 14 | +const userNameRequirementsText = 'Parameter name must consist of at least 3 and up to 40 alphanumerics (a-zA-Z0-9), dot (.), dash (-), underscore (_) and spaces.'; |
| 15 | +const nameValidRegex = |
| 16 | + /^[^~`!@#$%^&*()+=£€{}[\]|\\:;"'<>,?/\n\r\t\s][^~`!@#$%^&*()+=£€{}[\]|\\:;"'<>,?/\n\r\t]{1,39}[^~`!@#$%^&*()+=£€{}[\]|\\:;"'<>,?/\n\r\t\s]$/; |
12 | 17 |
|
13 | 18 | const validateField = function validateField (field, expr, msg) { |
14 | 19 | try { |
@@ -53,29 +58,41 @@ const findUserByEmailAndRole = async function findUserByEmailAndRole ({ |
53 | 58 | const createUser = async function createUser (name, email, password, language) { |
54 | 59 |
|
55 | 60 | validateField('name', name.length > 0, 'Name is required'); |
| 61 | + validateField( |
| 62 | + 'name', |
| 63 | + name.length > 3 && name.length < 40, |
| 64 | + userNameRequirementsText |
| 65 | + ); |
| 66 | + validateField('name', nameValidRegex.test(name), userNameRequirementsText); |
| 67 | + validateField('email', IsEmail.validate(email), 'Email is required'); |
56 | 68 | validateField('password', validatePassword(password), 'Password must be at least 8 characters'); |
57 | 69 |
|
58 | | - try { |
59 | | - // TODO: Wrap this in a transaction |
60 | | - const hashedPassword = await passwordHasher(password); |
61 | | - const user = await db |
| 70 | + const hashedPassword = await passwordHasher(password); |
| 71 | + |
| 72 | + const user = await db.transaction(async (tx) => { |
| 73 | + const user = await tx |
62 | 74 | .insert(userTable) |
63 | 75 | .values({ name, email, language }) |
64 | 76 | .returning(); |
65 | 77 |
|
66 | | - await db.insert(passwordTable).values({ |
| 78 | + await tx.insert(passwordTable).values({ |
67 | 79 | hash: hashedPassword, |
68 | 80 | userId: user[0].id |
69 | 81 | }); |
70 | 82 |
|
71 | | - await createProfile(user[0]); |
| 83 | + await tx.insert(profileTable).values({ |
| 84 | + username: name, |
| 85 | + public: false, |
| 86 | + userId: user[0].id |
| 87 | + }); |
72 | 88 |
|
73 | | - // TODO: Only return specific fields |
74 | 89 | return user[0]; |
75 | | - } catch (error) { |
76 | | - console.log(error); |
77 | | - throw error; |
78 | | - } |
| 90 | + }); |
| 91 | + |
| 92 | + // Delete not needed properties |
| 93 | + delete user.emailConfirmationToken; |
| 94 | + |
| 95 | + return user; |
79 | 96 | }; |
80 | 97 |
|
81 | 98 | const destroyUser = async function destroyUser (user) { |
|
0 commit comments