eletrotupi / tcc/ commit / e6b6493

api: activate user account

Pedro Lucas Porcellis porcellis@eletrotupi.com · 4 months ago e6b6493185741dd24cf765760d87180cb7e1f6a1 Browse files
Parents 6d8c0a7
Changed 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
}