Skip to content

Commit 82493ee

Browse files
committed
login with email and password
1 parent a8d6649 commit 82493ee

File tree

17 files changed

+190
-17
lines changed

17 files changed

+190
-17
lines changed

Projects/BooksLibrary/.env.sample

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ API_VERSION=0.0.1
66
DB_USER_NAME = someusername
77
DB_USER_PASSWORD = somepass
88
DB_NAME = somename
9-
DB_HOST = host
9+
DB_HOST = host
10+
11+
USER_ACCESS_TOKEN_SECRET = test

Projects/BooksLibrary/src/api/controllers/user.controller.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { UserValidator } from 'api/validators/user.validator';
22
import { Authorizer } from 'auth/authorizer';
33
import { ResponseHandler } from 'common/response.handler';
4-
import { UserDomainModel } from 'domain.types/user/user.domain.model';
4+
import { UserDomainModel, UserLoginDetails } from 'domain.types/user/user.domain.model';
55
import { UserDetailsDto } from 'domain.types/user/user.dto';
66
import express from 'express';
77
import { UserService } from 'services/user.service';
@@ -55,4 +55,34 @@ export class UserController {
5555
ResponseHandler.handleError(request, response, err);
5656
}
5757
};
58+
59+
loginWithPassword = async (request: express.Request, response: express.Response): Promise<void> => {
60+
try {
61+
// request.context = 'User.create';
62+
63+
const domainData: UserLoginDetails = await UserValidator.loginWithPassword(request, response);
64+
65+
const userdetails = await this._service.loginWithPassword(domainData);
66+
67+
const message = `User '${userdetails.user.FirstName}' logged in successfully!`;
68+
69+
const data = {
70+
AccessToken: userdetails.accessToken,
71+
User: userdetails.user,
72+
};
73+
74+
ResponseHandler.success(
75+
request,
76+
response,
77+
message,
78+
200,
79+
{
80+
entity: data,
81+
},
82+
false
83+
);
84+
} catch (err) {
85+
ResponseHandler.handleError(request, response, err);
86+
}
87+
};
5888
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import express, { Router } from 'express';
2+
// import { Loader } from '../../startup/loader';
3+
import { UserController } from '../controllers/user.controller';
4+
5+
///////////////////////////////////////////////////////////////////////////////////
6+
7+
export const register = (app: express.Application): void => {
8+
const router: Router = express.Router();
9+
// const authenticator = Loader.authenticator;
10+
const controller = new UserController();
11+
12+
router.post('/login', controller.loginWithPassword);
13+
// router.get('/', authenticator.authenticateUser, controller.search);
14+
// router.get('/:id', authenticator.authenticateUser, controller.getById);
15+
// router.delete('/:id', authenticator.authenticateUser, controller.delete);
16+
17+
app.use('/api/v1/auth', router);
18+
};

Projects/BooksLibrary/src/api/routes/router.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import express from 'express';
22
import { Logger } from '../../common/logger';
3-
import { register } from './user.routes';
3+
import { register as registerUserRoutes } from './user.routes';
4+
import { register as registerAuthRoutes } from './auth.routes';
45

56
export class Router {
67
private _app = null;
@@ -19,7 +20,8 @@ export class Router {
1920
});
2021
});
2122

22-
register(this._app);
23+
registerUserRoutes(this._app);
24+
registerAuthRoutes(this._app);
2325

2426
resolve(true);
2527
} catch (error) {

Projects/BooksLibrary/src/api/validators/user.validator.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,37 @@
11
/* eslint-disable newline-per-chained-call */
22
import { Helper } from 'common/helper';
33
import { ResponseHandler } from 'common/response.handler';
4-
import { UserDomainModel } from 'domain.types/user/user.domain.model';
4+
import { UserDomainModel, UserLoginDetails } from 'domain.types/user/user.domain.model';
55
import express from 'express';
66
import { body, oneOf, param, query, validationResult } from 'express-validator';
77

88
export class UserValidator {
9+
//
10+
11+
static loginWithPassword = async (
12+
request: express.Request,
13+
response: express.Response
14+
): Promise<UserLoginDetails> => {
15+
try {
16+
await body('Email').isString().notEmpty().trim().run(request);
17+
await body('Password').isString().notEmpty().trim().run(request);
18+
19+
const result = validationResult(request);
20+
if (!result.isEmpty()) {
21+
Helper.handleValidationError(result);
22+
}
23+
24+
const domainModel: UserLoginDetails = {
25+
Email: request.body.Email,
26+
Password: request.body.Password,
27+
};
28+
29+
return domainModel;
30+
} catch (err) {
31+
ResponseHandler.handleError(request, response, err);
32+
}
33+
};
34+
935
static create = async (request: express.Request, response: express.Response): Promise<UserDomainModel> => {
1036
try {
1137
await body('Prefix').optional().trim().run(request);

Projects/BooksLibrary/src/auth/custom/custom.authorizer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export class CustomAuthorizer implements IAuthorizer {
6666
return false;
6767
};
6868

69-
private hasConsent = async (currentRoleId: number, context: string): Promise<boolean> => {
69+
private hasConsent = async (currentRoleId: string, context: string): Promise<boolean> => {
7070
Logger.instance().log('Current role id: ' + currentRoleId);
7171
Logger.instance().log('Context: ' + context);
7272

Projects/BooksLibrary/src/database/repository.interfaces/role.privilege.repo.interface.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ export interface IRolePrivilegeRepo {
77

88
search(): Promise<RolePrivilegeDto[]>;
99

10-
getPrivilegesForRole(roleId: number): Promise<RolePrivilegeDto[]>;
10+
getPrivilegesForRole(roleId: string): Promise<RolePrivilegeDto[]>;
1111

12-
hasPrivilegeForRole(roleId: number, privilege: string): Promise<boolean>;
12+
hasPrivilegeForRole(roleId: string, privilege: string): Promise<boolean>;
1313

1414
delete(id: string): Promise<boolean>;
1515
}

Projects/BooksLibrary/src/database/repository.interfaces/user.repo.intrerface.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ import { UserDomainModel } from 'domain.types/user/user.domain.model';
22
import { UserDetailsDto } from 'domain.types/user/user.dto';
33

44
export interface IUserRepo {
5+
getUserHashedPassword(id: string): Promise<string>;
6+
findOneUser(options: UserFindOptions): Promise<UserDetailsDto>;
57
findUsersByRoleId(id: string): Promise<UserDetailsDto[]>;
68
createUser(userDetails: UserDomainModel): Promise<UserDetailsDto>;
79
}
10+
11+
export class UserFindOptions {
12+
userId?: string;
13+
email?: string;
14+
isActive: boolean;
15+
}

Projects/BooksLibrary/src/database/sql/sequelize/mapper/user.mapper.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import User from '../models/user.model';
33

44
export class UserMapper {
55
static toDetailsDto = async (entity: User): Promise<UserDetailsDto> => {
6+
if (entity === null) {
7+
return null;
8+
}
9+
610
const dto: UserDetailsDto = {
711
id: entity.id,
812
FirstName: entity.FirstName,
@@ -13,6 +17,7 @@ export class UserMapper {
1317
CreatedAt: entity.createdAt,
1418
UpdatedAt: entity.updatedAt,
1519
DeletedAt: entity.deletedAt,
20+
RoleId: entity.RoleId,
1621
};
1722

1823
return dto;

Projects/BooksLibrary/src/database/sql/sequelize/repositories/user.repo.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,51 @@
1-
import { IUserRepo } from 'database/repository.interfaces/user.repo.intrerface';
1+
import { IUserRepo, UserFindOptions } from 'database/repository.interfaces/user.repo.intrerface';
22
import { UserDomainModel } from 'domain.types/user/user.domain.model';
33
import { UserDetailsDto } from 'domain.types/user/user.dto';
4+
import { Op } from 'sequelize';
45
import { UserMapper } from '../mapper/user.mapper';
56
import User from '../models/user.model';
67

78
export class UserRepo implements IUserRepo {
9+
async getUserHashedPassword(userId: string): Promise<string> {
10+
const user: User = await User.findOne({
11+
where: {
12+
id: userId,
13+
},
14+
});
15+
16+
return user.Password;
17+
}
18+
19+
async findOneUser(options: UserFindOptions): Promise<UserDetailsDto> {
20+
const DeletedAt = options.isActive === true ? { DeletedAt: null } : { DeletedAt: { [Op.not]: null } };
21+
22+
let findByEmail = {};
23+
if (options.email) {
24+
findByEmail = {
25+
Email: options.email,
26+
};
27+
}
28+
29+
let findByUserId = {};
30+
if (options.userId) {
31+
findByUserId = {
32+
id: options.userId,
33+
};
34+
}
35+
36+
const user: User = await User.findOne({
37+
where: {
38+
...findByEmail,
39+
...findByUserId,
40+
...DeletedAt,
41+
},
42+
});
43+
44+
const details: UserDetailsDto = await UserMapper.toDetailsDto(user);
45+
46+
return details;
47+
}
48+
849
async findUsersByRoleId(roleid: string): Promise<UserDetailsDto[]> {
950
const users: User[] = await User.findAll({
1051
where: {

0 commit comments

Comments
 (0)