extend logging

This commit is contained in:
Bastian Wagner
2024-09-11 10:32:46 +02:00
parent 00c26e1fa1
commit 110a4b89c6
5 changed files with 92 additions and 4 deletions

View File

@@ -1,6 +1,5 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { AuthController } from './auth.controller'; import { AuthController } from './auth.controller';
import { UsersService } from 'src/users/users.service';
import { ClientService } from 'src/client/client.service'; import { ClientService } from 'src/client/client.service';
import { JwtModule } from '@nestjs/jwt'; import { JwtModule } from '@nestjs/jwt';
import { NestjsFormDataModule } from 'nestjs-form-data'; import { NestjsFormDataModule } from 'nestjs-form-data';
@@ -8,9 +7,10 @@ import { LoggerModule } from 'src/core/logger.module';
import { ConfigModule, ConfigService } from '@nestjs/config'; import { ConfigModule, ConfigService } from '@nestjs/config';
import { DatabaseModule } from 'src/core/database/database.module'; import { DatabaseModule } from 'src/core/database/database.module';
import { MailModule } from 'src/application/mail/mail.module'; import { MailModule } from 'src/application/mail/mail.module';
import { SecureModule } from 'src/core/secure/secure.module';
@Module({ @Module({
providers: [UsersService, ClientService], providers: [ClientService],
controllers: [AuthController], controllers: [AuthController],
imports: [ imports: [
JwtModule.registerAsync({ JwtModule.registerAsync({
@@ -25,6 +25,7 @@ import { MailModule } from 'src/application/mail/mail.module';
LoggerModule, LoggerModule,
DatabaseModule, DatabaseModule,
MailModule, MailModule,
SecureModule,
], ],
}) })
export class AuthModule {} export class AuthModule {}

View File

@@ -17,6 +17,8 @@ import {
AuthorizationCodeRepository, AuthorizationCodeRepository,
Role, Role,
RoleRepository, RoleRepository,
ActivityLog,
ActivityLogRepository,
} from 'src/model'; } from 'src/model';
const ENTITIES = [ const ENTITIES = [
@@ -28,6 +30,7 @@ const ENTITIES = [
SessionKey, SessionKey,
Log, Log,
ResetPwCode, ResetPwCode,
ActivityLog,
]; ];
const REPOSITORIES = [ const REPOSITORIES = [
UserRepository, UserRepository,
@@ -38,6 +41,7 @@ const REPOSITORIES = [
LogRepository, LogRepository,
ResetPwCodeRepository, ResetPwCodeRepository,
RoleRepository, RoleRepository,
ActivityLogRepository,
]; ];
@Module({ @Module({

View File

@@ -0,0 +1,77 @@
import { Injectable } from '@nestjs/common';
import {
Entity,
Column,
PrimaryGeneratedColumn,
Repository,
DataSource,
Between,
} from 'typeorm';
@Entity()
export class ActivityLog {
@PrimaryGeneratedColumn()
id: number;
@Column({ type: 'date', default: null })
date: Date;
@Column({ default: 0, type: 'int' })
loginCounter: number;
@Column({ default: 0, type: 'int' })
accessTokensVerifies: number;
@Column({ default: 0, type: 'int' })
accessTokenRefresh: number;
}
@Injectable()
export class ActivityLogRepository extends Repository<ActivityLog> {
constructor(dataSource: DataSource) {
super(ActivityLog, dataSource.createEntityManager());
}
async logAccessTokenVerification(): Promise<ActivityLog> {
const entity = await this.getTodaysActivityLog();
entity.accessTokensVerifies += 1;
return this.save(entity);
}
async logLogin(): Promise<ActivityLog> {
const entity = await this.getTodaysActivityLog();
entity.loginCounter += 1;
return this.save(entity);
}
async logGetNewAccessTokenWithRefresh(): Promise<ActivityLog> {
const entity = await this.getTodaysActivityLog();
entity.accessTokenRefresh += 1;
return this.save(entity);
}
async getTodaysActivityLog(): Promise<ActivityLog> {
const start = new Date();
start.setHours(0);
start.setMinutes(0);
start.setSeconds(0);
start.setMilliseconds(0);
const end = new Date();
end.setHours(23);
end.setMinutes(59);
end.setSeconds(59);
end.setMilliseconds(999);
let x: ActivityLog = await this.findOne({
where: {
date: Between(start, end),
},
});
if (!x) {
x = this.create({ date: new Date() });
}
return x;
}
}

View File

@@ -6,3 +6,4 @@ export * from './role.entity';
export * from './session-key.entity'; export * from './session-key.entity';
export * from './user.entity'; export * from './user.entity';
export * from './auth-code.entity'; export * from './auth-code.entity';
export * from './activity-log.entity';

View File

@@ -15,6 +15,7 @@ import {
Client, Client,
AuthorizationCodeRepository, AuthorizationCodeRepository,
AuthorizationCode, AuthorizationCode,
ActivityLogRepository,
} from 'src/model'; } from 'src/model';
@Injectable() @Injectable()
@@ -28,6 +29,7 @@ export class UsersService {
private logger: CustomLogger, private logger: CustomLogger,
private resetPwRepo: ResetPwCodeRepository, private resetPwRepo: ResetPwCodeRepository,
private mailService: MailService, private mailService: MailService,
private activityRepo: ActivityLogRepository,
) {} ) {}
async createUser(userDto: CreateUserDto): Promise<User> { async createUser(userDto: CreateUserDto): Promise<User> {
const hashedPassword = await bcrypt.hash(userDto.password, 10); const hashedPassword = await bcrypt.hash(userDto.password, 10);
@@ -79,7 +81,7 @@ export class UsersService {
user, user,
}); });
const session = await this.sessionRepo.save(s); const session = await this.sessionRepo.save(s);
this.activityRepo.logLogin();
return { code: token.code, session_key: session.id }; return { code: token.code, session_key: session.id };
} }
@@ -229,12 +231,15 @@ export class UsersService {
access_token: token, access_token: token,
expires_in: pay.exp - pay.iat, expires_in: pay.exp - pay.iat,
}; };
this.activityRepo.logGetNewAccessTokenWithRefresh();
return result; return result;
} }
verifyAccessToken(token: string) { async verifyAccessToken(token: string) {
try { try {
const decoded = this.jwtService.verify(token); const decoded = this.jwtService.verify(token);
this.activityRepo.logAccessTokenVerification();
return decoded; return decoded;
} catch (e) { } catch (e) {
this.logger.error(`Token ${token} is invalid. Error: ${e.message}`); this.logger.error(`Token ${token} is invalid. Error: ${e.message}`);