Skip to content

Commit c346b9b

Browse files
committed
work on signup and password recovery, change build script
1 parent b1da9f5 commit c346b9b

File tree

7 files changed

+98
-79
lines changed

7 files changed

+98
-79
lines changed

app/components/auth/signUp.scheme.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,8 @@ export const signUpScheme: FastifySchema = {
3434

3535

3636
export const signUpConfirmScheme: FastifySchema = {
37-
params: {
38-
type: 'object',
39-
required: ['code'],
40-
properties: {
41-
code: {type: 'string'}
42-
},
37+
querystring: {
38+
code: {type: 'string'}
4339
},
4440
response: {
4541
200: {

app/components/auth/signUp.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {createTransport} from 'nodemailer';
55
import {SMTPOpt} from '@/assist/mail';
66
import {randomBytes} from 'crypto';
77
import {env} from '@/envConfig';
8+
import * as crypto from 'crypto';
89

910
interface IBody {
1011
email: string
@@ -24,13 +25,15 @@ export const signUp = async (server: FastifyInstance) => {
2425

2526
if (rowCount) {
2627
const transporter = createTransport(SMTPOpt);
27-
const link = `http://${env.nodeEnv === 'dev' ? 'localhost:3000' : '51.15.71.195'}/confirm-email/` + linkCode;
28+
const link = `http://${env.nodeEnv === 'development' ? 'localhost:3000' : '51.15.71.195'}/signup/confirm/?code=${linkCode}`;
2829
const mailOptions = {
2930
to: email,
3031
subject: 'Confirmation of registration',
3132
html: `<h3>Hello.</h3> <p>Please click on the <a href=${link}><b>link</b></a> to confirm your registration.</p>`
3233
};
34+
3335
const sent = await transporter.sendMail(mailOptions);
36+
3437
if (sent) {
3538
return reply.status(201).send('An email has been sent to your email address');
3639
} else {
@@ -43,17 +46,17 @@ export const signUp = async (server: FastifyInstance) => {
4346
);
4447
};
4548

46-
interface IParams {
49+
interface IQuerystring {
4750
code: string
4851
}
4952
export const signUpConfirm = async (server: FastifyInstance) => {
50-
server.get<{Params: IParams}>(
51-
'/confirm-email/:code',
53+
server.get<{Querystring: IQuerystring}>(
54+
'/signup/confirm/',
5255
{schema: signUpConfirmScheme},
5356
async (req, reply) => {
54-
const {code} = req.params;
55-
const {rowCount} = await server.pg.query('UPDATE root.users SET confirmed = true, code = NULL WHERE code = $1 AND confirmed = false', [code]);
57+
const {code} = req.query;
5658

59+
const {rowCount} = await server.pg.query('UPDATE root.users SET confirmed = true, code = NULL WHERE code = $1 AND confirmed = false', [code]);
5760
if (rowCount) {
5861
reply.type('text/html').send('<h2>Registration has been successfully confirmed!</h2>');
5962
} else {
Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,51 @@
11
import {FastifySchema} from 'fastify';
22
import {emailRegex, passRegex} from '@/validation/regex';
33

4-
export const passRecoveryScheme: FastifySchema = {
4+
export const passResetScheme: FastifySchema = {
55
body: {
66
type: 'object',
7-
oneOf: [
8-
{
9-
required: ['email'],
10-
properties: {
11-
email: {
12-
type: 'string',
13-
pattern: emailRegex,
14-
},
15-
},
7+
required: ['email'],
8+
properties: {
9+
email: {
10+
type: 'string',
11+
pattern: emailRegex,
1612
},
17-
{
18-
required: ['code', 'password', 'confirmPassword'],
19-
properties: {
20-
email: {
21-
type: 'string',
22-
pattern: emailRegex,
23-
},
24-
password: {
25-
type: 'string',
26-
pattern: passRegex,
27-
},
28-
confirmPassword: {
29-
type: 'string',
30-
const: {
31-
$data: '1/password'
32-
}
33-
},
34-
},
13+
},
14+
},
15+
response: {
16+
200: {
17+
type: 'string',
18+
},
19+
500: {
20+
type: 'string',
21+
},
22+
},
23+
};
24+
25+
26+
export const usersPasswordScheme: FastifySchema = {
27+
body: {
28+
type: 'object',
29+
required: ['email', 'code', 'password', 'confirmPassword'],
30+
properties: {
31+
email: {
32+
type: 'string',
33+
pattern: emailRegex,
34+
},
35+
code: {
36+
type: 'string',
3537
},
36-
]
38+
password: {
39+
type: 'string',
40+
pattern: passRegex,
41+
},
42+
confirmPassword: {
43+
type: 'string',
44+
const: {
45+
$data: '1/password'
46+
}
47+
},
48+
},
3749
},
3850
response: {
3951
200: {
@@ -45,3 +57,5 @@ export const passRecoveryScheme: FastifySchema = {
4557
},
4658
};
4759

60+
61+

app/components/users/passRecovery.ts

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,61 @@
11
import {FastifyInstance} from 'fastify';
22
import {randomBytes} from 'crypto';
3-
import {passRecoveryScheme} from '@/components/users/passRecovery.scheme';
3+
import {passResetScheme, usersPasswordScheme} from '@/components/users/passRecovery.scheme'
44
import {createTransport} from 'nodemailer';
55
import {SMTPOpt} from '@/assist/mail';
66
import {sha256} from '@/components/auth/assistant';
77

8-
interface IBody {
9-
email?: string,
10-
code?: string,
11-
password?: string,
12-
confirmPassword?: string
8+
interface IBodyPassReset {
9+
email: string,
10+
}
11+
interface IBodyUsersPassword {
12+
email: string,
13+
code: string,
14+
password: string,
15+
confirmPassword: string
1316
}
1417
export const passRecovery = async (server: FastifyInstance) => {
15-
server.patch<{Body: IBody}>(
16-
'/users/password-recovery',
17-
{schema: passRecoveryScheme},
18+
server.patch<{Body: IBodyPassReset}>(
19+
'/password-reset',
20+
{schema: passResetScheme},
1821
async (req, reply) => {
19-
const {email, code, password, confirmPassword} = req.body;
22+
const {email} = req.body;
2023

21-
if (email) {
22-
const recoveryCode = randomBytes(48).toString('hex').substring(0, 63);
23-
const {rowCount} = await server.pg.query('UPDATE root.users SET code = $1 WHERE email = $2', [recoveryCode, email]);
24+
const recoveryCode = Math.floor(Math.random() * 10000000).toString();
25+
const {rowCount} = await server.pg.query('UPDATE root.users SET code = $1 WHERE email = $2', [recoveryCode, email]);
2426

25-
if (rowCount) {
26-
const transporter = createTransport(SMTPOpt);
27-
const mailOptions = {
28-
to: email,
29-
subject: 'Password recovery',
30-
html: `<p>Your recovery code: <br> <b>${recoveryCode}</b> <br>Please copy it to the app</p>`
31-
};
32-
const sent = await transporter.sendMail(mailOptions);
27+
if (rowCount) {
28+
const transporter = createTransport(SMTPOpt);
29+
const mailOptions = {
30+
to: email,
31+
subject: 'Password recovery',
32+
html: `<p>Your recovery code: <b>${recoveryCode}</b> <br>Please copy it to the app</p>`
33+
};
34+
const sent = await transporter.sendMail(mailOptions);
3335

34-
if (sent) {
35-
return reply.status(200).send('An email has been sent to your email address');
36-
} else {
37-
return reply.status(500).send('Couldn\'t send email.');
38-
}
36+
if (sent) {
37+
return reply.status(200).send('An email has been sent to your email address');
3938
} else {
40-
return reply.status(500).send('Failed to write to the database');
39+
return reply.status(500).send('Couldn\'t send email.');
4140
}
41+
} else {
42+
return reply.status(500).send('Failed to write to the database');
4243
}
44+
});
45+
46+
server.patch<{Body: IBodyUsersPassword}>(
47+
'/users/password',
48+
{schema: usersPasswordScheme},
49+
async (req, reply) => {
50+
const {email, code, password} = req.body;
4351

44-
if (code && password && confirmPassword) {
45-
const hash = sha256(password);
46-
const {rowCount} = await server.pg.query('UPDATE root.users SET code = NULL, password_hash = $1 WHERE code = $2', [hash, code]);
52+
const hash = sha256(password);
53+
const {rowCount} = await server.pg.query('UPDATE root.users SET code = NULL, password_hash = $1 WHERE code = $2 AND email=$3', [hash, code, email]);
4754

48-
if (rowCount) {
49-
return reply.send('You have successfully changed your password!');
50-
} else {
51-
return reply.status(500).send('Something went wrong. Check the code');
52-
}
55+
if (rowCount) {
56+
return reply.send('You have successfully changed your password!');
57+
} else {
58+
return reply.status(500).send('Something went wrong. Check the code');
5359
}
5460
});
5561
};

app/envConfig.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ export const env:TEnv = {
2020
mailClientId: process.env.MAIL_OAUTH_CLIENTID as string,
2121
mailClientSecret: process.env.MAIL_OAUTH_CLIENT_SECRET as string,
2222
mailRefreshToken: process.env.MAIL_OAUTH_REFRESH_TOKEN as string,
23-
mailAccessToken: process.env.MAIL_OAUTH_ACCESS_TOKEN as string
23+
mailAccessToken: process.env.MAIL_OAUTH_ACCESS_TOKEN as string,
2424
};

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"scripts": {
77
"test": "echo \"Error: no test specified\" && exit 1",
88
"start": "node -r dotenv/config dist/app.js",
9-
"build": "webpack && ts-node dev-helpers/create-package.ts",
9+
"build:dev": "webpack --mode=development && ts-node dev-helpers/create-package.ts",
10+
"build:prod": "webpack --mode=production && ts-node dev-helpers/create-package.ts",
1011
"lint": "eslint .",
1112
"lint:fix": "eslint --fix --ext .ts, app/app.ts",
1213
"prepare": "husky install"

webpack.config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {externals} from './dev-helpers/dependencies';
55

66
export default {
77
target: 'node',
8-
mode: 'production',
98
entry: resolve('app/app.ts'),
109
output: {
1110
path: resolve('dist'),

0 commit comments

Comments
 (0)