Skip to content

Commit 37dc146

Browse files
authored
Merge pull request #4 from Gambitier/authentication
Authentication & Authorization
2 parents b8f8e24 + 882edd5 commit 37dc146

31 files changed

+719
-27
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/package-lock.json

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Projects/BooksLibrary/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"author": "akash jadhav",
1313
"license": "ISC",
1414
"devDependencies": {
15+
"@types/bcryptjs": "^2.4.2",
1516
"@types/cors": "^2.8.12",
1617
"@types/express": "^4.17.13",
1718
"@types/express-fileupload": "^1.2.2",
@@ -28,6 +29,7 @@
2829
"typescript": "^4.6.2"
2930
},
3031
"dependencies": {
32+
"bcryptjs": "^2.4.3",
3133
"cors": "^2.8.5",
3234
"dotenv": "^16.0.0",
3335
"express": "^4.17.3",
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
{
2+
"info": {
3+
"_postman_id": "0a362e15-a9cb-49f7-bec7-d9ae7272d0a4",
4+
"name": "API",
5+
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
6+
},
7+
"item": [
8+
{
9+
"name": "API Version",
10+
"request": {
11+
"method": "GET",
12+
"header": [],
13+
"url": {
14+
"raw": "{{BaseUrl}}",
15+
"host": [
16+
"{{BaseUrl}}"
17+
]
18+
}
19+
},
20+
"response": []
21+
},
22+
{
23+
"name": "Create User",
24+
"request": {
25+
"method": "POST",
26+
"header": [],
27+
"body": {
28+
"mode": "raw",
29+
"raw": "{\r\n \"Email\": \"akash@gmail.com\",\r\n \"FirstName\": \" Akash \",\r\n \"LastName\": \"Jadhav\",\r\n \"Password\": \"Test@123\"\r\n}",
30+
"options": {
31+
"raw": {
32+
"language": "json"
33+
}
34+
}
35+
},
36+
"url": {
37+
"raw": "{{BaseUrl}}/users",
38+
"host": [
39+
"{{BaseUrl}}"
40+
],
41+
"path": [
42+
"users"
43+
]
44+
}
45+
},
46+
"response": []
47+
},
48+
{
49+
"name": "user login",
50+
"event": [
51+
{
52+
"listen": "test",
53+
"script": {
54+
"exec": [
55+
"pm.test(\"Status code is 200\", function () {\r",
56+
" pm.response.to.have.status(200);\r",
57+
"});\r",
58+
"pm.test(\"Body matches string\", function () {\r",
59+
" pm.expect(pm.response.text()).to.include(\"AccessToken\");\r",
60+
"});\r",
61+
"var jsonData = pm.response.json();\r",
62+
"pm.collectionVariables.set(\"AccessToken\", jsonData.Data.entity.AccessToken);"
63+
],
64+
"type": "text/javascript"
65+
}
66+
}
67+
],
68+
"request": {
69+
"method": "POST",
70+
"header": [],
71+
"body": {
72+
"mode": "raw",
73+
"raw": "{\r\n \"Email\": \"Kiran.kharade@yopmail.com\",\r\n \"Password\": \"Test@123\"\r\n}",
74+
"options": {
75+
"raw": {
76+
"language": "json"
77+
}
78+
}
79+
},
80+
"url": {
81+
"raw": "{{BaseUrl}}/auth/login",
82+
"host": [
83+
"{{BaseUrl}}"
84+
],
85+
"path": [
86+
"auth",
87+
"login"
88+
]
89+
}
90+
},
91+
"response": []
92+
},
93+
{
94+
"name": "user get by id",
95+
"protocolProfileBehavior": {
96+
"disableBodyPruning": true
97+
},
98+
"request": {
99+
"method": "GET",
100+
"header": [
101+
{
102+
"key": "authorization",
103+
"value": "Bearer {{AccessToken}}",
104+
"type": "text"
105+
}
106+
],
107+
"body": {
108+
"mode": "raw",
109+
"raw": "{\r\n \"Email\": \"Kiran.kharade@yopmail.com\",\r\n \"Password\": \"Test@123\"\r\n}",
110+
"options": {
111+
"raw": {
112+
"language": "json"
113+
}
114+
}
115+
},
116+
"url": {
117+
"raw": "{{BaseUrl}}/users/15ee7f17-43c6-46e9-a19b-f82440ef8011",
118+
"host": [
119+
"{{BaseUrl}}"
120+
],
121+
"path": [
122+
"users",
123+
"15ee7f17-43c6-46e9-a19b-f82440ef8011"
124+
]
125+
}
126+
},
127+
"response": []
128+
}
129+
],
130+
"event": [
131+
{
132+
"listen": "prerequest",
133+
"script": {
134+
"type": "text/javascript",
135+
"exec": [
136+
""
137+
]
138+
}
139+
},
140+
{
141+
"listen": "test",
142+
"script": {
143+
"type": "text/javascript",
144+
"exec": [
145+
""
146+
]
147+
}
148+
}
149+
],
150+
"variable": [
151+
{
152+
"key": "BaseUrl",
153+
"value": "http://localhost:7272/api/v1",
154+
"type": "string"
155+
},
156+
{
157+
"key": "AccessToken",
158+
"value": "",
159+
"type": "string"
160+
}
161+
]
162+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import express from 'express';
2+
import { Authorizer } from '../../auth/authorizer';
3+
import { ApiError } from '../../common/api.error';
4+
import { Loader } from '../../startup/loader';
5+
6+
///////////////////////////////////////////////////////////////////////////////////////
7+
8+
export class BaseController {
9+
_authorizer: Authorizer = null;
10+
11+
constructor() {
12+
this._authorizer = Loader.authorizer;
13+
}
14+
15+
setContext = async (context: string, request: express.Request, response: express.Response, authorize = true) => {
16+
if (context === undefined || context === null) {
17+
throw new ApiError(500, 'Invalid request context');
18+
}
19+
const tokens = context.split('.');
20+
if (tokens.length < 2) {
21+
throw new ApiError(500, 'Invalid request context');
22+
}
23+
const resourceType = tokens[0];
24+
request.context = context;
25+
request.resourceType = resourceType;
26+
if (request.params.id !== undefined && request.params.id !== null) {
27+
request.resourceId = request.params.id;
28+
}
29+
if (authorize) {
30+
await Loader.authorizer.authorize(request, response);
31+
}
32+
};
33+
}

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

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
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';
88
import { Loader } from 'startup/loader';
9+
import { BaseController } from './base.controller';
910

10-
export class UserController {
11+
export class UserController extends BaseController {
1112
//#region member variables and constructors
1213

1314
_service: UserService = null;
1415

1516
_authorizer: Authorizer = null;
1617

1718
constructor() {
19+
super();
1820
this._service = Loader.container.resolve(UserService);
1921
this._authorizer = Loader.authorizer;
2022
}
@@ -26,7 +28,26 @@ export class UserController {
2628
};
2729

2830
getById = async (request: express.Request, response: express.Response): Promise<void> => {
29-
throw new Error('Method not implemented.');
31+
try {
32+
await this.setContext('User.getById', request, response);
33+
34+
const userId: string = await UserValidator.get(request, response);
35+
36+
const userdetails: UserDetailsDto = await this._service.getById(userId);
37+
38+
ResponseHandler.success(
39+
request,
40+
response,
41+
'User get by id!',
42+
200,
43+
{
44+
entity: userdetails,
45+
},
46+
false
47+
);
48+
} catch (err) {
49+
ResponseHandler.handleError(request, response, err);
50+
}
3051
};
3152

3253
search = async (request: express.Request, response: express.Response): Promise<void> => {
@@ -35,7 +56,7 @@ export class UserController {
3556

3657
create = async (request: express.Request, response: express.Response): Promise<void> => {
3758
try {
38-
// request.context = 'User.create';
59+
this.setContext('User.create', request, response);
3960

4061
const domainData: UserDomainModel = await UserValidator.create(request, response);
4162

@@ -55,4 +76,34 @@ export class UserController {
5576
ResponseHandler.handleError(request, response, err);
5677
}
5778
};
79+
80+
loginWithPassword = async (request: express.Request, response: express.Response): Promise<void> => {
81+
try {
82+
// request.context = 'User.create';
83+
84+
const domainData: UserLoginDetails = await UserValidator.loginWithPassword(request, response);
85+
86+
const userdetails = await this._service.loginWithPassword(domainData);
87+
88+
const message = `User '${userdetails.user.FirstName}' logged in successfully!`;
89+
90+
const data = {
91+
AccessToken: userdetails.accessToken,
92+
User: userdetails.user,
93+
};
94+
95+
ResponseHandler.success(
96+
request,
97+
response,
98+
message,
99+
200,
100+
{
101+
entity: data,
102+
},
103+
false
104+
);
105+
} catch (err) {
106+
ResponseHandler.handleError(request, response, err);
107+
}
108+
};
58109
}

0 commit comments

Comments
 (0)