Abdul Rehman
commited on
Commit
·
ae1ae66
1
Parent(s):
3d851fb
first commit
Browse files- .eslintrc.js +25 -0
- .gitignore +56 -0
- .history/src/modules/property/property.controller_20240903221404.ts +100 -0
- .history/src/modules/property/property.controller_20240904225916.ts +100 -0
- .history/src/modules/property/property.controller_20240904230453.ts +100 -0
- .history/src/modules/property/property.controller_20240904230611.ts +100 -0
- .history/src/modules/property/property.controller_20240904230817.ts +100 -0
- .history/src/modules/property/property.service_20240903213534.ts +44 -0
- .history/src/modules/property/property.service_20240904230816.ts +44 -0
- .prettierrc +4 -0
- README.md +85 -1
- nest-cli.json +8 -0
- package-lock.json +0 -0
- package.json +82 -0
- src/app.controller.spec.ts +22 -0
- src/app.controller.ts +12 -0
- src/app.module.ts +17 -0
- src/app.service.ts +8 -0
- src/constants/collections.constant.ts +2 -0
- src/constants/index.ts +2 -0
- src/constants/jwt.constant.ts +4 -0
- src/constants/repository.constant.ts +2 -0
- src/locales/en.ts +9 -0
- src/main.ts +23 -0
- src/modules/auth/auth.controller.ts +113 -0
- src/modules/auth/auth.module.ts +27 -0
- src/modules/auth/auth.service.ts +107 -0
- src/modules/auth/jwt-auth.guard.ts +18 -0
- src/modules/auth/jwt.strategy.ts +30 -0
- src/modules/auth/local-auth.guard.ts +5 -0
- src/modules/auth/local.strategy.ts +37 -0
- src/modules/database/database.module.ts +10 -0
- src/modules/database/database.provider.ts +12 -0
- src/modules/property/property.controller.ts +100 -0
- src/modules/property/property.module.ts +12 -0
- src/modules/property/property.provider.ts +12 -0
- src/modules/property/property.schema.ts +34 -0
- src/modules/property/property.service.ts +44 -0
- src/modules/shared/common.service.ts +27 -0
- src/modules/shared/sharedCrud.services.ts +28 -0
- src/modules/user/user.controller.ts +49 -0
- src/modules/user/user.dto.ts +55 -0
- src/modules/user/user.module.ts +13 -0
- src/modules/user/user.provider.ts +11 -0
- src/modules/user/user.schema.ts +78 -0
- src/modules/user/user.service.ts +25 -0
- test/app.e2e-spec.ts +24 -0
- test/jest-e2e.json +9 -0
- tsconfig.build.json +4 -0
- tsconfig.json +21 -0
.eslintrc.js
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
module.exports = {
|
2 |
+
parser: '@typescript-eslint/parser',
|
3 |
+
parserOptions: {
|
4 |
+
project: 'tsconfig.json',
|
5 |
+
tsconfigRootDir: __dirname,
|
6 |
+
sourceType: 'module',
|
7 |
+
},
|
8 |
+
plugins: ['@typescript-eslint/eslint-plugin'],
|
9 |
+
extends: [
|
10 |
+
'plugin:@typescript-eslint/recommended',
|
11 |
+
'plugin:prettier/recommended',
|
12 |
+
],
|
13 |
+
root: true,
|
14 |
+
env: {
|
15 |
+
node: true,
|
16 |
+
jest: true,
|
17 |
+
},
|
18 |
+
ignorePatterns: ['.eslintrc.js'],
|
19 |
+
rules: {
|
20 |
+
'@typescript-eslint/interface-name-prefix': 'off',
|
21 |
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
22 |
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
23 |
+
'@typescript-eslint/no-explicit-any': 'off',
|
24 |
+
},
|
25 |
+
};
|
.gitignore
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# compiled output
|
2 |
+
/dist
|
3 |
+
/node_modules
|
4 |
+
/build
|
5 |
+
|
6 |
+
# Logs
|
7 |
+
logs
|
8 |
+
*.log
|
9 |
+
npm-debug.log*
|
10 |
+
pnpm-debug.log*
|
11 |
+
yarn-debug.log*
|
12 |
+
yarn-error.log*
|
13 |
+
lerna-debug.log*
|
14 |
+
|
15 |
+
# OS
|
16 |
+
.DS_Store
|
17 |
+
|
18 |
+
# Tests
|
19 |
+
/coverage
|
20 |
+
/.nyc_output
|
21 |
+
|
22 |
+
# IDEs and editors
|
23 |
+
/.idea
|
24 |
+
.project
|
25 |
+
.classpath
|
26 |
+
.c9/
|
27 |
+
*.launch
|
28 |
+
.settings/
|
29 |
+
*.sublime-workspace
|
30 |
+
|
31 |
+
# IDE - VSCode
|
32 |
+
.vscode/*
|
33 |
+
!.vscode/settings.json
|
34 |
+
!.vscode/tasks.json
|
35 |
+
!.vscode/launch.json
|
36 |
+
!.vscode/extensions.json
|
37 |
+
|
38 |
+
# dotenv environment variable files
|
39 |
+
.env
|
40 |
+
.env.development.local
|
41 |
+
.env.test.local
|
42 |
+
.env.production.local
|
43 |
+
.env.local
|
44 |
+
|
45 |
+
# temp directory
|
46 |
+
.temp
|
47 |
+
.tmp
|
48 |
+
|
49 |
+
# Runtime data
|
50 |
+
pids
|
51 |
+
*.pid
|
52 |
+
*.seed
|
53 |
+
*.pid.lock
|
54 |
+
|
55 |
+
# Diagnostic reports (https://nodejs.org/api/report.html)
|
56 |
+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
.history/src/modules/property/property.controller_20240903221404.ts
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {
|
2 |
+
Body,
|
3 |
+
Controller,
|
4 |
+
Get,
|
5 |
+
HttpStatus,
|
6 |
+
Post,
|
7 |
+
Query,
|
8 |
+
Req,
|
9 |
+
Res,
|
10 |
+
UseGuards,
|
11 |
+
} from '@nestjs/common';
|
12 |
+
import { Response } from 'express';
|
13 |
+
import { CommonServices } from '../shared/common.service';
|
14 |
+
import { PropertyService } from './property.service';
|
15 |
+
|
16 |
+
@Controller('property')
|
17 |
+
export class PropertyController extends CommonServices {
|
18 |
+
constructor(private readonly propertyService: PropertyService) {
|
19 |
+
super();
|
20 |
+
}
|
21 |
+
|
22 |
+
@Get('')
|
23 |
+
async getPropertListings(@Res() res: Response, @Req() req): Promise<any> {
|
24 |
+
try {
|
25 |
+
const response = await this.propertyService.sharedFind({});
|
26 |
+
return this.sendResponse(
|
27 |
+
this.messages.Success,
|
28 |
+
response ?? 'NOT_FOUND',
|
29 |
+
HttpStatus.OK,
|
30 |
+
res,
|
31 |
+
);
|
32 |
+
} catch (error) {
|
33 |
+
return this.sendResponse(
|
34 |
+
'Internal server Error',
|
35 |
+
{},
|
36 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
37 |
+
res,
|
38 |
+
);
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
*
|
44 |
+
* @param query
|
45 |
+
* @param res
|
46 |
+
* @param req
|
47 |
+
*/
|
48 |
+
@Get('/listings/dashboard')
|
49 |
+
async getDashboardLisings(@Res() res, @Req() req) {
|
50 |
+
try {
|
51 |
+
const listings = await this.propertyService.propertyRepository
|
52 |
+
.find({})
|
53 |
+
.sort({ _id: -1 })
|
54 |
+
.limit(20);
|
55 |
+
|
56 |
+
this.sendResponse(this.messages.Success, listings, HttpStatus.OK, res);
|
57 |
+
} catch (error) {
|
58 |
+
console.error('error', error);
|
59 |
+
this.sendResponse(
|
60 |
+
this.messages.Error,
|
61 |
+
null,
|
62 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
63 |
+
res,
|
64 |
+
);
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
*
|
70 |
+
* @param query
|
71 |
+
* @param res
|
72 |
+
* @param req
|
73 |
+
*/
|
74 |
+
@Get('/listings')
|
75 |
+
async getDashboardActiveUsers(@Query() query, @Res() res, @Req() req) {
|
76 |
+
try {
|
77 |
+
const page = Number(query.page);
|
78 |
+
const resPerPage = query.resPerPage ? Number(query.resPerPage) : 20;
|
79 |
+
const search = query.search;
|
80 |
+
|
81 |
+
console.log(`search =>`, search);
|
82 |
+
|
83 |
+
const activeUsers = await this.propertyService.propertyLisitng(
|
84 |
+
page,
|
85 |
+
resPerPage,
|
86 |
+
search,
|
87 |
+
);
|
88 |
+
|
89 |
+
this.sendResponse(this.messages.Success, activeUsers, HttpStatus.OK, res);
|
90 |
+
} catch (error) {
|
91 |
+
console.error('error', error);
|
92 |
+
this.sendResponse(
|
93 |
+
this.messages.Error,
|
94 |
+
null,
|
95 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
96 |
+
res,
|
97 |
+
);
|
98 |
+
}
|
99 |
+
}
|
100 |
+
}
|
.history/src/modules/property/property.controller_20240904225916.ts
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {
|
2 |
+
Body,
|
3 |
+
Controller,
|
4 |
+
Get,
|
5 |
+
HttpStatus,
|
6 |
+
Post,
|
7 |
+
Query,
|
8 |
+
Req,
|
9 |
+
Res,
|
10 |
+
UseGuards,
|
11 |
+
} from '@nestjs/common';
|
12 |
+
import { Response } from 'express';
|
13 |
+
import { CommonServices } from '../shared/common.service';
|
14 |
+
import { PropertyService } from './property.service';
|
15 |
+
|
16 |
+
@Controller('property')
|
17 |
+
export class PropertyController extends CommonServices {
|
18 |
+
constructor(private readonly propertyService: PropertyService) {
|
19 |
+
super();
|
20 |
+
}
|
21 |
+
|
22 |
+
@Get('')
|
23 |
+
async getPropertListings(@Res() res: Response, @Req() req): Promise<any> {
|
24 |
+
try {
|
25 |
+
const response = await this.propertyService.sharedFind({});
|
26 |
+
return this.sendResponse(
|
27 |
+
this.messages.Success,
|
28 |
+
response ?? 'NOT_FOUND',
|
29 |
+
HttpStatus.OK,
|
30 |
+
res,
|
31 |
+
);
|
32 |
+
} catch (error) {
|
33 |
+
return this.sendResponse(
|
34 |
+
'Internal server Error',
|
35 |
+
{},
|
36 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
37 |
+
res,
|
38 |
+
);
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
*
|
44 |
+
* @param query
|
45 |
+
* @param res
|
46 |
+
* @param req
|
47 |
+
*/
|
48 |
+
@Get('/listings/dashboard')
|
49 |
+
async getDashboardLisings(@Res() res, @Req() req) {
|
50 |
+
try {
|
51 |
+
const listings = await this.propertyService.propertyRepository
|
52 |
+
.find({})
|
53 |
+
.sort({ _id: -1 })
|
54 |
+
.limit(20);
|
55 |
+
|
56 |
+
this.sendResponse(this.messages.Success, listings, HttpStatus.OK, res);
|
57 |
+
} catch (error) {
|
58 |
+
console.error('error', error);
|
59 |
+
this.sendResponse(
|
60 |
+
this.messages.Error,
|
61 |
+
null,
|
62 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
63 |
+
res,
|
64 |
+
);
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
*
|
70 |
+
* @param query
|
71 |
+
* @param res
|
72 |
+
* @param req
|
73 |
+
*/
|
74 |
+
@Get('/listings')
|
75 |
+
async getDashboardActiveUsers(@Query() query, @Res() res, @Req() req) {
|
76 |
+
try {
|
77 |
+
const page = Number(query.page);
|
78 |
+
const resPerPage = query.resPerPage ? Number(query.resPerPage) : 20;
|
79 |
+
const search = query.search;
|
80 |
+
|
81 |
+
console.log(`search =>`, query);
|
82 |
+
|
83 |
+
const activeUsers = await this.propertyService.propertyLisitng(
|
84 |
+
page,
|
85 |
+
resPerPage,
|
86 |
+
search,
|
87 |
+
);
|
88 |
+
|
89 |
+
this.sendResponse(this.messages.Success, activeUsers, HttpStatus.OK, res);
|
90 |
+
} catch (error) {
|
91 |
+
console.error('error', error);
|
92 |
+
this.sendResponse(
|
93 |
+
this.messages.Error,
|
94 |
+
null,
|
95 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
96 |
+
res,
|
97 |
+
);
|
98 |
+
}
|
99 |
+
}
|
100 |
+
}
|
.history/src/modules/property/property.controller_20240904230453.ts
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {
|
2 |
+
Body,
|
3 |
+
Controller,
|
4 |
+
Get,
|
5 |
+
HttpStatus,
|
6 |
+
Post,
|
7 |
+
Query,
|
8 |
+
Req,
|
9 |
+
Res,
|
10 |
+
UseGuards,
|
11 |
+
} from '@nestjs/common';
|
12 |
+
import { Response } from 'express';
|
13 |
+
import { CommonServices } from '../shared/common.service';
|
14 |
+
import { PropertyService } from './property.service';
|
15 |
+
|
16 |
+
@Controller('property')
|
17 |
+
export class PropertyController extends CommonServices {
|
18 |
+
constructor(private readonly propertyService: PropertyService) {
|
19 |
+
super();
|
20 |
+
}
|
21 |
+
|
22 |
+
@Get('')
|
23 |
+
async getPropertListings(@Res() res: Response, @Req() req): Promise<any> {
|
24 |
+
try {
|
25 |
+
const response = await this.propertyService.sharedFind({});
|
26 |
+
return this.sendResponse(
|
27 |
+
this.messages.Success,
|
28 |
+
response ?? 'NOT_FOUND',
|
29 |
+
HttpStatus.OK,
|
30 |
+
res,
|
31 |
+
);
|
32 |
+
} catch (error) {
|
33 |
+
return this.sendResponse(
|
34 |
+
'Internal server Error',
|
35 |
+
{},
|
36 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
37 |
+
res,
|
38 |
+
);
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
*
|
44 |
+
* @param query
|
45 |
+
* @param res
|
46 |
+
* @param req
|
47 |
+
*/
|
48 |
+
@Get('/listings/dashboard')
|
49 |
+
async getDashboardLisings(@Res() res, @Req() req) {
|
50 |
+
try {
|
51 |
+
const listings = await this.propertyService.propertyRepository
|
52 |
+
.find({})
|
53 |
+
.sort({ _id: -1 })
|
54 |
+
.limit(20);
|
55 |
+
|
56 |
+
this.sendResponse(this.messages.Success, listings, HttpStatus.OK, res);
|
57 |
+
} catch (error) {
|
58 |
+
console.error('error', error);
|
59 |
+
this.sendResponse(
|
60 |
+
this.messages.Error,
|
61 |
+
null,
|
62 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
63 |
+
res,
|
64 |
+
);
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
*
|
70 |
+
* @param query
|
71 |
+
* @param res
|
72 |
+
* @param req
|
73 |
+
*/
|
74 |
+
@Get('/listings')
|
75 |
+
async getDashboardActiveUsers(@Query() query, @Res() res, @Req() req) {
|
76 |
+
try {
|
77 |
+
const page = Number(query.page);
|
78 |
+
const resPerPage = query.resPerPage ? Number(query.resPerPage) : 20;
|
79 |
+
const search = query.search || ''; // Default to empty search if not provided
|
80 |
+
|
81 |
+
console.log(`search =>`, query);
|
82 |
+
|
83 |
+
const activeUsers = await this.propertyService.propertyLisitng(
|
84 |
+
page,
|
85 |
+
resPerPage,
|
86 |
+
search,
|
87 |
+
);
|
88 |
+
|
89 |
+
this.sendResponse(this.messages.Success, activeUsers, HttpStatus.OK, res);
|
90 |
+
} catch (error) {
|
91 |
+
console.error('error', error);
|
92 |
+
this.sendResponse(
|
93 |
+
this.messages.Error,
|
94 |
+
null,
|
95 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
96 |
+
res,
|
97 |
+
);
|
98 |
+
}
|
99 |
+
}
|
100 |
+
}
|
.history/src/modules/property/property.controller_20240904230611.ts
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {
|
2 |
+
Body,
|
3 |
+
Controller,
|
4 |
+
Get,
|
5 |
+
HttpStatus,
|
6 |
+
Post,
|
7 |
+
Query,
|
8 |
+
Req,
|
9 |
+
Res,
|
10 |
+
UseGuards,
|
11 |
+
} from '@nestjs/common';
|
12 |
+
import { Response } from 'express';
|
13 |
+
import { CommonServices } from '../shared/common.service';
|
14 |
+
import { PropertyService } from './property.service';
|
15 |
+
|
16 |
+
@Controller('property')
|
17 |
+
export class PropertyController extends CommonServices {
|
18 |
+
constructor(private readonly propertyService: PropertyService) {
|
19 |
+
super();
|
20 |
+
}
|
21 |
+
|
22 |
+
@Get('')
|
23 |
+
async getPropertListings(@Res() res: Response, @Req() req): Promise<any> {
|
24 |
+
try {
|
25 |
+
const response = await this.propertyService.sharedFind({});
|
26 |
+
return this.sendResponse(
|
27 |
+
this.messages.Success,
|
28 |
+
response ?? 'NOT_FOUND',
|
29 |
+
HttpStatus.OK,
|
30 |
+
res,
|
31 |
+
);
|
32 |
+
} catch (error) {
|
33 |
+
return this.sendResponse(
|
34 |
+
'Internal server Error',
|
35 |
+
{},
|
36 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
37 |
+
res,
|
38 |
+
);
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
*
|
44 |
+
* @param query
|
45 |
+
* @param res
|
46 |
+
* @param req
|
47 |
+
*/
|
48 |
+
@Get('/listings/dashboard')
|
49 |
+
async getDashboardLisings(@Res() res, @Req() req) {
|
50 |
+
try {
|
51 |
+
const listings = await this.propertyService.propertyRepository
|
52 |
+
.find({})
|
53 |
+
.sort({ _id: -1 })
|
54 |
+
.limit(20);
|
55 |
+
|
56 |
+
this.sendResponse(this.messages.Success, listings, HttpStatus.OK, res);
|
57 |
+
} catch (error) {
|
58 |
+
console.error('error', error);
|
59 |
+
this.sendResponse(
|
60 |
+
this.messages.Error,
|
61 |
+
null,
|
62 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
63 |
+
res,
|
64 |
+
);
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
*
|
70 |
+
* @param query
|
71 |
+
* @param res
|
72 |
+
* @param req
|
73 |
+
*/
|
74 |
+
@Get('/listings')
|
75 |
+
async getDashboardActiveUsers(@Query() query, @Res() res, @Req() req) {
|
76 |
+
try {
|
77 |
+
const page = Number(query.page);
|
78 |
+
const resPerPage = query.resPerPage ? Number(query.resPerPage) : 20;
|
79 |
+
const search = query.search || ''; // Default to empty search if not provided
|
80 |
+
|
81 |
+
console.log(`search =>`, query);
|
82 |
+
|
83 |
+
const listings = await this.propertyService.propertyLisitng(
|
84 |
+
page,
|
85 |
+
resPerPage,
|
86 |
+
search,
|
87 |
+
);
|
88 |
+
|
89 |
+
this.sendResponse(this.messages.Success, listings, HttpStatus.OK, res);
|
90 |
+
} catch (error) {
|
91 |
+
console.error('error', error);
|
92 |
+
this.sendResponse(
|
93 |
+
this.messages.Error,
|
94 |
+
null,
|
95 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
96 |
+
res,
|
97 |
+
);
|
98 |
+
}
|
99 |
+
}
|
100 |
+
}
|
.history/src/modules/property/property.controller_20240904230817.ts
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {
|
2 |
+
Body,
|
3 |
+
Controller,
|
4 |
+
Get,
|
5 |
+
HttpStatus,
|
6 |
+
Post,
|
7 |
+
Query,
|
8 |
+
Req,
|
9 |
+
Res,
|
10 |
+
UseGuards,
|
11 |
+
} from '@nestjs/common';
|
12 |
+
import { Response } from 'express';
|
13 |
+
import { CommonServices } from '../shared/common.service';
|
14 |
+
import { PropertyService } from './property.service';
|
15 |
+
|
16 |
+
@Controller('property')
|
17 |
+
export class PropertyController extends CommonServices {
|
18 |
+
constructor(private readonly propertyService: PropertyService) {
|
19 |
+
super();
|
20 |
+
}
|
21 |
+
|
22 |
+
@Get('')
|
23 |
+
async getPropertListings(@Res() res: Response, @Req() req): Promise<any> {
|
24 |
+
try {
|
25 |
+
const response = await this.propertyService.sharedFind({});
|
26 |
+
return this.sendResponse(
|
27 |
+
this.messages.Success,
|
28 |
+
response ?? 'NOT_FOUND',
|
29 |
+
HttpStatus.OK,
|
30 |
+
res,
|
31 |
+
);
|
32 |
+
} catch (error) {
|
33 |
+
return this.sendResponse(
|
34 |
+
'Internal server Error',
|
35 |
+
{},
|
36 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
37 |
+
res,
|
38 |
+
);
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
*
|
44 |
+
* @param query
|
45 |
+
* @param res
|
46 |
+
* @param req
|
47 |
+
*/
|
48 |
+
@Get('/listings/dashboard')
|
49 |
+
async getDashboardLisings(@Res() res, @Req() req) {
|
50 |
+
try {
|
51 |
+
const listings = await this.propertyService.propertyRepository
|
52 |
+
.find({})
|
53 |
+
.sort({ _id: -1 })
|
54 |
+
.limit(20);
|
55 |
+
|
56 |
+
this.sendResponse(this.messages.Success, listings, HttpStatus.OK, res);
|
57 |
+
} catch (error) {
|
58 |
+
console.error('error', error);
|
59 |
+
this.sendResponse(
|
60 |
+
this.messages.Error,
|
61 |
+
null,
|
62 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
63 |
+
res,
|
64 |
+
);
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
*
|
70 |
+
* @param query
|
71 |
+
* @param res
|
72 |
+
* @param req
|
73 |
+
*/
|
74 |
+
@Get('/listings')
|
75 |
+
async getDashboardActiveUsers(@Query() query, @Res() res, @Req() req) {
|
76 |
+
try {
|
77 |
+
const page = Number(query.page);
|
78 |
+
const resPerPage = query.resPerPage ? Number(query.resPerPage) : 20;
|
79 |
+
const search = query.search || ''; // Default to empty search if not provided
|
80 |
+
|
81 |
+
console.log(`search =>`, query);
|
82 |
+
|
83 |
+
const listings = await this.propertyService.propertyLisitng(
|
84 |
+
page,
|
85 |
+
resPerPage,
|
86 |
+
search,
|
87 |
+
);
|
88 |
+
|
89 |
+
this.sendResponse(this.messages.Success, listings, HttpStatus.OK, res);
|
90 |
+
} catch (error) {
|
91 |
+
console.error('error', error);
|
92 |
+
this.sendResponse(
|
93 |
+
this.messages.Error,
|
94 |
+
null,
|
95 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
96 |
+
res,
|
97 |
+
);
|
98 |
+
}
|
99 |
+
}
|
100 |
+
}
|
.history/src/modules/property/property.service_20240903213534.ts
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Inject, Injectable } from '@nestjs/common';
|
2 |
+
import { Model, Types } from 'mongoose';
|
3 |
+
import { sharedCrudService } from '../shared/sharedCrud.services';
|
4 |
+
import { PROPERTY_REPOSITORY } from 'src/constants';
|
5 |
+
import { IPropertyDocument } from './property.schema';
|
6 |
+
|
7 |
+
@Injectable()
|
8 |
+
export class PropertyService extends sharedCrudService {
|
9 |
+
constructor(
|
10 |
+
@Inject(PROPERTY_REPOSITORY)
|
11 |
+
readonly propertyRepository: Model<IPropertyDocument>,
|
12 |
+
) {
|
13 |
+
super(propertyRepository);
|
14 |
+
}
|
15 |
+
|
16 |
+
async propertyLisitng(
|
17 |
+
page: number,
|
18 |
+
resPerPage: number,
|
19 |
+
search: string,
|
20 |
+
): Promise<any> {
|
21 |
+
const query = [];
|
22 |
+
query.push({ id: { $exists: true } });
|
23 |
+
|
24 |
+
if (search) query.push({ title: { $regex: search, $options: 'i' } });
|
25 |
+
|
26 |
+
const [users, cusersCount] = await Promise.all([
|
27 |
+
this.propertyRepository
|
28 |
+
.find({ $and: [...query] })
|
29 |
+
.sort({ createdAt: -1 })
|
30 |
+
.skip(resPerPage * (page - 1))
|
31 |
+
.limit(resPerPage)
|
32 |
+
.exec(),
|
33 |
+
this.propertyRepository.countDocuments({ $and: [...query] }).exec(),
|
34 |
+
]);
|
35 |
+
|
36 |
+
return {
|
37 |
+
users,
|
38 |
+
current_page: page,
|
39 |
+
pages: Math.ceil(cusersCount / resPerPage),
|
40 |
+
total_users: cusersCount,
|
41 |
+
per_page: resPerPage,
|
42 |
+
};
|
43 |
+
}
|
44 |
+
}
|
.history/src/modules/property/property.service_20240904230816.ts
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Inject, Injectable } from '@nestjs/common';
|
2 |
+
import { Model, Types } from 'mongoose';
|
3 |
+
import { sharedCrudService } from '../shared/sharedCrud.services';
|
4 |
+
import { PROPERTY_REPOSITORY } from 'src/constants';
|
5 |
+
import { IPropertyDocument } from './property.schema';
|
6 |
+
|
7 |
+
@Injectable()
|
8 |
+
export class PropertyService extends sharedCrudService {
|
9 |
+
constructor(
|
10 |
+
@Inject(PROPERTY_REPOSITORY)
|
11 |
+
readonly propertyRepository: Model<IPropertyDocument>,
|
12 |
+
) {
|
13 |
+
super(propertyRepository);
|
14 |
+
}
|
15 |
+
|
16 |
+
async propertyLisitng(
|
17 |
+
page: number,
|
18 |
+
resPerPage: number,
|
19 |
+
search: string,
|
20 |
+
): Promise<any> {
|
21 |
+
const query = [];
|
22 |
+
query.push({ id: { $exists: true } });
|
23 |
+
|
24 |
+
if (search) query.push({ title: { $regex: search, $options: 'i' } });
|
25 |
+
|
26 |
+
const [listings, tLisitngsCount] = await Promise.all([
|
27 |
+
this.propertyRepository
|
28 |
+
.find({ $and: [...query] })
|
29 |
+
.sort({ createdAt: -1 })
|
30 |
+
.skip(resPerPage * (page - 1))
|
31 |
+
.limit(resPerPage)
|
32 |
+
.exec(),
|
33 |
+
this.propertyRepository.countDocuments({ $and: [...query] }).exec(),
|
34 |
+
]);
|
35 |
+
|
36 |
+
return {
|
37 |
+
listings,
|
38 |
+
current_page: page,
|
39 |
+
pages: Math.ceil(tLisitngsCount / resPerPage),
|
40 |
+
total_listings: tLisitngsCount,
|
41 |
+
per_page: resPerPage,
|
42 |
+
};
|
43 |
+
}
|
44 |
+
}
|
.prettierrc
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"singleQuote": true,
|
3 |
+
"trailingComma": "all"
|
4 |
+
}
|
README.md
CHANGED
@@ -1 +1,85 @@
|
|
1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<p align="center">
|
2 |
+
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="120" alt="Nest Logo" /></a>
|
3 |
+
</p>
|
4 |
+
|
5 |
+
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
|
6 |
+
[circleci-url]: https://circleci.com/gh/nestjs/nest
|
7 |
+
|
8 |
+
<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
|
9 |
+
<p align="center">
|
10 |
+
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
|
11 |
+
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
|
12 |
+
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
|
13 |
+
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
|
14 |
+
<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
|
15 |
+
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
|
16 |
+
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
|
17 |
+
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
|
18 |
+
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg" alt="Donate us"/></a>
|
19 |
+
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
|
20 |
+
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow" alt="Follow us on Twitter"></a>
|
21 |
+
</p>
|
22 |
+
<!--[](https://opencollective.com/nest#backer)
|
23 |
+
[](https://opencollective.com/nest#sponsor)-->
|
24 |
+
|
25 |
+
## Description
|
26 |
+
|
27 |
+
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
|
28 |
+
|
29 |
+
## Project setup
|
30 |
+
|
31 |
+
```bash
|
32 |
+
$ npm install
|
33 |
+
```
|
34 |
+
|
35 |
+
## Compile and run the project
|
36 |
+
|
37 |
+
```bash
|
38 |
+
# development
|
39 |
+
$ npm run start
|
40 |
+
|
41 |
+
# watch mode
|
42 |
+
$ npm run start:dev
|
43 |
+
|
44 |
+
# production mode
|
45 |
+
$ npm run start:prod
|
46 |
+
```
|
47 |
+
|
48 |
+
## Run tests
|
49 |
+
|
50 |
+
```bash
|
51 |
+
# unit tests
|
52 |
+
$ npm run test
|
53 |
+
|
54 |
+
# e2e tests
|
55 |
+
$ npm run test:e2e
|
56 |
+
|
57 |
+
# test coverage
|
58 |
+
$ npm run test:cov
|
59 |
+
```
|
60 |
+
|
61 |
+
## Resources
|
62 |
+
|
63 |
+
Check out a few resources that may come in handy when working with NestJS:
|
64 |
+
|
65 |
+
- Visit the [NestJS Documentation](https://docs.nestjs.com) to learn more about the framework.
|
66 |
+
- For questions and support, please visit our [Discord channel](https://discord.gg/G7Qnnhy).
|
67 |
+
- To dive deeper and get more hands-on experience, check out our official video [courses](https://courses.nestjs.com/).
|
68 |
+
- Visualize your application graph and interact with the NestJS application in real-time using [NestJS Devtools](https://devtools.nestjs.com).
|
69 |
+
- Need help with your project (part-time to full-time)? Check out our official [enterprise support](https://enterprise.nestjs.com).
|
70 |
+
- To stay in the loop and get updates, follow us on [X](https://x.com/nestframework) and [LinkedIn](https://linkedin.com/company/nestjs).
|
71 |
+
- Looking for a job, or have a job to offer? Check out our official [Jobs board](https://jobs.nestjs.com).
|
72 |
+
|
73 |
+
## Support
|
74 |
+
|
75 |
+
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
|
76 |
+
|
77 |
+
## Stay in touch
|
78 |
+
|
79 |
+
- Author - [Kamil Myśliwiec](https://twitter.com/kammysliwiec)
|
80 |
+
- Website - [https://nestjs.com](https://nestjs.com/)
|
81 |
+
- Twitter - [@nestframework](https://twitter.com/nestframework)
|
82 |
+
|
83 |
+
## License
|
84 |
+
|
85 |
+
Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE).
|
nest-cli.json
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"$schema": "https://json.schemastore.org/nest-cli",
|
3 |
+
"collection": "@nestjs/schematics",
|
4 |
+
"sourceRoot": "src",
|
5 |
+
"compilerOptions": {
|
6 |
+
"deleteOutDir": true
|
7 |
+
}
|
8 |
+
}
|
package-lock.json
ADDED
The diff for this file is too large to render.
See raw diff
|
|
package.json
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "property",
|
3 |
+
"version": "0.0.1",
|
4 |
+
"description": "",
|
5 |
+
"author": "",
|
6 |
+
"private": true,
|
7 |
+
"license": "UNLICENSED",
|
8 |
+
"scripts": {
|
9 |
+
"build": "nest build",
|
10 |
+
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
11 |
+
"start": "nest start",
|
12 |
+
"start:dev": "nest start --watch",
|
13 |
+
"start:debug": "nest start --debug --watch",
|
14 |
+
"start:prod": "node dist/main",
|
15 |
+
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
16 |
+
"test": "jest",
|
17 |
+
"test:watch": "jest --watch",
|
18 |
+
"test:cov": "jest --coverage",
|
19 |
+
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
20 |
+
"test:e2e": "jest --config ./test/jest-e2e.json"
|
21 |
+
},
|
22 |
+
"dependencies": {
|
23 |
+
"@nestjs/common": "^10.0.0",
|
24 |
+
"@nestjs/core": "^10.0.0",
|
25 |
+
"@nestjs/jwt": "^10.2.0",
|
26 |
+
"@nestjs/passport": "^10.0.3",
|
27 |
+
"@nestjs/platform-express": "^10.0.0",
|
28 |
+
"bcrypt": "^5.1.1",
|
29 |
+
"body-parser": "^1.20.2",
|
30 |
+
"class-transformer": "^0.5.1",
|
31 |
+
"class-validator": "^0.14.1",
|
32 |
+
"cors": "^2.8.5",
|
33 |
+
"i18n-ts": "^1.0.5",
|
34 |
+
"jwt-decode": "^4.0.0",
|
35 |
+
"mongoose": "^8.6.0",
|
36 |
+
"passport-custom": "^1.1.1",
|
37 |
+
"passport-jwt": "^4.0.1",
|
38 |
+
"passport-local": "^1.0.0",
|
39 |
+
"reflect-metadata": "^0.2.0",
|
40 |
+
"rxjs": "^7.8.1"
|
41 |
+
},
|
42 |
+
"devDependencies": {
|
43 |
+
"@nestjs/cli": "^10.0.0",
|
44 |
+
"@nestjs/schematics": "^10.0.0",
|
45 |
+
"@nestjs/testing": "^10.0.0",
|
46 |
+
"@types/express": "^4.17.17",
|
47 |
+
"@types/jest": "^29.5.2",
|
48 |
+
"@types/node": "^20.3.1",
|
49 |
+
"@types/supertest": "^6.0.0",
|
50 |
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
51 |
+
"@typescript-eslint/parser": "^8.0.0",
|
52 |
+
"eslint": "^8.42.0",
|
53 |
+
"eslint-config-prettier": "^9.0.0",
|
54 |
+
"eslint-plugin-prettier": "^5.0.0",
|
55 |
+
"jest": "^29.5.0",
|
56 |
+
"prettier": "^3.0.0",
|
57 |
+
"source-map-support": "^0.5.21",
|
58 |
+
"supertest": "^7.0.0",
|
59 |
+
"ts-jest": "^29.1.0",
|
60 |
+
"ts-loader": "^9.4.3",
|
61 |
+
"ts-node": "^10.9.1",
|
62 |
+
"tsconfig-paths": "^4.2.0",
|
63 |
+
"typescript": "^5.1.3"
|
64 |
+
},
|
65 |
+
"jest": {
|
66 |
+
"moduleFileExtensions": [
|
67 |
+
"js",
|
68 |
+
"json",
|
69 |
+
"ts"
|
70 |
+
],
|
71 |
+
"rootDir": "src",
|
72 |
+
"testRegex": ".*\\.spec\\.ts$",
|
73 |
+
"transform": {
|
74 |
+
"^.+\\.(t|j)s$": "ts-jest"
|
75 |
+
},
|
76 |
+
"collectCoverageFrom": [
|
77 |
+
"**/*.(t|j)s"
|
78 |
+
],
|
79 |
+
"coverageDirectory": "../coverage",
|
80 |
+
"testEnvironment": "node"
|
81 |
+
}
|
82 |
+
}
|
src/app.controller.spec.ts
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Test, TestingModule } from '@nestjs/testing';
|
2 |
+
import { AppController } from './app.controller';
|
3 |
+
import { AppService } from './app.service';
|
4 |
+
|
5 |
+
describe('AppController', () => {
|
6 |
+
let appController: AppController;
|
7 |
+
|
8 |
+
beforeEach(async () => {
|
9 |
+
const app: TestingModule = await Test.createTestingModule({
|
10 |
+
controllers: [AppController],
|
11 |
+
providers: [AppService],
|
12 |
+
}).compile();
|
13 |
+
|
14 |
+
appController = app.get<AppController>(AppController);
|
15 |
+
});
|
16 |
+
|
17 |
+
describe('root', () => {
|
18 |
+
it('should return "Hello World!"', () => {
|
19 |
+
expect(appController.getHello()).toBe('Hello World!');
|
20 |
+
});
|
21 |
+
});
|
22 |
+
});
|
src/app.controller.ts
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Controller, Get } from '@nestjs/common';
|
2 |
+
import { AppService } from './app.service';
|
3 |
+
|
4 |
+
@Controller()
|
5 |
+
export class AppController {
|
6 |
+
constructor(private readonly appService: AppService) {}
|
7 |
+
|
8 |
+
@Get()
|
9 |
+
getHello(): string {
|
10 |
+
return this.appService.getHello();
|
11 |
+
}
|
12 |
+
}
|
src/app.module.ts
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Module } from '@nestjs/common';
|
2 |
+
import { AppController } from './app.controller';
|
3 |
+
import { AppService } from './app.service';
|
4 |
+
import { PropertyModule } from './modules/property/property.module';
|
5 |
+
import { AuthModule } from './modules/auth/auth.module';
|
6 |
+
import { UserModule } from './modules/user/user.module';
|
7 |
+
|
8 |
+
@Module({
|
9 |
+
imports: [
|
10 |
+
PropertyModule,
|
11 |
+
AuthModule,
|
12 |
+
UserModule,
|
13 |
+
],
|
14 |
+
controllers: [AppController],
|
15 |
+
providers: [AppService],
|
16 |
+
})
|
17 |
+
export class AppModule {}
|
src/app.service.ts
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Injectable } from '@nestjs/common';
|
2 |
+
|
3 |
+
@Injectable()
|
4 |
+
export class AppService {
|
5 |
+
getHello(): string {
|
6 |
+
return 'Hello World!';
|
7 |
+
}
|
8 |
+
}
|
src/constants/collections.constant.ts
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
export const PROPERTIE = 'propertie';
|
2 |
+
export const USERS = 'users';
|
src/constants/index.ts
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
export * from './collections.constant'
|
2 |
+
export * from './repository.constant'
|
src/constants/jwt.constant.ts
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export const jwtConstants = {
|
2 |
+
secret: "secretKey",
|
3 |
+
salt: 10
|
4 |
+
};
|
src/constants/repository.constant.ts
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
export const PROPERTY_REPOSITORY = 'PROPERTY_REPOSITORY';
|
2 |
+
export const USER_REPOSITORY = 'USER_REPOSITORY';
|
src/locales/en.ts
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export const en = {
|
2 |
+
Success: 'Operation is completed Success',
|
3 |
+
Error: 'Something Went Wrong',
|
4 |
+
adminVerificationFaild: 'Admin key verification failed',
|
5 |
+
friendAdded: 'Friend added Successfully.',
|
6 |
+
reqRejected: 'Friend request declined.',
|
7 |
+
friendReqSent: 'Friend request sent Successfully.',
|
8 |
+
userAlreadyExist: 'User already exist.',
|
9 |
+
};
|
src/main.ts
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { NestFactory } from '@nestjs/core';
|
2 |
+
import { AppModule } from './app.module';
|
3 |
+
import * as bodyParser from 'body-parser';
|
4 |
+
import { ValidationPipe } from '@nestjs/common';
|
5 |
+
|
6 |
+
async function bootstrap() {
|
7 |
+
const app = await NestFactory.create(AppModule);
|
8 |
+
|
9 |
+
app.useGlobalPipes(new ValidationPipe());
|
10 |
+
|
11 |
+
// Enable CORS for all origins and all methods
|
12 |
+
app.enableCors({
|
13 |
+
origin: '*', // Allow all origins
|
14 |
+
methods: '*', // Allow all methods
|
15 |
+
credentials: true,
|
16 |
+
});
|
17 |
+
|
18 |
+
app.use(bodyParser.urlencoded({ extended: true }));
|
19 |
+
app.use(bodyParser.json());
|
20 |
+
|
21 |
+
await app.listen(8080);
|
22 |
+
}
|
23 |
+
bootstrap();
|
src/modules/auth/auth.controller.ts
ADDED
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {
|
2 |
+
Body,
|
3 |
+
Controller,
|
4 |
+
Get,
|
5 |
+
HttpStatus,
|
6 |
+
Inject,
|
7 |
+
Param,
|
8 |
+
Post,
|
9 |
+
Put,
|
10 |
+
Query,
|
11 |
+
Req,
|
12 |
+
Res,
|
13 |
+
UploadedFile,
|
14 |
+
UseGuards,
|
15 |
+
UseInterceptors,
|
16 |
+
} from '@nestjs/common';
|
17 |
+
import { Response, Request } from 'express';
|
18 |
+
import { AuthService } from './auth.service';
|
19 |
+
import * as bcrypt from 'bcrypt';
|
20 |
+
import { LocalAuthGuard } from './local-auth.guard';
|
21 |
+
import { UserService } from '../user/user.service';
|
22 |
+
import { JwtAuthGuard } from './jwt-auth.guard';
|
23 |
+
import * as jwt from 'jsonwebtoken';
|
24 |
+
import { FileInterceptor } from '@nestjs/platform-express';
|
25 |
+
import { Model } from 'mongoose';
|
26 |
+
import { AuthGuard } from '@nestjs/passport';
|
27 |
+
import { JwtService } from '@nestjs/jwt';
|
28 |
+
import { CommonServices } from '../shared/common.service';
|
29 |
+
import { jwtConstants } from 'src/constants/jwt.constant';
|
30 |
+
|
31 |
+
@Controller('auth')
|
32 |
+
export class AuthController extends CommonServices {
|
33 |
+
constructor(
|
34 |
+
private readonly authService: AuthService,
|
35 |
+
private readonly userService: UserService,
|
36 |
+
) {
|
37 |
+
super();
|
38 |
+
}
|
39 |
+
|
40 |
+
@UseGuards(LocalAuthGuard)
|
41 |
+
@Post('/login')
|
42 |
+
async login(
|
43 |
+
@Req() req: any,
|
44 |
+
@Res() res: Response,
|
45 |
+
@Body() body: any,
|
46 |
+
): Promise<any> {
|
47 |
+
try {
|
48 |
+
const Userresp: any = await this.authService.login(req.user, body);
|
49 |
+
return this.sendResponse(
|
50 |
+
this.messages.Success,
|
51 |
+
Userresp,
|
52 |
+
HttpStatus.OK,
|
53 |
+
res,
|
54 |
+
);
|
55 |
+
} catch (error) {
|
56 |
+
console.log(`error =>`, error);
|
57 |
+
return this.sendResponse(
|
58 |
+
'Internal server Error',
|
59 |
+
{},
|
60 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
61 |
+
res,
|
62 |
+
);
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
@Post('/signup')
|
67 |
+
async signup(
|
68 |
+
@Req() req: any,
|
69 |
+
@Res() res: Response,
|
70 |
+
@Body() body: any,
|
71 |
+
): Promise<any> {
|
72 |
+
try {
|
73 |
+
const email = body.email.toLowerCase().trim();
|
74 |
+
|
75 |
+
const checkUser = await this.userService.sharedFindOne({ email: email });
|
76 |
+
|
77 |
+
if (checkUser && checkUser.email == email) {
|
78 |
+
return this.sendResponse(
|
79 |
+
this.messages.userAlreadyExist,
|
80 |
+
{},
|
81 |
+
HttpStatus.CONFLICT,
|
82 |
+
res,
|
83 |
+
);
|
84 |
+
}
|
85 |
+
|
86 |
+
const createUser = await this.userService.sharedCreate({
|
87 |
+
...body,
|
88 |
+
password: bcrypt.hashSync(body.password, jwtConstants.salt),
|
89 |
+
roles: ['user'],
|
90 |
+
});
|
91 |
+
|
92 |
+
const Userresp: any = await this.authService.login(createUser);
|
93 |
+
|
94 |
+
return this.sendResponse(
|
95 |
+
'Account created!',
|
96 |
+
{
|
97 |
+
...Userresp,
|
98 |
+
},
|
99 |
+
HttpStatus.OK,
|
100 |
+
res,
|
101 |
+
);
|
102 |
+
} catch (error) {
|
103 |
+
console.log(error);
|
104 |
+
|
105 |
+
return this.sendResponse(
|
106 |
+
'Internal server Error',
|
107 |
+
{},
|
108 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
109 |
+
res,
|
110 |
+
);
|
111 |
+
}
|
112 |
+
}
|
113 |
+
}
|
src/modules/auth/auth.module.ts
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Module } from '@nestjs/common';
|
2 |
+
import { AuthService } from './auth.service';
|
3 |
+
import { UserModule } from '../user/user.module';
|
4 |
+
import { AuthController } from './auth.controller';
|
5 |
+
import { DatabaseModule } from '../database/database.module';
|
6 |
+
import { UserService } from '../user/user.service';
|
7 |
+
import { JwtModule } from '@nestjs/jwt';
|
8 |
+
import { PassportModule } from '@nestjs/passport';
|
9 |
+
import { jwtConstants } from 'src/constants/jwt.constant';
|
10 |
+
import { JwtStrategy } from './jwt.strategy';
|
11 |
+
import { LocalStrategy } from './local.strategy';
|
12 |
+
|
13 |
+
@Module({
|
14 |
+
imports: [
|
15 |
+
DatabaseModule,
|
16 |
+
UserModule,
|
17 |
+
PassportModule,
|
18 |
+
JwtModule.register({
|
19 |
+
secret: 'secretKey',
|
20 |
+
signOptions: { expiresIn: '60d' },
|
21 |
+
}),
|
22 |
+
],
|
23 |
+
controllers: [AuthController],
|
24 |
+
providers: [AuthService, UserService, JwtStrategy, LocalStrategy],
|
25 |
+
exports: [AuthService, UserService],
|
26 |
+
})
|
27 |
+
export class AuthModule {}
|
src/modules/auth/auth.service.ts
ADDED
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Injectable, Inject } from '@nestjs/common';
|
2 |
+
import * as bcrypt from 'bcrypt';
|
3 |
+
import { JwtService } from '@nestjs/jwt';
|
4 |
+
import { UserService } from '../user/user.service';
|
5 |
+
import { Model } from 'mongoose';
|
6 |
+
import { CommonServices } from '../shared/common.service';
|
7 |
+
var qs = require('qs');
|
8 |
+
|
9 |
+
@Injectable()
|
10 |
+
export class AuthService extends CommonServices {
|
11 |
+
constructor(
|
12 |
+
private readonly userService: UserService,
|
13 |
+
private jwtService: JwtService,
|
14 |
+
) {
|
15 |
+
super();
|
16 |
+
}
|
17 |
+
|
18 |
+
async login(user: any, body: any = {}) {
|
19 |
+
const payload = {
|
20 |
+
userId: user._id,
|
21 |
+
name: user.name,
|
22 |
+
email: user.email,
|
23 |
+
roles: user.roles,
|
24 |
+
};
|
25 |
+
|
26 |
+
return {
|
27 |
+
access_token: this.jwtService.sign(payload, {
|
28 |
+
secret: 'secretKey',
|
29 |
+
expiresIn: '60d',
|
30 |
+
}),
|
31 |
+
user: {
|
32 |
+
_id: user._id,
|
33 |
+
name: user.name,
|
34 |
+
email: user.email,
|
35 |
+
roles: user.roles,
|
36 |
+
createdAt: user.createdAt,
|
37 |
+
updatedAt: user.updatedAt,
|
38 |
+
},
|
39 |
+
};
|
40 |
+
}
|
41 |
+
|
42 |
+
async validateUser(identifier: string, password: string): Promise<any> {
|
43 |
+
console.log(`IDENTIFIER =>`, identifier);
|
44 |
+
console.log(`password =>`, password);
|
45 |
+
const user = await this.userService.userRepository
|
46 |
+
.findOne({
|
47 |
+
$or: [{ email: identifier }, { username: identifier }],
|
48 |
+
})
|
49 |
+
.select('+password');
|
50 |
+
if (user && bcrypt.compareSync(password, user.password)) {
|
51 |
+
return user;
|
52 |
+
} else {
|
53 |
+
const userInLowerCase = await this.userService.userRepository
|
54 |
+
.findOne({
|
55 |
+
$or: [
|
56 |
+
{ email: identifier.toLowerCase() },
|
57 |
+
{ username: identifier.toLowerCase() },
|
58 |
+
],
|
59 |
+
})
|
60 |
+
.select('+password');
|
61 |
+
if (
|
62 |
+
userInLowerCase &&
|
63 |
+
bcrypt.compareSync(password, userInLowerCase.password)
|
64 |
+
) {
|
65 |
+
return userInLowerCase;
|
66 |
+
}
|
67 |
+
}
|
68 |
+
return null;
|
69 |
+
}
|
70 |
+
|
71 |
+
async validateByEmail(identifier: string): Promise<any> {
|
72 |
+
const user = await this.userService.userRepository.findOne({
|
73 |
+
$or: [{ email: identifier }, { username: identifier }],
|
74 |
+
});
|
75 |
+
|
76 |
+
if (user) {
|
77 |
+
const rUser = {
|
78 |
+
userId: user._id,
|
79 |
+
name: user.name,
|
80 |
+
username: user.username,
|
81 |
+
email: user.email,
|
82 |
+
roles: user.roles,
|
83 |
+
// iat: user.iat,
|
84 |
+
// exp: user.exp
|
85 |
+
};
|
86 |
+
return rUser;
|
87 |
+
} else {
|
88 |
+
const userInLowerCase = await this.userService.userRepository.findOne({
|
89 |
+
$or: [
|
90 |
+
{ email: identifier.toLowerCase() },
|
91 |
+
{ username: identifier.toLowerCase() },
|
92 |
+
],
|
93 |
+
});
|
94 |
+
if (userInLowerCase) {
|
95 |
+
const rUser = {
|
96 |
+
userId: userInLowerCase._id,
|
97 |
+
name: userInLowerCase.name,
|
98 |
+
username: user.username,
|
99 |
+
email: userInLowerCase.email,
|
100 |
+
roles: userInLowerCase.roles,
|
101 |
+
};
|
102 |
+
return rUser;
|
103 |
+
}
|
104 |
+
}
|
105 |
+
return null;
|
106 |
+
}
|
107 |
+
}
|
src/modules/auth/jwt-auth.guard.ts
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
3 |
+
import { AuthGuard } from '@nestjs/passport';
|
4 |
+
import { AuthService } from './auth.service';
|
5 |
+
|
6 |
+
@Injectable()
|
7 |
+
export class JwtAuthGuard extends AuthGuard('jwt') {
|
8 |
+
handleRequest(err, user, info) {
|
9 |
+
// console.log( user, err, info )
|
10 |
+
// You can throw an exception based on either "info" or "err" arguments
|
11 |
+
// console.log(user, info, '##################JWT');
|
12 |
+
if (err || !user) {
|
13 |
+
// console.log('ERROR', err);
|
14 |
+
throw err || new UnauthorizedException();
|
15 |
+
}
|
16 |
+
return user;
|
17 |
+
}
|
18 |
+
}
|
src/modules/auth/jwt.strategy.ts
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { ExtractJwt } from 'passport-jwt';
|
2 |
+
import { PassportStrategy } from '@nestjs/passport';
|
3 |
+
import { Injectable } from '@nestjs/common';
|
4 |
+
import { Strategy } from 'passport-custom';
|
5 |
+
import { AuthService } from './auth.service';
|
6 |
+
import { jwtDecode } from 'jwt-decode';
|
7 |
+
|
8 |
+
@Injectable()
|
9 |
+
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
|
10 |
+
constructor(private authService: AuthService) {
|
11 |
+
super();
|
12 |
+
}
|
13 |
+
async validate(req: Request): Promise<any> {
|
14 |
+
try {
|
15 |
+
const authHeader = String(req.headers['authorization'] || '');
|
16 |
+
if (authHeader.startsWith('Bearer ')) {
|
17 |
+
const token = authHeader.substring(7, authHeader.length);
|
18 |
+
const payload:any = jwtDecode(token) as any;
|
19 |
+
const user = this.authService.validateByEmail(payload.email)
|
20 |
+
return user ? user : false
|
21 |
+
}
|
22 |
+
else{
|
23 |
+
return false
|
24 |
+
}
|
25 |
+
} catch (error) {
|
26 |
+
return error
|
27 |
+
}
|
28 |
+
|
29 |
+
}
|
30 |
+
}
|
src/modules/auth/local-auth.guard.ts
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Injectable } from '@nestjs/common';
|
2 |
+
import { AuthGuard } from '@nestjs/passport';
|
3 |
+
|
4 |
+
@Injectable()
|
5 |
+
export class LocalAuthGuard extends AuthGuard('local') {}
|
src/modules/auth/local.strategy.ts
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Strategy } from 'passport-local';
|
2 |
+
import { PassportStrategy } from '@nestjs/passport';
|
3 |
+
import {
|
4 |
+
HttpException,
|
5 |
+
HttpStatus,
|
6 |
+
Injectable,
|
7 |
+
UnauthorizedException,
|
8 |
+
} from '@nestjs/common';
|
9 |
+
import { AuthService } from './auth.service';
|
10 |
+
|
11 |
+
@Injectable()
|
12 |
+
export class LocalStrategy extends PassportStrategy(Strategy) {
|
13 |
+
constructor(private authService: AuthService) {
|
14 |
+
super({ usernameField: 'identifier' });
|
15 |
+
}
|
16 |
+
|
17 |
+
async validate(
|
18 |
+
identifier: string,
|
19 |
+
password: string,
|
20 |
+
isAdmin: boolean = false,
|
21 |
+
): Promise<any> {
|
22 |
+
console.log(`IDENTIFIER =>`, identifier);
|
23 |
+
|
24 |
+
const user = await this.authService.validateUser(identifier, password);
|
25 |
+
if (!user) {
|
26 |
+
throw new UnauthorizedException('Incorrect username or password');
|
27 |
+
}
|
28 |
+
|
29 |
+
if ((user && user.deletedAt) || (user && user.isDeleted === true)) {
|
30 |
+
throw new HttpException(
|
31 |
+
'Your account has been deleted',
|
32 |
+
HttpStatus.FORBIDDEN,
|
33 |
+
);
|
34 |
+
}
|
35 |
+
return user;
|
36 |
+
}
|
37 |
+
}
|
src/modules/database/database.module.ts
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Module } from '@nestjs/common';
|
2 |
+
import { databaseProviders } from './database.provider';
|
3 |
+
import { propertyProviders } from '../property/property.provider';
|
4 |
+
import { usersProviders } from '../user/user.provider';
|
5 |
+
|
6 |
+
@Module({
|
7 |
+
providers: [...databaseProviders, ...propertyProviders, ...usersProviders],
|
8 |
+
exports: [...databaseProviders, ...propertyProviders, ...usersProviders],
|
9 |
+
})
|
10 |
+
export class DatabaseModule {}
|
src/modules/database/database.provider.ts
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import * as mongoose from 'mongoose';
|
2 |
+
import { env } from 'process';
|
3 |
+
|
4 |
+
export const databaseProviders = [
|
5 |
+
{
|
6 |
+
provide: 'DATABASE_CONNECTION',
|
7 |
+
useFactory: (): Promise<typeof mongoose> =>
|
8 |
+
mongoose.connect(
|
9 |
+
'mongodb+srv://rehmanwahlah248:[email protected]/property-listing?retryWrites=true&w=majority',
|
10 |
+
),
|
11 |
+
},
|
12 |
+
];
|
src/modules/property/property.controller.ts
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {
|
2 |
+
Body,
|
3 |
+
Controller,
|
4 |
+
Get,
|
5 |
+
HttpStatus,
|
6 |
+
Post,
|
7 |
+
Query,
|
8 |
+
Req,
|
9 |
+
Res,
|
10 |
+
UseGuards,
|
11 |
+
} from '@nestjs/common';
|
12 |
+
import { Response } from 'express';
|
13 |
+
import { CommonServices } from '../shared/common.service';
|
14 |
+
import { PropertyService } from './property.service';
|
15 |
+
|
16 |
+
@Controller('property')
|
17 |
+
export class PropertyController extends CommonServices {
|
18 |
+
constructor(private readonly propertyService: PropertyService) {
|
19 |
+
super();
|
20 |
+
}
|
21 |
+
|
22 |
+
@Get('')
|
23 |
+
async getPropertListings(@Res() res: Response, @Req() req): Promise<any> {
|
24 |
+
try {
|
25 |
+
const response = await this.propertyService.sharedFind({});
|
26 |
+
return this.sendResponse(
|
27 |
+
this.messages.Success,
|
28 |
+
response ?? 'NOT_FOUND',
|
29 |
+
HttpStatus.OK,
|
30 |
+
res,
|
31 |
+
);
|
32 |
+
} catch (error) {
|
33 |
+
return this.sendResponse(
|
34 |
+
'Internal server Error',
|
35 |
+
{},
|
36 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
37 |
+
res,
|
38 |
+
);
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
*
|
44 |
+
* @param query
|
45 |
+
* @param res
|
46 |
+
* @param req
|
47 |
+
*/
|
48 |
+
@Get('/listings/dashboard')
|
49 |
+
async getDashboardLisings(@Res() res, @Req() req) {
|
50 |
+
try {
|
51 |
+
const listings = await this.propertyService.propertyRepository
|
52 |
+
.find({})
|
53 |
+
.sort({ _id: -1 })
|
54 |
+
.limit(20);
|
55 |
+
|
56 |
+
this.sendResponse(this.messages.Success, listings, HttpStatus.OK, res);
|
57 |
+
} catch (error) {
|
58 |
+
console.error('error', error);
|
59 |
+
this.sendResponse(
|
60 |
+
this.messages.Error,
|
61 |
+
null,
|
62 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
63 |
+
res,
|
64 |
+
);
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
*
|
70 |
+
* @param query
|
71 |
+
* @param res
|
72 |
+
* @param req
|
73 |
+
*/
|
74 |
+
@Get('/listings')
|
75 |
+
async getDashboardActiveUsers(@Query() query, @Res() res, @Req() req) {
|
76 |
+
try {
|
77 |
+
const page = Number(query.page);
|
78 |
+
const resPerPage = query.resPerPage ? Number(query.resPerPage) : 20;
|
79 |
+
const search = query.search || ''; // Default to empty search if not provided
|
80 |
+
|
81 |
+
console.log(`search =>`, query);
|
82 |
+
|
83 |
+
const listings = await this.propertyService.propertyLisitng(
|
84 |
+
page,
|
85 |
+
resPerPage,
|
86 |
+
search,
|
87 |
+
);
|
88 |
+
|
89 |
+
this.sendResponse(this.messages.Success, listings, HttpStatus.OK, res);
|
90 |
+
} catch (error) {
|
91 |
+
console.error('error', error);
|
92 |
+
this.sendResponse(
|
93 |
+
this.messages.Error,
|
94 |
+
null,
|
95 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
96 |
+
res,
|
97 |
+
);
|
98 |
+
}
|
99 |
+
}
|
100 |
+
}
|
src/modules/property/property.module.ts
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Module } from '@nestjs/common';
|
2 |
+
import { PropertyController } from './property.controller';
|
3 |
+
import { PropertyService } from './property.service';
|
4 |
+
import { DatabaseModule } from '../database/database.module';
|
5 |
+
|
6 |
+
@Module({
|
7 |
+
imports: [DatabaseModule],
|
8 |
+
controllers: [PropertyController],
|
9 |
+
providers: [PropertyService],
|
10 |
+
exports: [PropertyService],
|
11 |
+
})
|
12 |
+
export class PropertyModule {}
|
src/modules/property/property.provider.ts
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Connection } from 'mongoose';
|
2 |
+
import { PROPERTIE, PROPERTY_REPOSITORY } from 'src/constants';
|
3 |
+
import { PropertySchema } from './property.schema';
|
4 |
+
|
5 |
+
export const propertyProviders = [
|
6 |
+
{
|
7 |
+
provide: PROPERTY_REPOSITORY,
|
8 |
+
useFactory: (connection: Connection) =>
|
9 |
+
connection.model(PROPERTIE, PropertySchema),
|
10 |
+
inject: ['DATABASE_CONNECTION'],
|
11 |
+
},
|
12 |
+
];
|
src/modules/property/property.schema.ts
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import * as mongoose from 'mongoose';
|
2 |
+
import { Document } from 'mongoose';
|
3 |
+
|
4 |
+
export interface IPropertyDocument extends Document {
|
5 |
+
title?: string;
|
6 |
+
price?: string;
|
7 |
+
id?: string;
|
8 |
+
imgs?: Array<[]>;
|
9 |
+
desc?: string;
|
10 |
+
features?: object;
|
11 |
+
thumbnail_summary?: string;
|
12 |
+
listing_url?: string;
|
13 |
+
createdAt?: Date;
|
14 |
+
updatedAt?: Date;
|
15 |
+
}
|
16 |
+
|
17 |
+
const PropertySchema = new mongoose.Schema<IPropertyDocument>(
|
18 |
+
{
|
19 |
+
title: { type: String },
|
20 |
+
price: { type: String },
|
21 |
+
id: { type: String },
|
22 |
+
desc: { type: String, unique: true },
|
23 |
+
features: { type: Object },
|
24 |
+
listing_url: { type: String },
|
25 |
+
imgs: [],
|
26 |
+
createdAt: { type: Date, default: Date.now },
|
27 |
+
updatedAt: { type: Date, default: Date.now },
|
28 |
+
},
|
29 |
+
{
|
30 |
+
toJSON: { versionKey: false },
|
31 |
+
},
|
32 |
+
);
|
33 |
+
|
34 |
+
export { PropertySchema };
|
src/modules/property/property.service.ts
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Inject, Injectable } from '@nestjs/common';
|
2 |
+
import { Model, Types } from 'mongoose';
|
3 |
+
import { sharedCrudService } from '../shared/sharedCrud.services';
|
4 |
+
import { PROPERTY_REPOSITORY } from 'src/constants';
|
5 |
+
import { IPropertyDocument } from './property.schema';
|
6 |
+
|
7 |
+
@Injectable()
|
8 |
+
export class PropertyService extends sharedCrudService {
|
9 |
+
constructor(
|
10 |
+
@Inject(PROPERTY_REPOSITORY)
|
11 |
+
readonly propertyRepository: Model<IPropertyDocument>,
|
12 |
+
) {
|
13 |
+
super(propertyRepository);
|
14 |
+
}
|
15 |
+
|
16 |
+
async propertyLisitng(
|
17 |
+
page: number,
|
18 |
+
resPerPage: number,
|
19 |
+
search: string,
|
20 |
+
): Promise<any> {
|
21 |
+
const query = [];
|
22 |
+
query.push({ id: { $exists: true } });
|
23 |
+
|
24 |
+
if (search) query.push({ title: { $regex: search, $options: 'i' } });
|
25 |
+
|
26 |
+
const [listings, tLisitngsCount] = await Promise.all([
|
27 |
+
this.propertyRepository
|
28 |
+
.find({ $and: [...query] })
|
29 |
+
.sort({ createdAt: -1 })
|
30 |
+
.skip(resPerPage * (page - 1))
|
31 |
+
.limit(resPerPage)
|
32 |
+
.exec(),
|
33 |
+
this.propertyRepository.countDocuments({ $and: [...query] }).exec(),
|
34 |
+
]);
|
35 |
+
|
36 |
+
return {
|
37 |
+
listings,
|
38 |
+
current_page: page,
|
39 |
+
pages: Math.ceil(tLisitngsCount / resPerPage),
|
40 |
+
total_listings: tLisitngsCount,
|
41 |
+
per_page: resPerPage,
|
42 |
+
};
|
43 |
+
}
|
44 |
+
}
|
src/modules/shared/common.service.ts
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { en } from 'src/locales/en';
|
2 |
+
import { I18nResolver } from 'i18n-ts';
|
3 |
+
import { Inject, Injectable } from '@nestjs/common';
|
4 |
+
import * as constants from '../../constants'
|
5 |
+
|
6 |
+
const i18n = {
|
7 |
+
en: en,
|
8 |
+
default: en,
|
9 |
+
};
|
10 |
+
|
11 |
+
@Injectable()
|
12 |
+
export class CommonServices{
|
13 |
+
public messages = new I18nResolver(i18n, 'en').translation;
|
14 |
+
public constants = constants;
|
15 |
+
constructor() {
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* name
|
20 |
+
*/
|
21 |
+
public sendResponse = (mesage, data, status, res) => {
|
22 |
+
return res.status(status).json({
|
23 |
+
message: mesage,
|
24 |
+
data: data,
|
25 |
+
});
|
26 |
+
};
|
27 |
+
}
|
src/modules/shared/sharedCrud.services.ts
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Injectable } from '@nestjs/common';
|
2 |
+
|
3 |
+
@Injectable()
|
4 |
+
export class sharedCrudService {
|
5 |
+
private service;
|
6 |
+
constructor(private serviceObj) {
|
7 |
+
// super();
|
8 |
+
this.service = serviceObj;
|
9 |
+
}
|
10 |
+
sharedCreate = (body) => {
|
11 |
+
return this.service.create(body);
|
12 |
+
};
|
13 |
+
sharedUpdate = (clause, body) => {
|
14 |
+
return this.service.updateOne(clause, body);
|
15 |
+
};
|
16 |
+
sharedFindOne = (clause) => {
|
17 |
+
return this.service.findOne(clause);
|
18 |
+
};
|
19 |
+
sharedFindOneAndUpdate = (clause, body, options) => {
|
20 |
+
return this.service.findOneAndUpdate(clause, body, options);
|
21 |
+
};
|
22 |
+
sharedFind = (clause) => {
|
23 |
+
return this.service.find(clause);
|
24 |
+
};
|
25 |
+
sharedDelete = (clause) => {
|
26 |
+
return this.service.deleteOne(clause);
|
27 |
+
};
|
28 |
+
}
|
src/modules/user/user.controller.ts
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {
|
2 |
+
Body,
|
3 |
+
Controller,
|
4 |
+
Get,
|
5 |
+
HttpStatus,
|
6 |
+
Post,
|
7 |
+
Query,
|
8 |
+
Req,
|
9 |
+
Res,
|
10 |
+
UseGuards,
|
11 |
+
} from '@nestjs/common';
|
12 |
+
import { UserService } from './user.service';
|
13 |
+
import { Response } from 'express';
|
14 |
+
import { CommonServices } from '../shared/common.service';
|
15 |
+
import { JwtAuthGuard } from '../auth/jwt-auth.guard'
|
16 |
+
|
17 |
+
|
18 |
+
@Controller('user')
|
19 |
+
export class UserController extends CommonServices {
|
20 |
+
constructor(
|
21 |
+
private readonly userService: UserService,
|
22 |
+
) {
|
23 |
+
super();
|
24 |
+
}
|
25 |
+
|
26 |
+
@Get('')
|
27 |
+
@UseGuards(JwtAuthGuard)
|
28 |
+
async getUserDetails(@Res() res: Response, @Req() req): Promise<any> {
|
29 |
+
try {
|
30 |
+
const response = await this.userService.userRepository.findById(
|
31 |
+
req.user.userId,
|
32 |
+
);
|
33 |
+
|
34 |
+
return this.sendResponse(
|
35 |
+
this.messages.Success,
|
36 |
+
response ?? 'NOT_FOUND',
|
37 |
+
HttpStatus.OK,
|
38 |
+
res,
|
39 |
+
);
|
40 |
+
} catch (error) {
|
41 |
+
return this.sendResponse(
|
42 |
+
'Internal server Error',
|
43 |
+
{},
|
44 |
+
HttpStatus.INTERNAL_SERVER_ERROR,
|
45 |
+
res,
|
46 |
+
);
|
47 |
+
}
|
48 |
+
}
|
49 |
+
}
|
src/modules/user/user.dto.ts
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {
|
2 |
+
IsEmail,
|
3 |
+
IsNotEmpty,
|
4 |
+
IsOptional,
|
5 |
+
IsString,
|
6 |
+
ValidateNested,
|
7 |
+
} from 'class-validator';
|
8 |
+
export class UpdateProfileDto {
|
9 |
+
@IsOptional()
|
10 |
+
firstName: string;
|
11 |
+
|
12 |
+
@IsOptional()
|
13 |
+
lastName: string;
|
14 |
+
|
15 |
+
@IsOptional()
|
16 |
+
username: string;
|
17 |
+
|
18 |
+
@IsOptional()
|
19 |
+
email: string;
|
20 |
+
|
21 |
+
avatar: any;
|
22 |
+
ats: any;
|
23 |
+
}
|
24 |
+
|
25 |
+
export class updatePasswordDto {
|
26 |
+
@IsNotEmpty()
|
27 |
+
password: string;
|
28 |
+
|
29 |
+
@IsNotEmpty()
|
30 |
+
newPassword: string;
|
31 |
+
|
32 |
+
@IsNotEmpty()
|
33 |
+
confirmPassword: string;
|
34 |
+
}
|
35 |
+
|
36 |
+
export class addRemoveFriendDto {
|
37 |
+
@IsNotEmpty()
|
38 |
+
userId: string;
|
39 |
+
|
40 |
+
@IsNotEmpty()
|
41 |
+
type: string;
|
42 |
+
}
|
43 |
+
export class validateEmailDto {
|
44 |
+
@IsString()
|
45 |
+
identifier: string;
|
46 |
+
}
|
47 |
+
export class NewsletterDto {
|
48 |
+
@IsString()
|
49 |
+
email: string;
|
50 |
+
}
|
51 |
+
export class validateEmailRegDto {
|
52 |
+
@IsString()
|
53 |
+
@IsEmail()
|
54 |
+
email: string;
|
55 |
+
}
|
src/modules/user/user.module.ts
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Module } from '@nestjs/common';
|
2 |
+
import { UserController } from './user.controller';
|
3 |
+
import { UserService } from './user.service';
|
4 |
+
import { DatabaseModule } from '../database/database.module';
|
5 |
+
import { AuthService } from '../auth/auth.service';
|
6 |
+
import { JwtService } from '@nestjs/jwt';
|
7 |
+
@Module({
|
8 |
+
imports: [DatabaseModule],
|
9 |
+
controllers: [UserController],
|
10 |
+
providers: [UserService, AuthService, JwtService],
|
11 |
+
exports: [UserService, AuthService, JwtService],
|
12 |
+
})
|
13 |
+
export class UserModule {}
|
src/modules/user/user.provider.ts
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Connection } from 'mongoose';
|
2 |
+
import { USERS, USER_REPOSITORY } from 'src/constants';
|
3 |
+
import { UserSchema } from './user.schema';
|
4 |
+
|
5 |
+
export const usersProviders = [
|
6 |
+
{
|
7 |
+
provide: USER_REPOSITORY,
|
8 |
+
useFactory: (connection: Connection) => connection.model(USERS, UserSchema),
|
9 |
+
inject: ['DATABASE_CONNECTION'],
|
10 |
+
},
|
11 |
+
];
|
src/modules/user/user.schema.ts
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import * as mongoose from 'mongoose';
|
2 |
+
import { Document } from 'mongoose';
|
3 |
+
import { USERS } from 'src/constants';
|
4 |
+
|
5 |
+
export interface IUserDocument extends Document {
|
6 |
+
name?: string;
|
7 |
+
username?: string;
|
8 |
+
email?: string;
|
9 |
+
avatar?: string;
|
10 |
+
isActive?: boolean;
|
11 |
+
isDeleted: boolean;
|
12 |
+
createdAt?: Date;
|
13 |
+
updatedAt?: Date;
|
14 |
+
deletedAt?: Date;
|
15 |
+
roles?: Array<string>;
|
16 |
+
password?: string;
|
17 |
+
session_id?: number;
|
18 |
+
login_location?: string;
|
19 |
+
preferred_location?: string;
|
20 |
+
preferred_listing_type?: string;
|
21 |
+
property_id?: string;
|
22 |
+
page_visit_duration?: number;
|
23 |
+
carousel_button_click_result_page?: number;
|
24 |
+
next_image_clicks_listing_page?: number;
|
25 |
+
read_more_click_result_page?: number;
|
26 |
+
read_more_click_listing_page?: number;
|
27 |
+
clicked_more_pictures?: number;
|
28 |
+
click_rate?: number;
|
29 |
+
bounce?: number;
|
30 |
+
title?: string;
|
31 |
+
price?: string;
|
32 |
+
bedrooms_?: string;
|
33 |
+
bathrooms?: string;
|
34 |
+
living_space_sqm?: string;
|
35 |
+
pool_?: number;
|
36 |
+
}
|
37 |
+
|
38 |
+
const UserSchema = new mongoose.Schema<IUserDocument>(
|
39 |
+
{
|
40 |
+
name: { type: String },
|
41 |
+
username: { type: String },
|
42 |
+
email: { type: String },
|
43 |
+
avatar: { type: String },
|
44 |
+
isActive: { type: Boolean, default: true },
|
45 |
+
isDeleted: { type: Boolean, default: false },
|
46 |
+
roles: [{ type: String, required: true, default: 'user' }],
|
47 |
+
password: { type: String, required: false },
|
48 |
+
// New fields added from IUserDocument
|
49 |
+
session_id: { type: Number },
|
50 |
+
login_location: { type: String },
|
51 |
+
preferred_location: { type: String },
|
52 |
+
preferred_listing_type: { type: String },
|
53 |
+
property_id: { type: String },
|
54 |
+
page_visit_duration: { type: Number, default: 0 },
|
55 |
+
carousel_button_click_result_page: { type: Number, default: 0 },
|
56 |
+
next_image_clicks_listing_page: { type: Number, default: 0 },
|
57 |
+
read_more_click_result_page: { type: Number, default: 0 },
|
58 |
+
read_more_click_listing_page: { type: Number, default: 0 },
|
59 |
+
clicked_more_pictures: { type: Number, default: 0 },
|
60 |
+
click_rate: { type: Number, default: 0 },
|
61 |
+
bounce: { type: Number, default: 0 },
|
62 |
+
title: { type: String },
|
63 |
+
price: { type: String },
|
64 |
+
bedrooms_: { type: String },
|
65 |
+
bathrooms: { type: String },
|
66 |
+
living_space_sqm: { type: String },
|
67 |
+
pool_: { type: Number },
|
68 |
+
|
69 |
+
createdAt: { type: Date, default: Date.now },
|
70 |
+
updatedAt: { type: Date, default: Date.now },
|
71 |
+
deletedAt: { type: Date },
|
72 |
+
},
|
73 |
+
{
|
74 |
+
toJSON: { versionKey: false },
|
75 |
+
},
|
76 |
+
);
|
77 |
+
|
78 |
+
export { UserSchema };
|
src/modules/user/user.service.ts
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Inject, Injectable } from '@nestjs/common';
|
2 |
+
import { Model, Types } from 'mongoose';
|
3 |
+
import { USER_REPOSITORY } from 'src/constants';
|
4 |
+
import { IUserDocument } from './user.schema';
|
5 |
+
import { sharedCrudService } from '../shared/sharedCrud.services';
|
6 |
+
|
7 |
+
interface UserDocument extends IUserDocument {
|
8 |
+
_id: Types.ObjectId;
|
9 |
+
}
|
10 |
+
|
11 |
+
@Injectable()
|
12 |
+
export class UserService extends sharedCrudService {
|
13 |
+
constructor(
|
14 |
+
@Inject(USER_REPOSITORY) readonly userRepository: Model<IUserDocument>,
|
15 |
+
) {
|
16 |
+
super(userRepository);
|
17 |
+
}
|
18 |
+
|
19 |
+
async getUserData(reqUser: any) {
|
20 |
+
const user = await this.userRepository.findById({
|
21 |
+
_id: reqUser._id,
|
22 |
+
});
|
23 |
+
return user;
|
24 |
+
}
|
25 |
+
}
|
test/app.e2e-spec.ts
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Test, TestingModule } from '@nestjs/testing';
|
2 |
+
import { INestApplication } from '@nestjs/common';
|
3 |
+
import * as request from 'supertest';
|
4 |
+
import { AppModule } from './../src/app.module';
|
5 |
+
|
6 |
+
describe('AppController (e2e)', () => {
|
7 |
+
let app: INestApplication;
|
8 |
+
|
9 |
+
beforeEach(async () => {
|
10 |
+
const moduleFixture: TestingModule = await Test.createTestingModule({
|
11 |
+
imports: [AppModule],
|
12 |
+
}).compile();
|
13 |
+
|
14 |
+
app = moduleFixture.createNestApplication();
|
15 |
+
await app.init();
|
16 |
+
});
|
17 |
+
|
18 |
+
it('/ (GET)', () => {
|
19 |
+
return request(app.getHttpServer())
|
20 |
+
.get('/')
|
21 |
+
.expect(200)
|
22 |
+
.expect('Hello World!');
|
23 |
+
});
|
24 |
+
});
|
test/jest-e2e.json
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"moduleFileExtensions": ["js", "json", "ts"],
|
3 |
+
"rootDir": ".",
|
4 |
+
"testEnvironment": "node",
|
5 |
+
"testRegex": ".e2e-spec.ts$",
|
6 |
+
"transform": {
|
7 |
+
"^.+\\.(t|j)s$": "ts-jest"
|
8 |
+
}
|
9 |
+
}
|
tsconfig.build.json
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"extends": "./tsconfig.json",
|
3 |
+
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
|
4 |
+
}
|
tsconfig.json
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"compilerOptions": {
|
3 |
+
"module": "commonjs",
|
4 |
+
"declaration": true,
|
5 |
+
"removeComments": true,
|
6 |
+
"emitDecoratorMetadata": true,
|
7 |
+
"experimentalDecorators": true,
|
8 |
+
"allowSyntheticDefaultImports": true,
|
9 |
+
"target": "ES2021",
|
10 |
+
"sourceMap": true,
|
11 |
+
"outDir": "./dist",
|
12 |
+
"baseUrl": "./",
|
13 |
+
"incremental": true,
|
14 |
+
"skipLibCheck": true,
|
15 |
+
"strictNullChecks": false,
|
16 |
+
"noImplicitAny": false,
|
17 |
+
"strictBindCallApply": false,
|
18 |
+
"forceConsistentCasingInFileNames": false,
|
19 |
+
"noFallthroughCasesInSwitch": false
|
20 |
+
}
|
21 |
+
}
|