extend logging
This commit is contained in:
@@ -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 {}
|
||||||
|
|||||||
@@ -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({
|
||||||
|
|||||||
77
idp/src/model/entity/activity-log.entity.ts
Normal file
77
idp/src/model/entity/activity-log.entity.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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';
|
||||||
|
|||||||
@@ -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}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user