Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions src/app/infra/http/middleware/authenticate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@ import { Role, Status } from '@prisma/client';
import { FastifyReply, FastifyRequest } from 'fastify';

import { app } from '@app/app';
import {
EXPIRED_TOKEN,
INVALID_TOKEN,
TOKEN_NOT_FOUND,
USER_INACTIVE,
USER_NOT_AUTHORIZED,
} from '@shared/constants/messages';

interface TokenData {
id: number;
role: Role;
status: string;
status: Status;
}

export const verifyAuthorization = (roleIds: Role[] = []) => {
Expand All @@ -15,22 +22,20 @@ export const verifyAuthorization = (roleIds: Role[] = []) => {
const authorization = req.headers.authorization;

if (!authorization) {
return res.status(401).send({ message: 'Token não fornecido' });
return res.status(401).send({ message: TOKEN_NOT_FOUND });
}

const token = authorization.split(' ')[1];
const { id, role, status } = app.jwt.verify<TokenData>(token);

if (status === Status.INACTIVE) {
return res.status(403).send({
message: 'Usuário inativo! Você está sem acesso no momento',
message: USER_INACTIVE,
});
}

if (!roleIds.includes(role)) {
return res
.status(403)
.send({ message: 'Acesso proibido! Tipo de usuário não autorizado' });
return res.status(403).send({ message: USER_NOT_AUTHORIZED });
}

req.user = { id, role, status };
Expand All @@ -39,11 +44,11 @@ export const verifyAuthorization = (roleIds: Role[] = []) => {
} catch (err) {
if (err instanceof Error) {
if (err.message.includes('expired')) {
return res.status(401).send({ message: 'O token expirou' });
return res.status(401).send({ message: EXPIRED_TOKEN });
}
}

return res.status(401).send({ message: 'Token inválido' });
return res.status(401).send({ message: INVALID_TOKEN });
}
};
};
15 changes: 10 additions & 5 deletions src/app/infra/http/middleware/update-last-access.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import { FastifyReply, FastifyRequest } from 'fastify';

import { app } from '@app/app';
import { IUserRepository } from '@shared/repositories/interfaces/user';
import { UserRepository } from '@modules/users/repositories/user-repository';
import {
EXPIRED_TOKEN,
INVALID_TOKEN,
TOKEN_NOT_FOUND,
} from '@shared/constants/messages';

export const updateLastAccess = (userRepository: IUserRepository) => {
export const updateLastAccess = (userRepository: UserRepository) => {
return async (req: FastifyRequest, res: FastifyReply) => {
try {
const authorization = req.headers.authorization;

if (!authorization) {
return res.status(401).send({ message: 'Token não fornecido' });
return res.status(401).send({ message: TOKEN_NOT_FOUND });
}

const token = authorization.split(' ')[1];
Expand All @@ -21,11 +26,11 @@ export const updateLastAccess = (userRepository: IUserRepository) => {
} catch (err) {
if (err instanceof Error) {
if (err.message.includes('expired')) {
return res.status(401).send({ message: 'O token expirou' });
return res.status(401).send({ message: EXPIRED_TOKEN });
}
}

return res.status(401).send({ message: 'Token inválido' });
return res.status(401).send({ message: INVALID_TOKEN });
}
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import {
makeUpdateAppointmentController,
makeUpdateAppointmentStatusController,
} from '@shared/factories/controllers';
import { makeUserRepository } from '@shared/factories/repositories';
import { makePrismaUserRepository } from '@shared/factories/repositories';

export const appointmentRoutes = async (app: FastifyInstance) => {
app.addHook('preHandler', updateLastAccess(makeUserRepository()));
app.addHook('preHandler', updateLastAccess(makePrismaUserRepository()));

app.get(
'/appointments',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@
import { AppointmentStatus, Prisma } from '@prisma/client';

import { prisma } from '@app/infra/prisma/client';
import { AppointmentRepository } from '@modules/appointments/repositories/appointment-repository';
import {
FindEntitiesAndCountResult,
IAppointment,
FindAppointmentsAndCountParams,
FindAllAppointmentsAndCountParams,
} from '@shared/entities';

import { IAppointmentRepository } from '../interfaces/appointment';

export class AppointmentRepository implements IAppointmentRepository {
export class PrismaAppointmentRepository implements AppointmentRepository {
async findAllAppointments(
params: FindAllAppointmentsAndCountParams,
): Promise<FindEntitiesAndCountResult<IAppointment>> {
Expand Down Expand Up @@ -128,7 +127,7 @@ export class AppointmentRepository implements IAppointmentRepository {
async updateAppointmentStatus(
appointment_id: number,
status: AppointmentStatus,
): Promise<string> {
): Promise<AppointmentStatus> {
const appointment = await prisma.appointment.update({
where: { id: appointment_id },
data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
IAppointment,
} from '@shared/entities';

export interface IAppointmentRepository {
export interface AppointmentRepository {
findAndCountAll(
params: FindAppointmentsAndCountParams,
): Promise<FindEntitiesAndCountResult<IAppointment>>;
Expand All @@ -23,5 +23,5 @@ export interface IAppointmentRepository {
updateAppointmentStatus(
appointment_id: number,
status: AppointmentStatus,
): Promise<string>;
): Promise<AppointmentStatus>;
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { Status } from '@prisma/client';

import { AppError } from '@app/errors/app-client';
import { AppointmentRepository } from '@modules/appointments/repositories/appointment-repository';
import { DoctorRepository } from '@modules/doctors/repositories/doctor-repository';
import { PatientRepository } from '@modules/patients/repositories/patient-repository';
import {
DOCTOR_INACTIVE,
DOCTOR_NOT_FOUND,
PATIENT_NOT_FOUND,
} from '@shared/constants/messages';
import {
PatientRepository,
AppointmentRepository,
DoctorRepository,
} from '@shared/repositories/implementations';

import { CreateAppointmentDTO } from './create-appointment-schema';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AppointmentStatus, AppointmentType } from '@prisma/client';

import { AppointmentRepository } from '@modules/appointments/repositories/appointment-repository';
import { IAppointment, IPaginateRequest } from '@shared/entities';
import { AppointmentRepository } from '@shared/repositories/implementations/appointment-repository';
import { validatePaginationParams } from '@shared/utils';
import { FindAndCountAll } from '@shared/utils/format-paginate';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { AppError } from '@app/errors/app-client';
import { AppointmentRepository } from '@modules/appointments/repositories/appointment-repository';
import { PatientRepository } from '@modules/patients/repositories/patient-repository';
import {
APPOINTMENT_NOT_FOUND,
PATIENT_NOT_FOUND,
} from '@shared/constants/messages';
import {
PatientRepository,
AppointmentRepository,
} from '@shared/repositories/implementations';

export class GetAppointmentService {
constructor(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { AppointmentStatus, AppointmentType } from '@prisma/client';

import { AppError } from '@app/errors/app-client';
import { AppointmentRepository } from '@modules/appointments/repositories/appointment-repository';
import { PatientRepository } from '@modules/patients/repositories/patient-repository';
import { PATIENT_NOT_FOUND } from '@shared/constants/messages';
import { IAppointment, IPaginateRequest } from '@shared/entities';
import {
PatientRepository,
AppointmentRepository,
} from '@shared/repositories/implementations';
import { validatePaginationParams } from '@shared/utils';
import { FindAndCountAll } from '@shared/utils/format-paginate';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { type FastifyReply } from 'fastify';

import { BaseController } from '@app/infra/http/controller/baseController';
import { appointmentParamsSchema } from '@modules/appointments/schemas';
import { APPOINTMENT_STATUS_LABELS } from '@shared/constants/labels';

import { updateAppointmentStatusSchema } from './update-appointment-status-schema';
import { UpdateAppointmentStatusService } from './update-appointment-status-service';
Expand All @@ -27,7 +28,7 @@ export class UpdateAppointmentStatusController extends BaseController {

return this.ok({
success: true,
status: `Status alterado para ${status}.`,
status: `Status alterado para ${APPOINTMENT_STATUS_LABELS[status]}.`,
});
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { AppointmentStatus } from '@prisma/client';

import { AppError } from '@app/errors/app-client';
import { AppointmentRepository } from '@modules/appointments/repositories/appointment-repository';
import { PatientRepository } from '@modules/patients/repositories/patient-repository';
import {
APPOINTMENT_NOT_FOUND,
APPOINTMENT_STATUS_CANNOT_BE_CHANGED,
PATIENT_NOT_FOUND,
} from '@shared/constants/messages';
import {
AppointmentRepository,
PatientRepository,
} from '@shared/repositories/implementations';

import { UpdateAppointmentStatusDTO } from './update-appointment-status-schema';

Expand All @@ -26,7 +24,7 @@ export class UpdateAppointmentStatusService {
appointmentId: number,
patientId: string,
dto: UpdateAppointmentStatusDTO,
): Promise<string> {
): Promise<AppointmentStatus> {
const patient = await this.patientRepository.findById(patientId);

if (!patient) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { Status } from '@prisma/client';

import { AppError } from '@app/errors/app-client';
import { AppointmentRepository } from '@modules/appointments/repositories/appointment-repository';
import { DoctorRepository } from '@modules/doctors/repositories/doctor-repository';
import { PatientRepository } from '@modules/patients/repositories/patient-repository';
import {
APPOINTMENT_NOT_FOUND,
DOCTOR_INACTIVE,
DOCTOR_NOT_FOUND,
PATIENT_NOT_FOUND,
} from '@shared/constants/messages';
import {
PatientRepository,
AppointmentRepository,
} from '@shared/repositories/implementations';
import { DoctorRepository } from '@shared/repositories/implementations/doctor-repository';

import { UpdateAppointmentDTO } from './update-appointment-schema';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { Status } from '@prisma/client';
import nodemailer from 'nodemailer';

import { AppError } from '@app/errors/app-client';
import { getMailClient } from '@shared/configs/mailer';
import { UserRepository } from '@modules/users/repositories/user-repository';
import { sendResetPasswordEmail } from '@shared/config/emails/reset-password';
import { USER_INACTIVE, USER_NOT_FOUND } from '@shared/constants/messages';
import { UserRepository } from '@shared/repositories/implementations';
import {
generateProvisionalPassword,
hashPassword,
Expand Down Expand Up @@ -36,35 +36,15 @@ export class ForgotPasswordService {
password: hashedPassword,
});

// TO-DO
console.log({ provisionalPassword });

const mail = await getMailClient();

const message = await mail.sendMail({
from: {
name: 'Equipe Teste',
address: 'equipe@example.com',
},
to: user.email,
subject: 'Sua nova senha já está disponivel',
html: `
<div style="font-family: sans-serif; font-size: 16px; line-height: 1.6;">
<p>Olá, ${user.name}!</p>
<p>Recebemos seu pedido para redefinir a senha e estamos aqui para ajudar!</p>
<p>Use a senha provisória abaixo para acessar sua conta novamente:</p>
<p><strong>${provisionalPassword}</strong></p>
<p>Não se esqueça de trocar essa senha assim que possível para manter sua conta segura.</p>
<p>Você pode acessar o sistema clicando no link abaixo:</p>
<p><a target="_blank" href="${process.env.BASE_URL_WEB}/sign-in">Clique aqui para fazer login</a></p>
<p>Caso você não tenha solicitado a redefinição de senha, pode ignorar esta mensagem sem preocupações.</p>
<p>Estamos sempre aqui para ajudar!</p>
<p>Abraços,</p>
<p>Equipe Teste</p>
</div>
`.trim(),
const message = await sendResetPasswordEmail({
user,
temporaryPassword: provisionalPassword,
});

// Remover
// TO-DO
console.error(nodemailer.getTestMessageUrl(message));
}
}
10 changes: 5 additions & 5 deletions src/modules/auth/useCases/login/login-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { Status } from '@prisma/client';

import { app } from '@app/app';
import { AppError } from '@app/errors/app-client';
import { UserRepository } from '@modules/users/repositories/user-repository';
import {
EMAIL_INVALID,
PASSWORD_INVALID,
INVALID_EMAIL,
INVALID_PASSWORD,
USER_INACTIVE,
} from '@shared/constants/messages';
import { UserRepository } from '@shared/repositories/implementations';

import { AuthenticationDTO } from './login-schema';

Expand All @@ -21,7 +21,7 @@ export class LoginService {
const user = await this.userRepository.findByEmail(email);

if (!user) {
throw new AppError(EMAIL_INVALID);
throw new AppError(INVALID_EMAIL);
}

const isPasswordValid = await app.bcrypt.compare(
Expand All @@ -30,7 +30,7 @@ export class LoginService {
);

if (!isPasswordValid) {
throw new AppError(PASSWORD_INVALID);
throw new AppError(INVALID_PASSWORD);
}

if (user.status === Status.INACTIVE) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import {
makeUpdateDoctorController,
makeUpdateDoctorStatusController,
} from '@shared/factories/controllers';
import { makeUserRepository } from '@shared/factories/repositories';
import { makePrismaUserRepository } from '@shared/factories/repositories';

export const doctorRoutes = async (app: FastifyInstance) => {
app.addHook(
'preHandler',
verifyAuthorization([Role.ADMIN, Role.EDITOR, Role.CLINICAL]),
);
app.addHook('preHandler', updateLastAccess(makeUserRepository()));
app.addHook('preHandler', updateLastAccess(makePrismaUserRepository()));

app.get('/doctors', bindController(makeGetAllDoctorsController()));
app.get('/doctors/:id', bindController(makeGetDoctorController()));
Expand Down
Loading
Loading