feature: Create user data module #6
|
@ -10,6 +10,7 @@ import { SecurityHeadersMiddleware } from './middleware/security-middleware/secu
|
||||||
import { AuthModule } from './modules/auth-module/auth.module';
|
import { AuthModule } from './modules/auth-module/auth.module';
|
||||||
import { AccessTokenGuard } from './modules/auth-module/common/guards';
|
import { AccessTokenGuard } from './modules/auth-module/common/guards';
|
||||||
import { DatabaseModule } from './modules/database-module/database.module';
|
import { DatabaseModule } from './modules/database-module/database.module';
|
||||||
|
import { UserModule } from './modules/user-module/user.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -18,6 +19,7 @@ import { DatabaseModule } from './modules/database-module/database.module';
|
||||||
}),
|
}),
|
||||||
DatabaseModule,
|
DatabaseModule,
|
||||||
AuthModule,
|
AuthModule,
|
||||||
|
UserModule,
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService, { provide: 'APP_GUARD', useClass: AccessTokenGuard }],
|
providers: [AppService, { provide: 'APP_GUARD', useClass: AccessTokenGuard }],
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
export * from './user-credentials.entity';
|
export * from './user-credentials.entity';
|
||||||
|
export * from './user-data.entity';
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
import {
|
||||||
|
Column,
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
OneToOne,
|
||||||
|
JoinColumn,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
import { UserCredentials } from './user-credentials.entity';
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class UserData {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
public id: string;
|
||||||
|
|
||||||
|
@Column({ default: false })
|
||||||
|
public isEmailConfirmed: boolean;
|
||||||
|
|
||||||
|
@OneToOne(() => UserCredentials)
|
||||||
|
@JoinColumn({ name: 'userCredentialsId' })
|
||||||
|
public user: UserCredentials;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
public updatedAt: Date;
|
||||||
|
}
|
|
@ -1,10 +1,12 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { JwtModule } from '@nestjs/jwt';
|
import { JwtModule } from '@nestjs/jwt';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { UserCredentials } from 'src/entities/user-credentials.entity';
|
import { UserCredentials } from 'src/entities';
|
||||||
|
|
||||||
|
import { UserModule } from '../user-module/user.module';
|
||||||
|
|
||||||
import { AuthController } from './controller/auth.controller';
|
import { AuthController } from './controller/auth.controller';
|
||||||
import { UserRepository } from './repositories/user.repository';
|
import { UserCredentialsRepository } from './repositories/user-credentials.repository';
|
||||||
import { AuthService } from './services/auth.service';
|
import { AuthService } from './services/auth.service';
|
||||||
import { EncryptionService } from './services/encryption.service';
|
import { EncryptionService } from './services/encryption.service';
|
||||||
import { TokenManagementService } from './services/token-management.service';
|
import { TokenManagementService } from './services/token-management.service';
|
||||||
|
@ -12,6 +14,7 @@ import { AccessTokenStrategy, RefreshTokenStrategy } from './strategies';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
UserModule,
|
||||||
JwtModule.register({}),
|
JwtModule.register({}),
|
||||||
TypeOrmModule.forFeature([UserCredentials]),
|
TypeOrmModule.forFeature([UserCredentials]),
|
||||||
],
|
],
|
||||||
|
@ -19,7 +22,7 @@ import { AccessTokenStrategy, RefreshTokenStrategy } from './strategies';
|
||||||
AuthService,
|
AuthService,
|
||||||
TokenManagementService,
|
TokenManagementService,
|
||||||
EncryptionService,
|
EncryptionService,
|
||||||
UserRepository,
|
UserCredentialsRepository,
|
||||||
AccessTokenStrategy,
|
AccessTokenStrategy,
|
||||||
RefreshTokenStrategy,
|
RefreshTokenStrategy,
|
||||||
],
|
],
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { UserCredentials } from 'src/entities/user-credentials.entity';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UserRepository {
|
export class UserCredentialsRepository {
|
||||||
public constructor(
|
public constructor(
|
||||||
@InjectRepository(UserCredentials)
|
@InjectRepository(UserCredentials)
|
||||||
private readonly repository: Repository<UserCredentials>
|
private readonly repository: Repository<UserCredentials>
|
|
@ -1,7 +1,8 @@
|
||||||
import { ForbiddenException, Injectable } from '@nestjs/common';
|
import { ForbiddenException, Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { UserDataRepository } from '../../user-module/repositories/user-data.repository';
|
||||||
import { TokensDto, UserCredentialsDto } from '../models/dto';
|
import { TokensDto, UserCredentialsDto } from '../models/dto';
|
||||||
import { UserRepository } from '../repositories/user.repository';
|
import { UserCredentialsRepository } from '../repositories/user-credentials.repository';
|
||||||
|
|
||||||
import { EncryptionService } from './encryption.service';
|
import { EncryptionService } from './encryption.service';
|
||||||
import { TokenManagementService } from './token-management.service';
|
import { TokenManagementService } from './token-management.service';
|
||||||
|
@ -9,7 +10,8 @@ import { TokenManagementService } from './token-management.service';
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
public constructor(
|
public constructor(
|
||||||
private readonly userRepository: UserRepository,
|
private readonly userCredentialsRepository: UserCredentialsRepository,
|
||||||
|
private readonly userDataRepository: UserDataRepository,
|
||||||
private readonly tokenManagementService: TokenManagementService,
|
private readonly tokenManagementService: TokenManagementService,
|
||||||
private readonly encryptionService: EncryptionService
|
private readonly encryptionService: EncryptionService
|
||||||
) {}
|
) {}
|
||||||
|
@ -18,16 +20,18 @@ export class AuthService {
|
||||||
const passwordHashed = await this.encryptionService.hashData(
|
const passwordHashed = await this.encryptionService.hashData(
|
||||||
userCredentials.password
|
userCredentials.password
|
||||||
);
|
);
|
||||||
const user = await this.userRepository.createUser(
|
const user = await this.userCredentialsRepository.createUser(
|
||||||
userCredentials.email,
|
userCredentials.email,
|
||||||
passwordHashed
|
passwordHashed
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await this.userDataRepository.createInitialUserData(user);
|
||||||
|
|
||||||
return this.generateAndPersistTokens(user.id, user.email);
|
return this.generateAndPersistTokens(user.id, user.email);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async signin(userCredentials: UserCredentialsDto): Promise<TokensDto> {
|
public async signin(userCredentials: UserCredentialsDto): Promise<TokensDto> {
|
||||||
const user = await this.userRepository.findUserByEmail(
|
const user = await this.userCredentialsRepository.findUserByEmail(
|
||||||
userCredentials.email
|
userCredentials.email
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -51,7 +55,7 @@ export class AuthService {
|
||||||
userId: number,
|
userId: number,
|
||||||
refreshToken: string
|
refreshToken: string
|
||||||
): Promise<TokensDto> {
|
): Promise<TokensDto> {
|
||||||
const user = await this.userRepository.findUserById(userId);
|
const user = await this.userCredentialsRepository.findUserById(userId);
|
||||||
|
|
||||||
if (!user || !user.hashedRt) {
|
if (!user || !user.hashedRt) {
|
||||||
throw new ForbiddenException('Access Denied');
|
throw new ForbiddenException('Access Denied');
|
||||||
|
@ -70,7 +74,7 @@ export class AuthService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async logout(userId: number): Promise<boolean> {
|
public async logout(userId: number): Promise<boolean> {
|
||||||
const affected = await this.userRepository.updateUserTokenHash(
|
const affected = await this.userCredentialsRepository.updateUserTokenHash(
|
||||||
userId,
|
userId,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
@ -90,7 +94,10 @@ export class AuthService {
|
||||||
tokens.refresh_token
|
tokens.refresh_token
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.userRepository.updateUserTokenHash(userId, hashedRefreshToken);
|
await this.userCredentialsRepository.updateUserTokenHash(
|
||||||
|
userId,
|
||||||
|
hashedRefreshToken
|
||||||
|
);
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
|
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
|
||||||
import { UserCredentials } from 'src/entities';
|
import { UserCredentials, UserData } from 'src/entities';
|
||||||
|
|
||||||
export const databaseConfigFactory = (
|
export const databaseConfigFactory = (
|
||||||
configService: ConfigService
|
configService: ConfigService
|
||||||
|
@ -13,5 +13,5 @@ export const databaseConfigFactory = (
|
||||||
database: configService.get('DB_NAME'),
|
database: configService.get('DB_NAME'),
|
||||||
synchronize: true,
|
synchronize: true,
|
||||||
logging: true,
|
logging: true,
|
||||||
entities: [UserCredentials],
|
entities: [UserCredentials, UserData],
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './user-data.repository';
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { UserCredentials, UserData } from 'src/entities';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UserDataRepository {
|
||||||
|
public constructor(
|
||||||
|
@InjectRepository(UserData)
|
||||||
|
private readonly repository: Repository<UserData>
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public async createInitialUserData(
|
||||||
|
userCredentials: UserCredentials
|
||||||
|
): Promise<UserData> {
|
||||||
|
const userData = new UserData();
|
||||||
|
|
||||||
|
userData.user = userCredentials;
|
||||||
|
userData.isEmailConfirmed = false;
|
||||||
|
|
||||||
|
return this.repository.save(userData);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { UserData } from 'src/entities';
|
||||||
|
|
||||||
|
import { UserDataRepository } from './repositories';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [TypeOrmModule.forFeature([UserData])],
|
||||||
|
providers: [UserDataRepository],
|
||||||
|
controllers: [],
|
||||||
|
exports: [UserDataRepository],
|
||||||
|
})
|
||||||
|
export class UserModule {}
|
Loading…
Reference in New Issue