Skip to content

Commit

Permalink
feat: add login history, country at create/sign up
Browse files Browse the repository at this point in the history
  • Loading branch information
andrechristikan committed Jun 16, 2024
1 parent d263e9a commit 9bbdee6
Show file tree
Hide file tree
Showing 27 changed files with 1,732 additions and 1,180 deletions.
24 changes: 12 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"rollback": "nestjs-command remove:country && nestjs-command remove:apikey && nestjs-command remove:user && nestjs-command remove:role"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.591.0",
"@aws-sdk/client-ses": "^3.590.0",
"@aws-sdk/client-s3": "^3.598.0",
"@aws-sdk/client-ses": "^3.598.0",
"@casl/ability": "^6.7.1",
"@faker-js/faker": "^8.4.1",
"@nestjs/axios": "^3.0.2",
Expand All @@ -47,16 +47,16 @@
"@nestjs/schedule": "^4.0.2",
"@nestjs/swagger": "^7.3.1",
"@nestjs/terminus": "^10.2.3",
"@nestjs/throttler": "^5.1.2",
"@nestjs/throttler": "^5.2.0",
"@ntegral/nestjs-sentry": "^4.0.1",
"@sentry/node": "^8.7.0",
"@sentry/node": "^8.9.2",
"axios": "^1.7.2",
"bcryptjs": "^2.4.3",
"case": "^1.6.3",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"crypto-js": "^4.2.0",
"google-auth-library": "^9.10.0",
"google-auth-library": "^9.11.0",
"helmet": "^7.1.0",
"moment": "^2.30.1",
"moment-timezone": "^0.5.45",
Expand All @@ -77,7 +77,7 @@
"devDependencies": {
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@eslint/js": "^9.4.0",
"@eslint/js": "^9.5.0",
"@nestjs/cli": "^10.3.2",
"@nestjs/schematics": "^10.1.1",
"@nestjs/testing": "^10.3.9",
Expand All @@ -89,7 +89,7 @@
"@types/eslint__js": "^8.42.3",
"@types/express": "^4.17.21",
"@types/jest": "^29.5.12",
"@types/lodash": "^4.17.4",
"@types/lodash": "^4.17.5",
"@types/ms": "^0.7.34",
"@types/multer": "^1.4.11",
"@types/node": "^20.14.2",
Expand All @@ -98,20 +98,20 @@
"@types/supertest": "^6.0.2",
"@types/uuid": "^9.0.8",
"cspell": "^8.8.4",
"eslint": "^9.4.0",
"eslint": "^9.5.0",
"eslint-config-prettier": "^9.1.0",
"husky": "^9.0.11",
"jest": "^29.7.0",
"lint-staged": "^15.2.5",
"prettier": "^3.3.1",
"lint-staged": "^15.2.7",
"prettier": "^3.3.2",
"stop-only": "^3.3.2",
"supertest": "^7.0.0",
"ts-jest": "^29.1.4",
"ts-jest": "^29.1.5",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.2",
"ts-prune": "^0.10.3",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.4.5",
"typescript-eslint": "^7.12.0"
"typescript-eslint": "^7.13.0"
}
}
13 changes: 12 additions & 1 deletion src/migration/seeds/migration.user.seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import { RoleService } from 'src/modules/role/services/role.service';
import { ENUM_USER_SIGN_UP_FROM } from 'src/modules/user/constants/user.enum.constant';
import { UserPasswordService } from 'src/modules/user/services/user-password.service';
import { UserHistoryService } from 'src/modules/user/services/user-history.service';
import { CountryDoc } from 'src/modules/country/repository/entities/country.entity';
import { CountryService } from 'src/modules/country/services/country.service';
import { ENUM_MESSAGE_LANGUAGE } from 'src/common/message/constants/message.enum.constant';

@Injectable()
export class MigrationUserSeed {
Expand All @@ -16,7 +19,8 @@ export class MigrationUserSeed {
private readonly userService: UserService,
private readonly userPasswordService: UserPasswordService,
private readonly userHistoryService: UserHistoryService,
private readonly roleService: RoleService
private readonly roleService: RoleService,
private readonly countryService: CountryService
) {}

@Command({
Expand All @@ -33,13 +37,17 @@ export class MigrationUserSeed {
const memberRole: RoleDoc =
await this.roleService.findOneByName('member');
const userRole: RoleDoc = await this.roleService.findOneByName('user');
const country: CountryDoc = await this.countryService.findOneByAlpha2(
ENUM_MESSAGE_LANGUAGE.EN
);

try {
const user1: UserDoc = await this.userService.create(
{
role: superAdminRole._id,
name: 'superadmin',
email: 'superadmin@mail.com',
country: country._id,
},
passwordHash,
ENUM_USER_SIGN_UP_FROM.ADMIN
Expand All @@ -50,6 +58,7 @@ export class MigrationUserSeed {
role: adminRole._id,
name: 'admin',
email: 'admin@mail.com',
country: country._id,
},
passwordHash,
ENUM_USER_SIGN_UP_FROM.ADMIN
Expand All @@ -59,6 +68,7 @@ export class MigrationUserSeed {
role: userRole._id,
name: 'user',
email: 'user@mail.com',
country: country._id,
},
passwordHash,
ENUM_USER_SIGN_UP_FROM.ADMIN
Expand All @@ -68,6 +78,7 @@ export class MigrationUserSeed {
role: memberRole._id,
name: 'member',
email: 'member@mail.com',
country: country._id,
},
passwordHash,
ENUM_USER_SIGN_UP_FROM.ADMIN
Expand Down
8 changes: 8 additions & 0 deletions src/modules/country/interfaces/country.service.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ export interface ICountryService {
find: Record<string, any>,
options?: IDatabaseFindOneOptions
): Promise<CountryDoc>;
findOneByAlpha2(
alpha2: string,
options?: IDatabaseFindOneOptions
): Promise<CountryDoc>;
findOneByName(
name: string,
options?: IDatabaseFindOneOptions
): Promise<CountryDoc>;
findOneActiveByPhoneCode(
phoneCode: string,
options?: IDatabaseFindOneOptions
Expand Down
21 changes: 21 additions & 0 deletions src/modules/country/services/country.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Injectable } from '@nestjs/common';
import { plainToInstance } from 'class-transformer';
import { DatabaseQueryContain } from 'src/common/database/decorators/database.decorator';
import {
IDatabaseCreateManyOptions,
IDatabaseFindAllOptions,
Expand Down Expand Up @@ -35,6 +36,26 @@ export class CountryService implements ICountryService {
return this.countryRepository.findOne<CountryDoc>(find, options);
}

async findOneByName(
name: string,
options?: IDatabaseFindOneOptions
): Promise<CountryDoc> {
return this.countryRepository.findOne<CountryDoc>(
DatabaseQueryContain('name', name),
options
);
}

async findOneByAlpha2(
alpha2: string,
options?: IDatabaseFindOneOptions
): Promise<CountryDoc> {
return this.countryRepository.findOne<CountryDoc>(
DatabaseQueryContain('alpha2Code', alpha2),
options
);
}

async findOneActiveByPhoneCode(
phoneCode: string,
options?: IDatabaseFindOneOptions
Expand Down
35 changes: 14 additions & 21 deletions src/modules/user/controllers/user.admin.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,16 +147,14 @@ export class UserAdminController {
...role,
};

const users: IUserDoc[] = await this.userService.findAllWithRoles(
find,
{
const users: IUserDoc[] =
await this.userService.findAllWithRoleAndCountry(find, {
paging: {
limit: _limit,
offset: _offset,
},
order: _order,
}
);
});
const total: number = await this.userService.getTotal(find);
const totalPage: number = this.paginationService.totalPage(
total,
Expand Down Expand Up @@ -185,7 +183,7 @@ export class UserAdminController {
@Param('user', RequestRequiredPipe, UserParsePipe) user: UserDoc
): Promise<IResponse<UserProfileResponseDto>> {
const userWithRole: IUserDoc =
await this.userService.joinWithRole(user);
await this.userService.joinWithRoleAndCountry(user);
const mapped: UserProfileResponseDto =
await this.userService.mapProfile(userWithRole);

Expand Down Expand Up @@ -291,32 +289,27 @@ export class UserAdminController {
@Post('/create')
async create(
@Body()
{ email, mobileNumber, role, name }: UserCreateRequestDto
{ email, role, name, country }: UserCreateRequestDto
): Promise<IResponse<DatabaseIdResponseDto>> {
if (mobileNumber) {
const checkCountry = await this.countryService.findOneActiveById(
mobileNumber.country
);
if (!checkCountry) {
throw new NotFoundException({
statusCode: ENUM_COUNTRY_STATUS_CODE_ERROR.NOT_FOUND_ERROR,
message: 'country.error.notFound',
});
}
}

const promises: Promise<any>[] = [
this.roleService.findOneById(role),
this.userService.existByEmail(email),
this.countryService.findOneActiveById(country),
];

const [checkRole, emailExist] = await Promise.all(promises);
const [checkRole, emailExist, checkCountry] =
await Promise.all(promises);

if (!checkRole) {
throw new NotFoundException({
statusCode: ENUM_ROLE_STATUS_CODE_ERROR.NOT_FOUND_ERROR,
message: 'role.error.notFound',
});
} else if (!checkCountry) {
throw new NotFoundException({
statusCode: ENUM_COUNTRY_STATUS_CODE_ERROR.NOT_FOUND_ERROR,
message: 'country.error.notFound',
});
} else if (emailExist) {
throw new ConflictException({
statusCode: ENUM_USER_STATUS_CODE_ERROR.EMAIL_EXIST_ERROR,
Expand All @@ -336,7 +329,7 @@ export class UserAdminController {
const created = await this.userService.create(
{
email,
mobileNumber,
country,
role,
name,
},
Expand Down
Loading

0 comments on commit 9bbdee6

Please sign in to comment.