feat(SPG-885): add validation login admin queue
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
14dd2880bc
commit
c897e4fcde
|
@ -0,0 +1,17 @@
|
|||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class AddColumnItemId1726139426994 implements MigrationInterface {
|
||||
name = 'AddColumnItemId1726139426994';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "users_login" ADD "item_id" uuid`);
|
||||
await queryRunner.query(`ALTER TABLE "log_users_login" ADD "item_id" uuid`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "log_users_login" DROP COLUMN "item_id"`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "users_login" DROP COLUMN "item_id"`);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class AddColumnItemName1726141393404 implements MigrationInterface {
|
||||
name = 'AddColumnItemName1726141393404';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "users_login" ADD "item_name" character varying`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "log_users_login" ADD "item_name" character varying`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "log_users_login" DROP COLUMN "item_name"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "users_login" DROP COLUMN "item_name"`,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -13,11 +13,15 @@ import { AuthAdminQueueController } from './infrastructure/auth-admin-queue.cont
|
|||
import { AuthAdminQueueOrchestrator } from './domain/auth-admin-queue.orchestrator';
|
||||
import { LoginAdminQueueManager } from './domain/managers/admin-queue/login-admin-queue.manager';
|
||||
import { LogoutAdminQueueManager } from './domain/managers/admin-queue/logout-admin-queue.manager';
|
||||
import { UserLoginModel } from 'src/modules/user-related/user/data/models/user-login.model';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot(),
|
||||
TypeOrmModule.forFeature([UserModel], CONNECTION_NAME.DEFAULT),
|
||||
TypeOrmModule.forFeature(
|
||||
[UserModel, UserLoginModel],
|
||||
CONNECTION_NAME.DEFAULT,
|
||||
),
|
||||
CqrsModule,
|
||||
],
|
||||
controllers: [AuthController, AuthAdminQueueController],
|
||||
|
|
|
@ -33,6 +33,10 @@ export class LoginAdminQueueManager extends BaseCustomManager<UserEntity> {
|
|||
}
|
||||
|
||||
async process(): Promise<void> {
|
||||
const itemLogin = await this.dataService.getLoginUserByItem(
|
||||
this.data.item_id,
|
||||
);
|
||||
|
||||
// get user active by username
|
||||
this.userLogin = await this.dataService.getOneByOptions({
|
||||
where: {
|
||||
|
@ -42,6 +46,7 @@ export class LoginAdminQueueManager extends BaseCustomManager<UserEntity> {
|
|||
},
|
||||
relations: ['user_login'],
|
||||
});
|
||||
|
||||
if (!this.userLogin) this.throwError();
|
||||
|
||||
// validasi password
|
||||
|
@ -51,13 +56,22 @@ export class LoginAdminQueueManager extends BaseCustomManager<UserEntity> {
|
|||
);
|
||||
if (!valid) this.throwError();
|
||||
|
||||
if (
|
||||
this.userLogin.user_login &&
|
||||
this.userLogin.role === UserRole.QUEUE_ADMIN
|
||||
) {
|
||||
const userLoginItem = await this.dataService.getOneByOptions({
|
||||
where: {
|
||||
id: itemLogin?.user_id,
|
||||
},
|
||||
});
|
||||
|
||||
if (this.userLogin.user_login) {
|
||||
throw new UnauthorizedException({
|
||||
statusCode: HttpStatus.UNAUTHORIZED,
|
||||
message: `Gagal! akun anda sudah login di perangkat lain.`,
|
||||
message: `Akun anda sudah login di perangkat lain.`,
|
||||
error: 'Unauthorized',
|
||||
});
|
||||
} else if (itemLogin) {
|
||||
throw new UnauthorizedException({
|
||||
statusCode: HttpStatus.UNAUTHORIZED,
|
||||
message: `"${userLoginItem.name}" masih login sebagai admin antrian `,
|
||||
error: 'Unauthorized',
|
||||
});
|
||||
}
|
||||
|
@ -69,6 +83,8 @@ export class LoginAdminQueueManager extends BaseCustomManager<UserEntity> {
|
|||
username: this.userLogin.username,
|
||||
role: this.userLogin.role,
|
||||
user_privilege_id: this.userLogin.user_privilege_id,
|
||||
item_id: this.data.item_id,
|
||||
item_name: this.data.item_name,
|
||||
};
|
||||
|
||||
Logger.debug('Sign Token Admin Queue', 'LoginAdminQueueManager');
|
||||
|
@ -79,22 +95,21 @@ export class LoginAdminQueueManager extends BaseCustomManager<UserEntity> {
|
|||
|
||||
Logger.debug('Update Refresh Token Admin Queue', 'LoginAdminQueueManager');
|
||||
|
||||
const newDataUser = { refresh_token: refreshToken };
|
||||
if (this.userLogin.role === UserRole.QUEUE_ADMIN) {
|
||||
Object.assign(newDataUser, {
|
||||
user_login: {
|
||||
user_id: this.userLogin.id,
|
||||
login_token: this.token,
|
||||
login_date: new Date().getTime(),
|
||||
},
|
||||
});
|
||||
}
|
||||
// Update refresh token
|
||||
await this.dataService.update(
|
||||
this.queryRunner,
|
||||
this.entityTarget,
|
||||
{ id: this.userLogin.id },
|
||||
newDataUser,
|
||||
{
|
||||
refresh_token: refreshToken,
|
||||
user_login: {
|
||||
user_id: this.userLogin.id,
|
||||
login_token: this.token,
|
||||
login_date: new Date().getTime(),
|
||||
item_id: this.data.item_id,
|
||||
item_name: this.data.item_name,
|
||||
},
|
||||
},
|
||||
);
|
||||
await this.publishEvents();
|
||||
|
||||
|
@ -113,6 +128,8 @@ export class LoginAdminQueueManager extends BaseCustomManager<UserEntity> {
|
|||
username: this.userLogin.username,
|
||||
role: this.userLogin.role,
|
||||
token: this.token,
|
||||
item_id: this.data.item_id,
|
||||
item_name: this.data.item_name,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -130,6 +147,8 @@ export class LoginAdminQueueManager extends BaseCustomManager<UserEntity> {
|
|||
user_id: this.userLogin.id,
|
||||
username: this.userLogin.username,
|
||||
created_at: new Date().getTime(),
|
||||
item_id: this.data.item_id,
|
||||
item_name: this.data.item_name,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Body, Controller, Delete, Param, Post, Put } from '@nestjs/common';
|
||||
import { ExcludePrivilege, Public } from 'src/core/guards';
|
||||
import { ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { LoginDto } from './dto/login.dto';
|
||||
import { LoginQueueDto } from './dto/login.dto';
|
||||
import { AuthAdminQueueOrchestrator } from '../domain/auth-admin-queue.orchestrator';
|
||||
|
||||
@Controller('v1/auth/queue')
|
||||
|
@ -10,7 +10,7 @@ export class AuthAdminQueueController {
|
|||
|
||||
@Post()
|
||||
@Public(true)
|
||||
async login(@Body() body: LoginDto) {
|
||||
async login(@Body() body: LoginQueueDto) {
|
||||
return await this.orchestrator.login(body);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,3 +11,21 @@ export class LoginDto implements LoginRequest {
|
|||
@IsString()
|
||||
password: string;
|
||||
}
|
||||
|
||||
export class LoginQueueDto implements LoginRequest {
|
||||
@ApiProperty({ name: 'username', required: true, default: 'superadmin' })
|
||||
@IsString()
|
||||
username: string;
|
||||
|
||||
@ApiProperty({ name: 'password', required: true, default: 'Eigen123!' })
|
||||
@IsString()
|
||||
password: string;
|
||||
|
||||
@ApiProperty({ name: 'item_id', required: true, default: 'string' })
|
||||
@IsString()
|
||||
item_id: string;
|
||||
|
||||
@ApiProperty({ name: 'item_name', required: true, default: 'string' })
|
||||
@IsString()
|
||||
item_name: string;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ import {
|
|||
import { SeasonPeriodDataService } from 'src/modules/season-related/season-period/data/services/season-period-data.service';
|
||||
import { SeasonPeriodModel } from 'src/modules/season-related/season-period/data/models/season-period.model';
|
||||
import { TransactionDemographyModel } from 'src/modules/transaction/transaction/data/models/transaction-demography.model';
|
||||
import { UserLoginModel } from 'src/modules/user-related/user/data/models/user-login.model';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
@ -61,6 +62,7 @@ import { TransactionDemographyModel } from 'src/modules/transaction/transaction/
|
|||
ItemRateModel,
|
||||
SeasonPeriodModel,
|
||||
UserModel,
|
||||
UserLoginModel,
|
||||
TransactionModel,
|
||||
TransactionTaxModel,
|
||||
TransactionItemModel,
|
||||
|
|
|
@ -20,6 +20,12 @@ export class LogUserLoginModel
|
|||
@Column({ type: 'uuid', nullable: true })
|
||||
user_id: string;
|
||||
|
||||
@Column({ type: 'uuid', nullable: true })
|
||||
item_id: string;
|
||||
|
||||
@Column({ type: 'varchar', nullable: true })
|
||||
item_name: string;
|
||||
|
||||
@Column({ type: 'varchar', nullable: true })
|
||||
username: string;
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ export interface LogUserLoginEntity extends BaseCoreEntity {
|
|||
type: LogUserType;
|
||||
role: UserRole;
|
||||
user_id: string;
|
||||
item_id: string;
|
||||
item_name: string;
|
||||
username: string;
|
||||
created_at: number;
|
||||
}
|
||||
|
|
|
@ -25,11 +25,15 @@ import { UserDataService } from '../user/data/services/user-data.service';
|
|||
import { UserReadService } from '../user/data/services/user-read.service';
|
||||
import { TenantItemReadController } from './infrastructure/tenant-item-read.controller';
|
||||
import { TenantItemDataController } from './infrastructure/tenant-item-data.controller';
|
||||
import { UserLoginModel } from '../user/data/models/user-login.model';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot(),
|
||||
TypeOrmModule.forFeature([UserModel], CONNECTION_NAME.DEFAULT),
|
||||
TypeOrmModule.forFeature(
|
||||
[UserModel, UserLoginModel],
|
||||
CONNECTION_NAME.DEFAULT,
|
||||
),
|
||||
CqrsModule,
|
||||
],
|
||||
controllers: [
|
||||
|
|
|
@ -19,6 +19,12 @@ export class UserLoginModel
|
|||
@Column('varchar', { name: 'user_id', nullable: true })
|
||||
user_id: string;
|
||||
|
||||
@Column({ type: 'uuid', nullable: true })
|
||||
item_id: string;
|
||||
|
||||
@Column({ type: 'varchar', nullable: true })
|
||||
item_name: string;
|
||||
|
||||
@OneToOne(() => UserModel, (model) => model.user_login, {
|
||||
onDelete: 'CASCADE',
|
||||
onUpdate: 'CASCADE',
|
||||
|
|
|
@ -4,14 +4,24 @@ import { UserEntity } from '../../domain/entities/user.entity';
|
|||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { UserModel } from '../models/user.model';
|
||||
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
|
||||
import { Repository } from 'typeorm';
|
||||
import { IsNull, Not, Repository } from 'typeorm';
|
||||
import { UserLoginModel } from '../models/user-login.model';
|
||||
|
||||
@Injectable()
|
||||
export class UserDataService extends BaseDataService<UserEntity> {
|
||||
constructor(
|
||||
@InjectRepository(UserModel, CONNECTION_NAME.DEFAULT)
|
||||
private repo: Repository<UserModel>,
|
||||
|
||||
@InjectRepository(UserLoginModel, CONNECTION_NAME.DEFAULT)
|
||||
private repoLoginUser: Repository<UserLoginModel>,
|
||||
) {
|
||||
super(repo);
|
||||
}
|
||||
|
||||
async getLoginUserByItem(itemId: string) {
|
||||
return this.repoLoginUser.findOne({
|
||||
where: { item_id: itemId, user_id: Not(IsNull()) },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,4 +3,6 @@ import { BaseCoreEntity } from 'src/core/modules/domain/entities/base-core.entit
|
|||
export interface UserLoginEntity extends BaseCoreEntity {
|
||||
login_date: number;
|
||||
login_token: string;
|
||||
item_id: string;
|
||||
item_name: string;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,8 @@ export class IndexUserManager extends BaseIndexManager<UserEntity> {
|
|||
|
||||
'user_login.id',
|
||||
'user_login.login_date',
|
||||
'user_login.item_id',
|
||||
'user_login.item_name',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue