api: activate user account
Pedro Lucas Porcellis porcellis@eletrotupi.com · 4 months ago
e6b6493185741dd24cf765760d87180cb7e1f6a1 Browse filesParents
6d8c0a7Changed files
5
Additions
+26
Deletions
-10
api/src/controllers/auth.ts
1 1
import { Request, Response, NextFunction } from 'express';
2 2
import {
3 3
login,
4 4
generateToken,
5 5
requestPasswordReset,
12 12
} from '@app/lib/jwt';
13 13
14 14
import {
15 15
findUserByEmail,
16 16
findUserById,
17 +
findUserByActivationCode
17 18
} from '@app/services/user.service'
18 19
19 20
import {
20 21
LoginSchema,
21 22
PasswordResetSchema,
33 34
errors: parsed.error!.issues
34 35
});
35 36
}
36 37
37 38
const { user, token } = await login(parsed.data);
39 +
40 +
if (!user.active) {
41 +
// TODO: generate a new activation code and send an email
42 +
// if the code has expired
43 +
}
38 44
39 45
return res.json({
40 46
token,
41 47
user
42 48
});
134 140
return res.status(400).json({
135 141
errors: parsed.error!.issues
136 142
});
137 143
}
138 144
139 -
const user = await findUserById(parsed.data.userId);
145 +
const user = await findUserByActivationCode(String(parsed.data.code));
140 146
141 147
if (!user) {
142 148
return res.status(403).json({ error: "Usuario não encontrado" })
143 149
}
144 150
145 -
const result = await activateUser(user, parsed.data);
146 -
return res.status(200).json(result);
151 +
const result = await activateUser(user);
152 +
153 +
return res.status(200).json({
154 +
user: result
155 +
});
147 156
} catch (err: any) {
148 157
next(err);
149 158
}
150 159
}
151 160
};
api/src/controllers/users.ts
1 1
import { Request, Response, NextFunction } from 'express';
2 2
import {
3 3
generateToken
4 4
} from '@app/services/auth.service';
5 5
48 48
}
49 49
50 50
const user = await createUser(parsed.data);
51 51
const jwtToken = generateToken(user.id, user.email);
52 52
53 -
const code = [...Array(6)].map(() => crypto.randomInt(100))
54 -
.join(" ");
53 +
const code = [...Array(6)].map(() => crypto.randomInt(9))
54 +
.join("");
55 55
56 56
const expiresAt = addMinutes(new Date(), 5);
57 57
await storeActivationCode(user.id, code, expiresAt);
58 58
59 59
const mailQueue = getQueue('mail');
162 162
return res.json({
163 163
user
164 164
})
165 165
}
166 166
}
api/src/schemas/auth.schema.ts
1 1
import { z } from 'zod';
2 2
3 3
export const LoginSchema = z.object({
4 4
email: z.string().email(),
5 5
password: z.string().min(1)
13 13
token: z.string(),
14 14
newPassword: z.string().min(6)
15 15
});
16 16
17 17
export const ActivateUserSchema = z.object({
18 -
userId: z.number(),
19 -
code: z.number().max(6)
18 +
code: z.number()
20 19
});
21 20
22 21
export type LoginInput = z.infer<typeof LoginSchema>;
23 22
export type PasswordResetRequestInput = z.infer<typeof PasswordResetRequestSchema>;
24 23
export type PasswordResetInput = z.infer<typeof PasswordResetSchema>;
25 24
export type ActivateUserInput = z.infer<typeof ActivateUserSchema>;
api/src/services/auth.service.ts
1 1
import { prisma } from '@app/lib/prisma';
2 2
import { User } from '@prisma/client';
3 3
import bcrypt from "bcryptjs";
4 4
5 5
import {
29 29
class InvalidOrExpiredTokenError extends Error {
30 30
constructor() { super('Invalid or Expired reset token') }
31 31
}
32 32
33 33
export const login = async({ email, password }: LoginInput) => {
34 -
const user = await findUserByEmail(email);
34 +
const user = await findUserByEmail(email)!;
35 35
36 36
if (!user || !bcrypt.compareSync(password, user.encryptedPassword)) {
37 37
throw new InvalidCredentialsError();
38 38
}
39 39
102 102
103 103
export const generateToken = (userId: number, email: string) => {
104 104
return createJWT(userId, email);
105 105
};
106 106
107 -
export const activateUser = async(user: User, input: ActivateUserInput): Promise<User> => {
107 +
export const activateUser = async(user: User): Promise<User> => {
108 108
return await prisma.user.update({
109 109
where: {
110 110
id: user.id
111 111
},
112 112
data: {
113 -
isActive: true,
113 +
active: true,
114 114
activationCode: null,
115 115
activationCodeExpiresAt: null
116 116
}
117 117
});
118 118
}
126 126
activationCode: code,
127 127
activationCodeExpiresAt: expiresAt
128 128
}
129 129
})
130 130
}
api/src/services/user.service.ts
1 1
import { prisma } from '@app/lib/prisma';
2 2
import { User } from '@prisma/client';
3 3
import bcrypt from 'bcryptjs';
4 4
5 5
import {
32 32
email
33 33
}
34 34
});
35 35
};
36 36
37 +
export const findUserByActivationCode = async(code: string): Promise<User | null> => {
38 +
return await prisma.user.findFirst({
39 +
where: {
40 +
activationCode: code
41 +
}
42 +
});
43 +
}
44 +
37 45
export const updateUser = async (input: UpdateUserInput): Promise<User> => {
38 46
const { password, ...data } = input;
39 47
40 48
const updateData = {
41 49
...data,
47 55
id: input.id
48 56
},
49 57
data: updateData
50 58
})
51 59
}