Compare commits
No commits in common. "2f418ab14e90f4787d2752ac5ec516f21be9b53f" and "74e77e7404fdef1d8483e470cab813b744e66a2f" have entirely different histories.
2f418ab14e
...
74e77e7404
|
@ -12,7 +12,6 @@ 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 { SendgridModule } from './modules/sendgrid-module/sendgrid.module';
|
import { SendgridModule } from './modules/sendgrid-module/sendgrid.module';
|
||||||
import { UserModule } from './modules/user-module/user.module';
|
import { UserModule } from './modules/user-module/user.module';
|
||||||
import { VerifyModule } from './modules/verify-module/verify.module';
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -23,7 +22,6 @@ import { VerifyModule } from './modules/verify-module/verify.module';
|
||||||
AuthModule,
|
AuthModule,
|
||||||
UserModule,
|
UserModule,
|
||||||
SendgridModule,
|
SendgridModule,
|
||||||
VerifyModule,
|
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService, { provide: 'APP_GUARD', useClass: AccessTokenGuard }],
|
providers: [AppService, { provide: 'APP_GUARD', useClass: AccessTokenGuard }],
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
import {
|
|
||||||
Column,
|
|
||||||
CreateDateColumn,
|
|
||||||
Entity,
|
|
||||||
JoinColumn,
|
|
||||||
OneToOne,
|
|
||||||
PrimaryGeneratedColumn,
|
|
||||||
UpdateDateColumn,
|
|
||||||
} from 'typeorm';
|
|
||||||
|
|
||||||
import { UserCredentials } from './user-credentials.entity';
|
|
||||||
|
|
||||||
@Entity()
|
|
||||||
export class EmailVerification {
|
|
||||||
@PrimaryGeneratedColumn('uuid')
|
|
||||||
public id: string;
|
|
||||||
|
|
||||||
@Column()
|
|
||||||
public token: string;
|
|
||||||
|
|
||||||
@Column()
|
|
||||||
public expiresAt: Date;
|
|
||||||
|
|
||||||
@OneToOne(() => UserCredentials)
|
|
||||||
@JoinColumn({ name: 'userCredentialsId' })
|
|
||||||
public user: UserCredentials;
|
|
||||||
|
|
||||||
@CreateDateColumn()
|
|
||||||
public createdAt: Date;
|
|
||||||
|
|
||||||
@UpdateDateColumn()
|
|
||||||
public updatedAt: Date;
|
|
||||||
}
|
|
|
@ -1,3 +1,2 @@
|
||||||
export * from './user-credentials.entity';
|
export * from './user-credentials.entity';
|
||||||
export * from './user-data.entity';
|
export * from './user-data.entity';
|
||||||
export * from './email-verification.entity';
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
@Entity()
|
@Entity()
|
||||||
export class UserCredentials {
|
export class UserCredentials {
|
||||||
@PrimaryGeneratedColumn('uuid')
|
@PrimaryGeneratedColumn('uuid')
|
||||||
public id: string;
|
public id: number;
|
||||||
|
|
||||||
@Column({ unique: true })
|
@Column({ unique: true })
|
||||||
public email: string;
|
public email: string;
|
||||||
|
|
|
@ -5,7 +5,6 @@ import { UserCredentials } from 'src/entities';
|
||||||
|
|
||||||
import { SendgridModule } from '../sendgrid-module/sendgrid.module';
|
import { SendgridModule } from '../sendgrid-module/sendgrid.module';
|
||||||
import { UserModule } from '../user-module/user.module';
|
import { UserModule } from '../user-module/user.module';
|
||||||
import { VerifyModule } from '../verify-module/verify.module';
|
|
||||||
|
|
||||||
import { AuthController } from './controller/auth.controller';
|
import { AuthController } from './controller/auth.controller';
|
||||||
import { UserCredentialsRepository } from './repositories/user-credentials.repository';
|
import { UserCredentialsRepository } from './repositories/user-credentials.repository';
|
||||||
|
@ -18,7 +17,6 @@ import { AccessTokenStrategy, RefreshTokenStrategy } from './strategies';
|
||||||
imports: [
|
imports: [
|
||||||
UserModule,
|
UserModule,
|
||||||
SendgridModule,
|
SendgridModule,
|
||||||
VerifyModule,
|
|
||||||
JwtModule.register({}),
|
JwtModule.register({}),
|
||||||
TypeOrmModule.forFeature([UserCredentials]),
|
TypeOrmModule.forFeature([UserCredentials]),
|
||||||
],
|
],
|
||||||
|
|
|
@ -50,7 +50,7 @@ export class AuthController {
|
||||||
})
|
})
|
||||||
@Post('logout')
|
@Post('logout')
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
public async logout(@GetCurrentUserId() userId: string): Promise<boolean> {
|
public async logout(@GetCurrentUserId() userId: number): Promise<boolean> {
|
||||||
return this.authService.logout(userId);
|
return this.authService.logout(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ export class AuthController {
|
||||||
@Post('refresh')
|
@Post('refresh')
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
public async refresh(
|
public async refresh(
|
||||||
@GetCurrentUserId() userId: string,
|
@GetCurrentUserId() userId: number,
|
||||||
@GetCurrentUser('refresh_token') refresh_token: string
|
@GetCurrentUser('refresh_token') refresh_token: string
|
||||||
): Promise<TokensDto> {
|
): Promise<TokensDto> {
|
||||||
return this.authService.refresh(userId, refresh_token);
|
return this.authService.refresh(userId, refresh_token);
|
||||||
|
|
|
@ -26,13 +26,13 @@ export class UserCredentialsRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async findUserById(
|
public async findUserById(
|
||||||
userId: string
|
userId: number
|
||||||
): Promise<UserCredentials | undefined> {
|
): Promise<UserCredentials | undefined> {
|
||||||
return this.repository.findOne({ where: { id: userId } });
|
return this.repository.findOne({ where: { id: userId } });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateUserTokenHash(
|
public async updateUserTokenHash(
|
||||||
userId: string,
|
userId: number,
|
||||||
hashedRt: string | null
|
hashedRt: string | null
|
||||||
): Promise<number> {
|
): Promise<number> {
|
||||||
const result = await this.repository.update(userId, { hashedRt });
|
const result = await this.repository.update(userId, { hashedRt });
|
||||||
|
|
|
@ -2,7 +2,6 @@ import { ForbiddenException, Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
import { PasswordConfirmationMailService } from '../../sendgrid-module/services/password-confirmation.mail.service';
|
import { PasswordConfirmationMailService } from '../../sendgrid-module/services/password-confirmation.mail.service';
|
||||||
import { UserDataRepository } from '../../user-module/repositories/user-data.repository';
|
import { UserDataRepository } from '../../user-module/repositories/user-data.repository';
|
||||||
import { EmailVerificationService } from '../../verify-module/services/email-verification.service';
|
|
||||||
import { TokensDto, UserCredentialsDto } from '../models/dto';
|
import { TokensDto, UserCredentialsDto } from '../models/dto';
|
||||||
import { UserCredentialsRepository } from '../repositories/user-credentials.repository';
|
import { UserCredentialsRepository } from '../repositories/user-credentials.repository';
|
||||||
|
|
||||||
|
@ -16,8 +15,7 @@ export class AuthService {
|
||||||
private readonly userDataRepository: UserDataRepository,
|
private readonly userDataRepository: UserDataRepository,
|
||||||
private readonly tokenManagementService: TokenManagementService,
|
private readonly tokenManagementService: TokenManagementService,
|
||||||
private readonly encryptionService: EncryptionService,
|
private readonly encryptionService: EncryptionService,
|
||||||
private readonly passwordConfirmationMailService: PasswordConfirmationMailService,
|
private readonly passwordConfirmationMailService: PasswordConfirmationMailService
|
||||||
private readonly emailVerificationService: EmailVerificationService
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async signup(userCredentials: UserCredentialsDto): Promise<TokensDto> {
|
public async signup(userCredentials: UserCredentialsDto): Promise<TokensDto> {
|
||||||
|
@ -31,15 +29,10 @@ export class AuthService {
|
||||||
|
|
||||||
await this.userDataRepository.createInitialUserData(user);
|
await this.userDataRepository.createInitialUserData(user);
|
||||||
|
|
||||||
const token =
|
// TODO Send email confirmation
|
||||||
await this.emailVerificationService.generateEmailVerificationToken(
|
// await this.passwordConfirmationMailService.sendPasswordConfirmationMail(
|
||||||
user.id
|
// user.email
|
||||||
);
|
// );
|
||||||
|
|
||||||
await this.passwordConfirmationMailService.sendPasswordConfirmationMail(
|
|
||||||
user.email,
|
|
||||||
token
|
|
||||||
);
|
|
||||||
|
|
||||||
return this.generateAndPersistTokens(user.id, user.email);
|
return this.generateAndPersistTokens(user.id, user.email);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +59,7 @@ export class AuthService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async refresh(
|
public async refresh(
|
||||||
userId: string,
|
userId: number,
|
||||||
refreshToken: string
|
refreshToken: string
|
||||||
): Promise<TokensDto> {
|
): Promise<TokensDto> {
|
||||||
const user = await this.userCredentialsRepository.findUserById(userId);
|
const user = await this.userCredentialsRepository.findUserById(userId);
|
||||||
|
@ -87,7 +80,7 @@ export class AuthService {
|
||||||
return this.generateAndPersistTokens(user.id, user.email);
|
return this.generateAndPersistTokens(user.id, user.email);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async logout(userId: string): Promise<boolean> {
|
public async logout(userId: number): Promise<boolean> {
|
||||||
const affected = await this.userCredentialsRepository.updateUserTokenHash(
|
const affected = await this.userCredentialsRepository.updateUserTokenHash(
|
||||||
userId,
|
userId,
|
||||||
null
|
null
|
||||||
|
@ -97,7 +90,7 @@ export class AuthService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async generateAndPersistTokens(
|
private async generateAndPersistTokens(
|
||||||
userId: string,
|
userId: number,
|
||||||
email: string
|
email: string
|
||||||
): Promise<TokensDto> {
|
): Promise<TokensDto> {
|
||||||
const tokens = await this.tokenManagementService.generateTokens(
|
const tokens = await this.tokenManagementService.generateTokens(
|
||||||
|
|
|
@ -26,7 +26,7 @@ export class TokenManagementService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async generateTokens(
|
public async generateTokens(
|
||||||
userId: string,
|
userId: number,
|
||||||
email: string
|
email: string
|
||||||
): Promise<TokensDto> {
|
): Promise<TokensDto> {
|
||||||
const access_token: string = await this.createAccessToken(userId, email);
|
const access_token: string = await this.createAccessToken(userId, email);
|
||||||
|
@ -36,7 +36,7 @@ export class TokenManagementService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createAccessToken(
|
private async createAccessToken(
|
||||||
userId: string,
|
userId: number,
|
||||||
email: string
|
email: string
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
return this.jwt.signAsync(
|
return this.jwt.signAsync(
|
||||||
|
@ -49,7 +49,7 @@ export class TokenManagementService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createRefreshToken(
|
private async createRefreshToken(
|
||||||
userId: string,
|
userId: number,
|
||||||
email: string
|
email: string
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
return this.jwt.signAsync(
|
return this.jwt.signAsync(
|
||||||
|
|
|
@ -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 { EmailVerification, UserCredentials, UserData } 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, UserData, EmailVerification],
|
entities: [UserCredentials, UserData],
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,23 +16,18 @@ export class PasswordConfirmationMailService extends BaseMailService {
|
||||||
super(sendGridApiKey);
|
super(sendGridApiKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendPasswordConfirmationMail(
|
public async sendPasswordConfirmationMail(to: string): Promise<void> {
|
||||||
to: string,
|
|
||||||
token: string
|
|
||||||
): Promise<void> {
|
|
||||||
const templateId: string = this.templateConfigService.getTemplateId(
|
const templateId: string = this.templateConfigService.getTemplateId(
|
||||||
this.PASSWORD_CONFIRMATION_EMAIL
|
this.PASSWORD_CONFIRMATION_EMAIL
|
||||||
);
|
);
|
||||||
|
|
||||||
const encodedToken = encodeURIComponent(token);
|
|
||||||
|
|
||||||
const mailoptions: SendGridMailApi.MailDataRequired = {
|
const mailoptions: SendGridMailApi.MailDataRequired = {
|
||||||
to,
|
to,
|
||||||
from: { email: 'info@igor-propisnov.com', name: 'Ticket App' },
|
from: { email: 'info@igor-propisnov.com', name: 'Ticket App' },
|
||||||
templateId: templateId,
|
templateId: templateId,
|
||||||
dynamicTemplateData: {
|
dynamicTemplateData: {
|
||||||
name: 'Mara',
|
name: 'Mara',
|
||||||
buttonUrl: `http://localhost:4200/?token=${encodedToken}`,
|
buttonUrl: 'https://igor-propisnov.com',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
|
||||||
import { EmailVerification } from 'src/entities';
|
|
||||||
import { Repository } from 'typeorm';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class EmailVerifyRepository {
|
|
||||||
public constructor(
|
|
||||||
@InjectRepository(EmailVerification)
|
|
||||||
private readonly repository: Repository<EmailVerification>
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public async createEmailVerification(
|
|
||||||
token: string,
|
|
||||||
expiresAt: Date,
|
|
||||||
userId: string
|
|
||||||
): Promise<void> {
|
|
||||||
await this.repository.save({
|
|
||||||
token,
|
|
||||||
expiresAt,
|
|
||||||
user: { id: userId },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export * from './email-verify.repository';
|
|
|
@ -1,27 +0,0 @@
|
||||||
import { randomBytes } from 'crypto';
|
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { EmailVerifyRepository } from '../repositories';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class EmailVerificationService {
|
|
||||||
public constructor(
|
|
||||||
private readonly emailVerifyRepository: EmailVerifyRepository
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public async generateEmailVerificationToken(userId: string): Promise<string> {
|
|
||||||
const token = randomBytes(32).toString('hex');
|
|
||||||
|
|
||||||
// TODO Check users local time zone and set expiration time accordingly
|
|
||||||
const expiration = new Date(Date.now() + 24 * 60 * 60 * 1000);
|
|
||||||
|
|
||||||
this.emailVerifyRepository.createEmailVerification(
|
|
||||||
token,
|
|
||||||
expiration,
|
|
||||||
userId
|
|
||||||
);
|
|
||||||
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { Module } from '@nestjs/common';
|
|
||||||
import { ConfigModule } from '@nestjs/config';
|
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
||||||
import { EmailVerification } from 'src/entities';
|
|
||||||
|
|
||||||
import { EmailVerifyRepository } from './repositories';
|
|
||||||
import { EmailVerificationService } from './services/email-verification.service';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [ConfigModule, TypeOrmModule.forFeature([EmailVerification])],
|
|
||||||
providers: [EmailVerifyRepository, EmailVerificationService],
|
|
||||||
controllers: [],
|
|
||||||
exports: [EmailVerificationService],
|
|
||||||
})
|
|
||||||
export class VerifyModule {}
|
|
Loading…
Reference in New Issue