mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2025-08-25 05:42:27 +00:00
refactor: refactor the code
This commit is contained in:
@ -4,12 +4,12 @@ import { JwtModule } from '@nestjs/jwt';
|
|||||||
import { JuniorModule } from '~/junior/junior.module';
|
import { JuniorModule } from '~/junior/junior.module';
|
||||||
import { UserModule } from '~/user/user.module';
|
import { UserModule } from '~/user/user.module';
|
||||||
import { AuthController } from './controllers';
|
import { AuthController } from './controllers';
|
||||||
import { AuthService, Oauth2Service } from './services';
|
import { AuthService } from './services';
|
||||||
import { AccessTokenStrategy } from './strategies';
|
import { AccessTokenStrategy } from './strategies';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [JwtModule.register({}), UserModule, JuniorModule, HttpModule],
|
imports: [JwtModule.register({}), UserModule, JuniorModule, HttpModule],
|
||||||
providers: [AuthService, AccessTokenStrategy, Oauth2Service],
|
providers: [AuthService, AccessTokenStrategy],
|
||||||
controllers: [AuthController],
|
controllers: [AuthController],
|
||||||
exports: [],
|
exports: [],
|
||||||
})
|
})
|
||||||
|
@ -86,25 +86,4 @@ export class AuthController {
|
|||||||
async logout(@Req() request: Request) {
|
async logout(@Req() request: Request) {
|
||||||
await this.authService.logout(request);
|
await this.authService.logout(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Post('biometric/enable')
|
|
||||||
// @HttpCode(HttpStatus.NO_CONTENT)
|
|
||||||
// @UseGuards(AccessTokenGuard)
|
|
||||||
// enableBiometric(@AuthenticatedUser() { sub }: IJwtPayload, @Body() enableBiometricDto: EnableBiometricRequestDto) {
|
|
||||||
// return this.authService.enableBiometric(sub, enableBiometricDto);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @Post('biometric/disable')
|
|
||||||
// @HttpCode(HttpStatus.NO_CONTENT)
|
|
||||||
// @UseGuards(AccessTokenGuard)
|
|
||||||
// disableBiometric(@AuthenticatedUser() { sub }: IJwtPayload, @Body() disableBiometricDto: DisableBiometricRequestDto) {
|
|
||||||
// return this.authService.disableBiometric(sub, disableBiometricDto);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @Post('junior/set-passcode')
|
|
||||||
// @HttpCode(HttpStatus.NO_CONTENT)
|
|
||||||
// @Public()
|
|
||||||
// setJuniorPasscode(@Body() setPasscodeDto: setJuniorPasswordRequestDto) {
|
|
||||||
// return this.authService.setJuniorPasscode(setPasscodeDto);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
|
||||||
import { i18nValidationMessage as i18n } from 'nestjs-i18n';
|
|
||||||
export class AppleAdditionalData {
|
|
||||||
@ApiProperty({ example: 'Ahmad' })
|
|
||||||
@IsString({ message: i18n('validation.IsString', { path: 'general', property: 'customer.firstName' }) })
|
|
||||||
@IsNotEmpty({ message: i18n('validation.IsNotEmpty', { path: 'general', property: 'customer.firstName' }) })
|
|
||||||
firstName!: string;
|
|
||||||
|
|
||||||
@ApiProperty({ example: 'Khan' })
|
|
||||||
@IsString({ message: i18n('validation.IsString', { path: 'general', property: 'customer.lastName' }) })
|
|
||||||
@IsNotEmpty({ message: i18n('validation.IsNotEmpty', { path: 'general', property: 'customer.lastName' }) })
|
|
||||||
lastName!: string;
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { Type } from 'class-transformer';
|
|
||||||
import { IsNotEmpty, IsOptional, IsString, ValidateNested } from 'class-validator';
|
|
||||||
import { i18nValidationMessage as i18n } from 'nestjs-i18n';
|
|
||||||
import { AppleAdditionalData } from './apple-additional-data.request.dto';
|
|
||||||
|
|
||||||
export class AppleLoginRequestDto {
|
|
||||||
@ApiProperty({ example: 'apple_token' })
|
|
||||||
@IsString({ message: i18n('validation.IsString', { path: 'general', property: 'auth.appleToken' }) })
|
|
||||||
@IsNotEmpty({ message: i18n('validation.IsNotEmpty', { path: 'general', property: 'auth.appleToken' }) })
|
|
||||||
appleToken!: string;
|
|
||||||
|
|
||||||
@ApiProperty({ type: AppleAdditionalData })
|
|
||||||
@ValidateNested({
|
|
||||||
each: true,
|
|
||||||
message: i18n('validation.ValidateNested', { path: 'general', property: 'auth.apple.additionalData' }),
|
|
||||||
})
|
|
||||||
@IsOptional()
|
|
||||||
@Type(() => AppleAdditionalData)
|
|
||||||
additionalData?: AppleAdditionalData;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
import { PickType } from '@nestjs/swagger';
|
|
||||||
import { EnableBiometricRequestDto } from './enable-biometric.request.dto';
|
|
||||||
|
|
||||||
export class DisableBiometricRequestDto extends PickType(EnableBiometricRequestDto, ['deviceId']) {}
|
|
@ -1,14 +0,0 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
|
||||||
import { i18nValidationMessage as i18n } from 'nestjs-i18n';
|
|
||||||
export class EnableBiometricRequestDto {
|
|
||||||
@ApiProperty({ example: 'device-id' })
|
|
||||||
@IsString({ message: i18n('validation.IsString', { path: 'general', property: 'auth.deviceId' }) })
|
|
||||||
@IsNotEmpty({ message: i18n('validation.IsNotEmpty', { path: 'general', property: 'auth.deviceId' }) })
|
|
||||||
deviceId!: string;
|
|
||||||
|
|
||||||
@ApiProperty({ example: 'publicKey' })
|
|
||||||
@IsString({ message: i18n('validation.IsString', { path: 'general', property: 'auth.publicKey' }) })
|
|
||||||
@IsNotEmpty({ message: i18n('validation.IsNotEmpty', { path: 'general', property: 'auth.publicKey' }) })
|
|
||||||
publicKey!: string;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
|
||||||
import { i18nValidationMessage as i18n } from 'nestjs-i18n';
|
|
||||||
|
|
||||||
export class GoogleLoginRequestDto {
|
|
||||||
@ApiProperty({ example: 'google_token' })
|
|
||||||
@IsString({ message: i18n('validation.IsString', { path: 'general', property: 'auth.googleToken' }) })
|
|
||||||
@IsNotEmpty({ message: i18n('validation.IsNotEmpty', { path: 'general', property: 'auth.googleToken' }) })
|
|
||||||
googleToken!: string;
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { IsEmail } from 'class-validator';
|
|
||||||
import { i18nValidationMessage as i18n } from 'nestjs-i18n';
|
|
||||||
export class SetEmailRequestDto {
|
|
||||||
@ApiProperty({ example: 'test@test.com' })
|
|
||||||
@IsEmail({}, { message: i18n('validation.IsEmail', { path: 'general', property: 'auth.email' }) })
|
|
||||||
email!: string;
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
export interface ApplePayload {
|
|
||||||
iss: string;
|
|
||||||
aud: string;
|
|
||||||
exp: number;
|
|
||||||
iat: number;
|
|
||||||
sub: string;
|
|
||||||
c_hash: string;
|
|
||||||
auth_time: number;
|
|
||||||
nonce_supported: boolean;
|
|
||||||
email?: string;
|
|
||||||
}
|
|
@ -13,8 +13,6 @@ import { User } from '../../user/entities';
|
|||||||
import {
|
import {
|
||||||
ChangePasswordRequestDto,
|
ChangePasswordRequestDto,
|
||||||
CreateUnverifiedUserRequestDto,
|
CreateUnverifiedUserRequestDto,
|
||||||
DisableBiometricRequestDto,
|
|
||||||
EnableBiometricRequestDto,
|
|
||||||
ForgetPasswordRequestDto,
|
ForgetPasswordRequestDto,
|
||||||
LoginRequestDto,
|
LoginRequestDto,
|
||||||
SendForgetPasswordOtpRequestDto,
|
SendForgetPasswordOtpRequestDto,
|
||||||
@ -24,7 +22,6 @@ import {
|
|||||||
} from '../dtos/request';
|
} from '../dtos/request';
|
||||||
import { Roles } from '../enums';
|
import { Roles } from '../enums';
|
||||||
import { IJwtPayload, ILoginResponse } from '../interfaces';
|
import { IJwtPayload, ILoginResponse } from '../interfaces';
|
||||||
import { Oauth2Service } from './oauth2.service';
|
|
||||||
|
|
||||||
const ONE_THOUSAND = 1000;
|
const ONE_THOUSAND = 1000;
|
||||||
const SALT_ROUNDS = 10;
|
const SALT_ROUNDS = 10;
|
||||||
@ -40,7 +37,6 @@ export class AuthService {
|
|||||||
private readonly deviceService: DeviceService,
|
private readonly deviceService: DeviceService,
|
||||||
private readonly userTokenService: UserTokenService,
|
private readonly userTokenService: UserTokenService,
|
||||||
private readonly cacheService: CacheService,
|
private readonly cacheService: CacheService,
|
||||||
private readonly oauth2Service: Oauth2Service,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async sendRegisterOtp(body: CreateUnverifiedUserRequestDto) {
|
async sendRegisterOtp(body: CreateUnverifiedUserRequestDto) {
|
||||||
@ -100,43 +96,6 @@ export class AuthService {
|
|||||||
return [tokens, user];
|
return [tokens, user];
|
||||||
}
|
}
|
||||||
|
|
||||||
async enableBiometric(userId: string, { deviceId, publicKey }: EnableBiometricRequestDto) {
|
|
||||||
this.logger.log(`Enabling biometric for user with id ${userId}`);
|
|
||||||
const device = await this.deviceService.findUserDeviceById(deviceId, userId);
|
|
||||||
|
|
||||||
if (!device) {
|
|
||||||
this.logger.log(`Device not found, creating new device for user with id ${userId}`);
|
|
||||||
return this.deviceService.createDevice({
|
|
||||||
deviceId,
|
|
||||||
userId,
|
|
||||||
publicKey,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (device.publicKey) {
|
|
||||||
this.logger.error(`Biometric already enabled for user with id ${userId}`);
|
|
||||||
throw new BadRequestException('AUTH.BIOMETRIC_ALREADY_ENABLED');
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.deviceService.updateDevice(deviceId, { publicKey });
|
|
||||||
}
|
|
||||||
|
|
||||||
async disableBiometric(userId: string, { deviceId }: DisableBiometricRequestDto) {
|
|
||||||
const device = await this.deviceService.findUserDeviceById(deviceId, userId);
|
|
||||||
|
|
||||||
if (!device) {
|
|
||||||
this.logger.error(`Device not found for user with id ${userId} and device id ${deviceId}`);
|
|
||||||
throw new BadRequestException('AUTH.DEVICE_NOT_FOUND');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!device.publicKey) {
|
|
||||||
this.logger.error(`Biometric already disabled for user with id ${userId}`);
|
|
||||||
throw new BadRequestException('AUTH.BIOMETRIC_ALREADY_DISABLED');
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.deviceService.updateDevice(deviceId, { publicKey: null });
|
|
||||||
}
|
|
||||||
|
|
||||||
async sendForgetPasswordOtp({ countryCode, phoneNumber }: SendForgetPasswordOtpRequestDto) {
|
async sendForgetPasswordOtp({ countryCode, phoneNumber }: SendForgetPasswordOtpRequestDto) {
|
||||||
this.logger.log(`Sending forget password OTP to ${countryCode + phoneNumber}`);
|
this.logger.log(`Sending forget password OTP to ${countryCode + phoneNumber}`);
|
||||||
const user = await this.userService.findUserOrThrow({ countryCode, phoneNumber });
|
const user = await this.userService.findUserOrThrow({ countryCode, phoneNumber });
|
||||||
@ -319,40 +278,6 @@ export class AuthService {
|
|||||||
return [tokens, user];
|
return [tokens, user];
|
||||||
}
|
}
|
||||||
|
|
||||||
// private async loginWithBiometric(loginDto: LoginRequestDto, deviceId: string): Promise<[ILoginResponse, User]> {
|
|
||||||
// const user = await this.userService.findUserOrThrow({ email: loginDto.email });
|
|
||||||
|
|
||||||
// this.logger.log(`validating biometric for user with email ${loginDto.email}`);
|
|
||||||
// const device = await this.deviceService.findUserDeviceById(deviceId, user.id);
|
|
||||||
|
|
||||||
// if (!device) {
|
|
||||||
// this.logger.error(`Device not found for user with email ${loginDto.email} and device id ${deviceId}`);
|
|
||||||
// throw new UnauthorizedException('AUTH.DEVICE_NOT_FOUND');
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!device.publicKey) {
|
|
||||||
// this.logger.error(`Biometric not enabled for user with email ${loginDto.email}`);
|
|
||||||
// throw new UnauthorizedException('AUTH.BIOMETRIC_NOT_ENABLED');
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const cleanToken = removePadding(loginDto.signature);
|
|
||||||
// const isValidToken = await verifySignature(
|
|
||||||
// device.publicKey,
|
|
||||||
// cleanToken,
|
|
||||||
// `${user.email} - ${device.deviceId}`,
|
|
||||||
// 'SHA1',
|
|
||||||
// );
|
|
||||||
|
|
||||||
// if (!isValidToken) {
|
|
||||||
// this.logger.error(`Invalid biometric for user with email ${loginDto.email}`);
|
|
||||||
// throw new UnauthorizedException('AUTH.INVALID_BIOMETRIC');
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const tokens = await this.generateAuthToken(user);
|
|
||||||
// this.logger.log(`Biometric validated successfully for user with email ${loginDto.email}`);
|
|
||||||
// return [tokens, user];
|
|
||||||
// }
|
|
||||||
|
|
||||||
private async generateAuthToken(user: User) {
|
private async generateAuthToken(user: User) {
|
||||||
this.logger.log(`Generating auth token for user with id ${user.id}`);
|
this.logger.log(`Generating auth token for user with id ${user.id}`);
|
||||||
const [accessToken, refreshToken] = await Promise.all([
|
const [accessToken, refreshToken] = await Promise.all([
|
||||||
|
@ -1,2 +1 @@
|
|||||||
export * from './auth.service';
|
export * from './auth.service';
|
||||||
export * from './oauth2.service';
|
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
import { HttpService } from '@nestjs/axios';
|
|
||||||
import { Injectable, Logger, UnauthorizedException } from '@nestjs/common';
|
|
||||||
import { ConfigService } from '@nestjs/config';
|
|
||||||
import { JwtService } from '@nestjs/jwt';
|
|
||||||
import { OAuth2Client } from 'google-auth-library';
|
|
||||||
import jwkToPem from 'jwk-to-pem';
|
|
||||||
import { lastValueFrom } from 'rxjs';
|
|
||||||
import { ApplePayload } from '../interfaces';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class Oauth2Service {
|
|
||||||
private readonly logger = new Logger(Oauth2Service.name);
|
|
||||||
private appleKeysEndpoint = 'https://appleid.apple.com/auth/keys';
|
|
||||||
private appleIssuer = 'https://appleid.apple.com';
|
|
||||||
private readonly googleWebClientId = this.configService.getOrThrow('GOOGLE_WEB_CLIENT_ID');
|
|
||||||
private readonly googleAndroidClientId = this.configService.getOrThrow('GOOGLE_ANDROID_CLIENT_ID');
|
|
||||||
private readonly googleIosClientId = this.configService.getOrThrow('GOOGLE_IOS_CLIENT_ID');
|
|
||||||
private readonly client = new OAuth2Client();
|
|
||||||
constructor(
|
|
||||||
private readonly httpService: HttpService,
|
|
||||||
private readonly jwtService: JwtService,
|
|
||||||
private readonly configService: ConfigService,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async verifyAppleToken(appleToken: string): Promise<ApplePayload> {
|
|
||||||
try {
|
|
||||||
const response = await lastValueFrom(this.httpService.get(this.appleKeysEndpoint));
|
|
||||||
|
|
||||||
const keys = response.data.keys;
|
|
||||||
|
|
||||||
const decodedHeader = this.jwtService.decode(appleToken, { complete: true })?.header;
|
|
||||||
|
|
||||||
if (!decodedHeader) {
|
|
||||||
this.logger.error(`Invalid apple token`);
|
|
||||||
throw new UnauthorizedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
const keyId = decodedHeader.kid;
|
|
||||||
|
|
||||||
const appleKey = keys.find((key: any) => key.kid === keyId);
|
|
||||||
|
|
||||||
if (!appleKey) {
|
|
||||||
this.logger.error(`Invalid apple token`);
|
|
||||||
throw new UnauthorizedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
const publicKey = jwkToPem(appleKey);
|
|
||||||
|
|
||||||
const payload = this.jwtService.verify(appleToken, {
|
|
||||||
publicKey,
|
|
||||||
algorithms: ['RS256'],
|
|
||||||
audience: this.configService.getOrThrow('APPLE_CLIENT_ID').split(','),
|
|
||||||
issuer: this.appleIssuer,
|
|
||||||
});
|
|
||||||
|
|
||||||
return payload;
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error(`Error verifying apple token: ${error} `);
|
|
||||||
throw new UnauthorizedException(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async verifyGoogleToken(googleToken: string): Promise<any> {
|
|
||||||
try {
|
|
||||||
const ticket = await this.client.verifyIdToken({
|
|
||||||
idToken: googleToken,
|
|
||||||
audience: [this.googleWebClientId, this.googleAndroidClientId, this.googleIosClientId],
|
|
||||||
});
|
|
||||||
|
|
||||||
const payload = ticket.getPayload();
|
|
||||||
|
|
||||||
if (!payload) {
|
|
||||||
this.logger.error(`payload not found in google token`);
|
|
||||||
throw new UnauthorizedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return payload;
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error(`Invalid google token`, error);
|
|
||||||
throw new UnauthorizedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,95 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class CreateNeoleapRelatedEntities1754915164809 implements MigrationInterface {
|
||||||
|
name = 'CreateNeoleapRelatedEntities1754915164809';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" DROP CONSTRAINT "FK_e7574892da11dd01de5cfc46499"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "transactions" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "transaction_scope" character varying NOT NULL, "transaction_type" character varying NOT NULL DEFAULT 'EXTERNAL', "card_reference" character varying, "account_reference" character varying, "transaction_id" character varying, "card_masked_number" character varying, "transaction_date" TIMESTAMP WITH TIME ZONE, "rrn" character varying, "transaction_amount" numeric(12,2) NOT NULL, "transaction_currency" character varying NOT NULL, "billing_amount" numeric(12,2) NOT NULL, "settlement_amount" numeric(12,2) NOT NULL, "fees" numeric(12,2) NOT NULL, "vat_on_fees" numeric(12,2) NOT NULL DEFAULT '0', "card_id" uuid, "account_id" uuid, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), CONSTRAINT "UQ_9162bf9ab4e31961a8f7932974c" UNIQUE ("transaction_id"), CONSTRAINT "PK_a219afd8dd77ed80f5a862f1db9" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "accounts" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "account_reference" character varying(255) NOT NULL, "account_number" character varying(255) NOT NULL, "iban" character varying(255) NOT NULL, "currency" character varying(255) NOT NULL, "balance" numeric(10,2) NOT NULL DEFAULT '0', "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), CONSTRAINT "UQ_829183fe026a0ce5fc8026b2417" UNIQUE ("account_reference"), CONSTRAINT "PK_5a7a02c20412299d198e097a8fe" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE UNIQUE INDEX "IDX_829183fe026a0ce5fc8026b241" ON "accounts" ("account_reference") `,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_ffd1ae96513bfb2c6eada0f7d3" ON "accounts" ("account_number") `);
|
||||||
|
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_9a4b004902294416b096e7556e" ON "accounts" ("iban") `);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "cards" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "card_reference" character varying NOT NULL, "vpan" character varying NOT NULL, "first_six_digits" character varying(6) NOT NULL, "last_four_digits" character varying(4) NOT NULL, "expiry" character varying NOT NULL, "customer_type" character varying NOT NULL, "color" character varying NOT NULL DEFAULT 'BLUE', "status" character varying NOT NULL DEFAULT 'PENDING', "statusDescription" character varying NOT NULL DEFAULT 'PENDING_ACTIVATION', "limit" numeric(10,2) NOT NULL DEFAULT '0', "scheme" character varying NOT NULL DEFAULT 'VISA', "issuer" character varying NOT NULL, "customer_id" uuid NOT NULL, "parent_id" uuid, "account_id" uuid NOT NULL, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), CONSTRAINT "PK_5f3269634705fdff4a9935860fc" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_4f7df5c5dc950295dc417a11d8" ON "cards" ("card_reference") `);
|
||||||
|
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_1ec2ef68b0370f26639261e87b" ON "cards" ("vpan") `);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" DROP CONSTRAINT "REL_e7574892da11dd01de5cfc4649"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" DROP COLUMN "profile_picture_id"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" ADD "first_name" character varying(255) NOT NULL`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" ADD "last_name" character varying(255) NOT NULL`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" ADD "profile_picture_id" uuid`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "users" ADD CONSTRAINT "UQ_02ec15de199e79a0c46869895f4" UNIQUE ("profile_picture_id")`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "documents" ADD "upload_status" character varying(255) NOT NULL DEFAULT 'NOT_UPLOADED'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" ADD "country" character varying(255)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" ADD "region" character varying(255)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" ADD "city" character varying(255)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" ADD "neighborhood" character varying(255)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" ADD "street" character varying(255)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" ADD "building" character varying(255)`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "users" ADD CONSTRAINT "FK_02ec15de199e79a0c46869895f4" FOREIGN KEY ("profile_picture_id") REFERENCES "documents"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD CONSTRAINT "FK_80ad48141be648db2d84ff32f79" FOREIGN KEY ("card_id") REFERENCES "cards"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD CONSTRAINT "FK_49c0d6e8ba4bfb5582000d851f0" FOREIGN KEY ("account_id") REFERENCES "accounts"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "cards" ADD CONSTRAINT "FK_8ba18e7060c38ddae12e5bdf907" FOREIGN KEY ("parent_id") REFERENCES "customers"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "cards" ADD CONSTRAINT "FK_2fd0ee722ec57594d2e448c73d7" FOREIGN KEY ("customer_id") REFERENCES "customers"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "cards" ADD CONSTRAINT "FK_b2874ef49ff7da2dee49e4bc6d3" FOREIGN KEY ("account_id") REFERENCES "accounts"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "cards" DROP CONSTRAINT "FK_b2874ef49ff7da2dee49e4bc6d3"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "cards" DROP CONSTRAINT "FK_2fd0ee722ec57594d2e448c73d7"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "cards" DROP CONSTRAINT "FK_8ba18e7060c38ddae12e5bdf907"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "transactions" DROP CONSTRAINT "FK_49c0d6e8ba4bfb5582000d851f0"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "transactions" DROP CONSTRAINT "FK_80ad48141be648db2d84ff32f79"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" DROP CONSTRAINT "FK_02ec15de199e79a0c46869895f4"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" DROP COLUMN "building"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" DROP COLUMN "street"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" DROP COLUMN "neighborhood"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" DROP COLUMN "city"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" DROP COLUMN "region"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" DROP COLUMN "country"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "documents" DROP COLUMN "upload_status"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" DROP CONSTRAINT "UQ_02ec15de199e79a0c46869895f4"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "profile_picture_id"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "last_name"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "first_name"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "customers" ADD "profile_picture_id" uuid`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "customers" ADD CONSTRAINT "REL_e7574892da11dd01de5cfc4649" UNIQUE ("profile_picture_id")`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP INDEX "public"."IDX_1ec2ef68b0370f26639261e87b"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "public"."IDX_4f7df5c5dc950295dc417a11d8"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "cards"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "public"."IDX_9a4b004902294416b096e7556e"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "public"."IDX_ffd1ae96513bfb2c6eada0f7d3"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "public"."IDX_829183fe026a0ce5fc8026b241"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "accounts"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "transactions"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "customers" ADD CONSTRAINT "FK_e7574892da11dd01de5cfc46499" FOREIGN KEY ("profile_picture_id") REFERENCES "documents"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,2 +1,3 @@
|
|||||||
export * from './1754913378460-initial-migration';
|
export * from './1754913378460-initial-migration';
|
||||||
export * from './1754913378461-seed-default-avatar';
|
export * from './1754913378461-seed-default-avatar';
|
||||||
|
export * from './1754915164809-create-neoleap-related-entities';
|
||||||
|
Reference in New Issue
Block a user