Skip to content

Commit

Permalink
Prettier all files, added refresh route
Browse files Browse the repository at this point in the history
  • Loading branch information
HalloSouf committed Apr 18, 2023
1 parent e1b13a6 commit 76908f5
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 41 deletions.
47 changes: 42 additions & 5 deletions src/api/controllers/AuthController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class AuthController extends Controller {
where: { OR: [{ email: username }, { username: username }] }
});

if (!user || !this.authService.compareHash(password, user.password))
if (!user || !this.authService.compareHash(password, user.password))
throw new Error('INVALID_CREDENTIALS');

const accessToken = this.authService.signToken({ id: user.id }, { expiresIn: '1h' });
Expand All @@ -31,16 +31,53 @@ class AuthController extends Controller {
return res.json({
user: excludeField<User, keyof User>(user, ['password']),
accessToken,
refreshToken
refreshToken,
expiresIn: 3600
});
} catch (ex: unknown) {
if (ex instanceof Error) {
if (ex.message === 'INVALID_CREDENTIALS')
return res.status(401).json({ error: 'INVALID_CREDENTIALS', message: 'Your credentials did not match.' });
if (ex.message === 'INVALID_CREDENTIALS')
return res
.status(401)
.json({ error: 'INVALID_CREDENTIALS', message: 'Your credentials did not match.' });
}

this.logger.error(ex);
return res.status(500).json({ error: 'UNKNOWN_ERROR', message: 'Error while resolving your request.' });
return res
.status(500)
.json({ error: 'UNKNOWN_ERROR', message: 'Error while resolving your request.' });
}
}

/**
* Refresh access token
* @param req Express request
* @param res Express response
*/
public async refresh(req: Request, res: Response): Promise<Response> {
const { refresh } = req.body;

try {
const refreshPayload = await this.authService.verifyToken(refresh);
if (!refreshPayload) throw new Error('INVALID_REFRESH');
if (req.auth?.bearer !== refreshPayload.payload.accessToken)
throw new Error('INVALID_REFRESH');

const accessToken = this.authService.signToken(
{ id: refreshPayload.payload.id },
{ expiresIn: '1h' }
);
const refreshToken = this.authService.signToken({
id: refreshPayload.payload.id,
accessToken
});

return res.json({ accessToken, refreshToken, expiresIn: 3600 });
} catch (ex: unknown) {
this.logger.error(ex);
return res
.status(500)
.json({ error: 'UNKNOWN_ERROR', message: 'Error while resolving your request.' });
}
}
}
Expand Down
29 changes: 21 additions & 8 deletions src/api/controllers/UserController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,22 @@ class UserController extends Controller {
} catch (ex: unknown) {
if (ex instanceof Error) {
if (ex.message === 'UNKNOWN_USER') {
return res.status(404).json({ error: 'UNKNOWN_USER', message: 'Could not find user with specified ID.' });
return res
.status(404)
.json({ error: 'UNKNOWN_USER', message: 'Could not find user with specified ID.' });
}

if (ex.message === 'NO_ACCESS') {
return res.status(403).json({ error: 'NO_ACCESS', message: 'You do not have access to this resource.' });
return res
.status(403)
.json({ error: 'NO_ACCESS', message: 'You do not have access to this resource.' });
}
}

this.logger.error(ex);
return res.status(500).json({ error: 'UNKNONW_ERROR', message: 'Error while resolving your request.' });
return res
.status(500)
.json({ error: 'UNKNONW_ERROR', message: 'Error while resolving your request.' });
}
}

Expand All @@ -51,17 +57,24 @@ class UserController extends Controller {
return res.json({ ...user });
} catch (ex: unknown) {
if (ex instanceof Prisma.PrismaClientKnownRequestError) {
if (ex.code === 'P2002' && ex.meta?.target === 'users_email_key') {
return res.status(400).json({ error: 'DUPLICATE EMAIL', message: `Email "${email}" is already used.` });
if (ex.code === 'P2002' && ex.meta?.target === 'users_email_key') {
return res
.status(400)
.json({ error: 'DUPLICATE EMAIL', message: `Email "${email}" is already used.` });
}

if (ex.code === 'P2002' && ex.meta?.target === 'users_username_key') {
return res.status(400).json({ error: 'DUPLICATE USERNAME', message: `Username "${username}" is already used.` });
return res.status(400).json({
error: 'DUPLICATE USERNAME',
message: `Username "${username}" is already used.`
});
}
}

this.logger.error(ex);
return res.status(500).json({ error: 'UNKNONW_ERROR', message: 'Error while resolving your request.' });
return res
.status(500)
.json({ error: 'UNKNONW_ERROR', message: 'Error while resolving your request.' });
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/api/routes/AuthRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ class AuthRoute extends Route {
* Initialize the routes
*/
private init(): void {
this.router.post(
'/refresh',
[
GlobalMiddleware.getBearer,
body('refresh').isLength({ min: 1 }),
GlobalMiddleware.validateBody
],
this.controller.refresh.bind(this.controller)
);
this.router.post(
'/signin',
[
Expand Down
52 changes: 26 additions & 26 deletions src/api/services/AuthService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,35 +45,35 @@ class AuthService {
);
}

/**
/**
* Verify JWT token
* @param token Token to verify
*/
public verifyToken(token: string): Promise<ICustomJwt | undefined> {
return new Promise(
(
promiseResolve: (value: ICustomJwt | undefined) => void,
reject: (reason?: VerifyErrors) => void
) => {
jwtPkg.verify(
token,
readFileSync(resolve(config.keys.publicPath), {
encoding: 'utf-8'
}),
{
audience: config.jwt.audience,
issuer: config.jwt.issuer,
algorithms: ['RS256'],
complete: true
},
(error: VerifyErrors | null, payload: Jwt | undefined) => {
if (error) reject(error);
promiseResolve(payload as ICustomJwt);
}
);
}
);
}
public verifyToken(token: string): Promise<ICustomJwt | undefined> {
return new Promise(
(
promiseResolve: (value: ICustomJwt | undefined) => void,
reject: (reason?: VerifyErrors) => void
) => {
jwtPkg.verify(
token,
readFileSync(resolve(config.keys.publicPath), {
encoding: 'utf-8'
}),
{
audience: config.jwt.audience,
issuer: config.jwt.issuer,
algorithms: ['RS256'],
complete: true
},
(error: VerifyErrors | null, payload: Jwt | undefined) => {
if (error) reject(error);
promiseResolve(payload as ICustomJwt);
}
);
}
);
}
}

export default AuthService;
2 changes: 1 addition & 1 deletion src/api/services/Service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class Service {
/**
* Prisma client instance
*/
protected get prisma(): IPrismaClient {
protected get prisma(): IPrismaClient {
return PrismaClient;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/types/global.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ declare global {
auth?: {
jwt?: ICustomJwt;
bearer?: string;
}
};
}
}
}

0 comments on commit 76908f5

Please sign in to comment.