Skip to content

Commit

Permalink
Merge pull request #45 from gsainfoteam/siwonpada/issue37
Browse files Browse the repository at this point in the history
[FEATURE] Logger
  • Loading branch information
chungjung-d authored Nov 22, 2024
2 parents da07801 + 7175bd9 commit 4de34de
Show file tree
Hide file tree
Showing 18 changed files with 132 additions and 45 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"gitops",
"gsainfoteam",
"infoteam",
"loggable",
"mjml",
"nestjs",
"noreply",
Expand Down
4 changes: 4 additions & 0 deletions libs/logger/src/decorator/loggable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { SetMetadata } from '@nestjs/common';

export const LOGGABLE = Symbol('LOGGABLE');
export const Loggable = () => SetMetadata(LOGGABLE, true);
1 change: 1 addition & 0 deletions libs/logger/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './logger.module';
48 changes: 48 additions & 0 deletions libs/logger/src/logger.decorator.register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { DiscoveryService, MetadataScanner } from '@nestjs/core';
import { LOGGABLE } from './decorator/loggable';

@Injectable()
export class LoggerDecoratorRegister implements OnModuleInit {
constructor(
private readonly discoveryService: DiscoveryService,
private readonly metadataScanner: MetadataScanner,
) {}

onModuleInit() {
return this.discoveryService
.getProviders()
.filter((wrapper) => wrapper.isDependencyTreeStatic())
.filter(({ metatype, instance }) => {
if (!instance || !metatype) {
return false;
}
return Reflect.getMetadata(LOGGABLE, metatype);
})
.forEach(({ instance }) => {
this.metadataScanner
.getAllMethodNames(instance)
.forEach((methodName) => {
const originalMethod = instance[methodName];
if (typeof originalMethod !== 'function') {
return;
}
const logger = new Logger(instance.constructor.name);
instance[methodName] = function (...args: any[]) {
logger.log(`Before ${methodName}`);
const now = Date.now();
const result = originalMethod.apply(this, args);
if (result instanceof Promise) {
return result.then((resolvedResult) => {
logger.log(`After ${methodName} +${Date.now() - now}ms`);
return resolvedResult;
});
} else {
logger.log(`After ${methodName} +${Date.now() - now}ms`);
return result;
}
};
});
});
}
}
9 changes: 9 additions & 0 deletions libs/logger/src/logger.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { DiscoveryModule } from '@nestjs/core';
import { LoggerDecoratorRegister } from './logger.decorator.register';

@Module({
imports: [DiscoveryModule],
providers: [LoggerDecoratorRegister],
})
export class LoggerModule {}
9 changes: 9 additions & 0 deletions libs/logger/tsconfig.lib.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"declaration": true,
"outDir": "../../dist/libs/logger"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "test", "**/*spec.ts"]
}
16 changes: 14 additions & 2 deletions nest-cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true
"deleteOutDir": true,
"webpack": true
},
"projects": {
"logger": {
"type": "library",
"root": "libs/logger",
"entryFile": "index",
"sourceRoot": "libs/logger/src",
"compilerOptions": {
"tsConfigPath": "libs/logger/tsconfig.lib.json"
}
}
}
}
}
14 changes: 10 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"license": "UNLICENSED",
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"libs/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
Expand Down Expand Up @@ -101,9 +101,15 @@
],
"moduleNameMapper": {
"^src/(.*)$": "<rootDir>/src/$1",
"^test/(.*)$": "<rootDir>/test/$1"
"^test/(.*)$": "<rootDir>/test/$1",
"^@lib/logger(|/.*)$": "<rootDir>/libs/logger/src/$1"
},
"coverageDirectory": "../coverage",
"testEnvironment": "node"
"testEnvironment": "node",
"roots": [
"<rootDir>/src/",
"<rootDir>/libs/",
"<rootDir>/test/"
]
}
}
}
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { EmailModule } from './email/email.module';
import { OauthModule } from './oauth/oauth.module';
import { CacheModule } from './cache/cache.module';
import { HealthModule } from './health/health.module';
import { LoggerModule } from '@lib/logger';

@Module({
imports: [
Expand All @@ -24,6 +25,7 @@ import { HealthModule } from './health/health.module';
OauthModule,
CacheModule,
HealthModule,
LoggerModule,
],
controllers: [AppController],
})
Expand Down
9 changes: 2 additions & 7 deletions src/client/client.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@ import { Client } from '@prisma/client';
import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library';
import { PrismaService } from 'src/prisma/prisma.service';
import { ConsentClient } from './types/consentClient.type';
import { Loggable } from '@lib/logger/decorator/loggable';

@Injectable()
@Loggable()
export class ClientRepository {
private readonly logger = new Logger(ClientRepository.name);
constructor(private readonly prismaService: PrismaService) {}

async findClientsByUserUuid(
userUuid: string,
): Promise<Omit<Client, 'password'>[]> {
this.logger.log(`findClientsByUserUuid: userUuid=${userUuid}`);
return this.prismaService.client.findMany({
where: {
member: {
Expand All @@ -40,7 +41,6 @@ export class ClientRepository {
}

async findById(id: string): Promise<Client> {
this.logger.log(`findById: id=${id}`);
return this.prismaService.client
.findUniqueOrThrow({
where: {
Expand All @@ -64,7 +64,6 @@ export class ClientRepository {
id: string,
userUuid: string,
): Promise<ConsentClient | null> {
this.logger.log(`findClientWithConsentByIdAndUserUuid: id=${id}`);
return this.prismaService.client
.findUnique({
where: { id },
Expand All @@ -87,7 +86,6 @@ export class ClientRepository {
uuid: string,
userUuid: string,
): Promise<Omit<Client, 'password'>> {
this.logger.log(`findClientByUuidAndUserUuid: uuid=${uuid}`);
return this.prismaService.client
.findUniqueOrThrow({
where: {
Expand Down Expand Up @@ -130,7 +128,6 @@ export class ClientRepository {
}: Pick<Client, 'id' | 'name' | 'password'> & Partial<Pick<Client, 'urls'>>,
userUuid: string,
): Promise<Client> {
this.logger.log(`createClient: id=${id}, name=${name}`);
return this.prismaService.client
.create({
data: {
Expand Down Expand Up @@ -162,7 +159,6 @@ export class ClientRepository {
{ uuid, password }: Pick<Client, 'uuid' | 'password'>,
userUuid: string,
): Promise<Client> {
this.logger.log(`updateClientSecret: uuid=${uuid}`);
return this.prismaService.client
.update({
where: {
Expand Down Expand Up @@ -198,7 +194,6 @@ export class ClientRepository {
}: Pick<Client, 'uuid'> & Partial<Pick<Client, 'name' | 'urls'>>,
userUuid: string,
): Promise<Omit<Client, 'password'>> {
this.logger.log(`updateClient: uuid=${uuid}`);
return this.prismaService.client
.update({
where: {
Expand Down
9 changes: 2 additions & 7 deletions src/client/client.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import { firstValueFrom } from 'rxjs';
import { UpdateClientDto } from './dto/req/updateClient.dto';
import { UserInfo } from 'src/idp/types/userInfo.type';
import { ClientPublicResDto } from './dto/res/clientPublicRes.dto';
import { Loggable } from '@lib/logger/decorator/loggable';

@Injectable()
@Loggable()
export class ClientService {
private readonly logger = new Logger(ClientService.name);
constructor(
Expand All @@ -28,7 +30,6 @@ export class ClientService {
* @returns client list
*/
async getClientList(user: UserInfo): Promise<ClientResDto[]> {
this.logger.log(`getClientList: user=${JSON.stringify(user)}`);
return (await this.clientRepository.findClientsByUserUuid(user.uuid)).map(
this.convertToClientResDto,
);
Expand All @@ -41,7 +42,6 @@ export class ClientService {
* @returns client information
*/
async getClient(uuid: string, user: UserInfo): Promise<ClientResDto> {
this.logger.log(`getClient: uuid=${uuid}`);
return this.convertToClientResDto(
await this.clientRepository.findClientByUuidAndUserUuid(uuid, user.uuid),
);
Expand All @@ -57,7 +57,6 @@ export class ClientService {
id: string,
user: UserInfo,
): Promise<ClientPublicResDto> {
this.logger.log(`getClientPublicInformation: id=${id}`);
const client = await this.clientRepository.findById(id);
const clientWithConsent =
await this.clientRepository.findClientWithConsentByIdAndUserUuid(
Expand All @@ -83,7 +82,6 @@ export class ClientService {
{ id, name, urls }: CreateClientDto,
user: UserInfo,
): Promise<ClientCredentialResDto> {
this.logger.log(`registerClient: id=${id}, name=${name}`);
const { secretKey, hashed } = this.generateClientSecret();
const client = await this.clientRepository.createClient(
{
Expand Down Expand Up @@ -111,7 +109,6 @@ export class ClientService {
uuid: string,
user: UserInfo,
): Promise<ClientCredentialResDto> {
this.logger.log(`resetClientSecret: uuid=${uuid}`);
const { secretKey, hashed } = this.generateClientSecret();
const client = await this.clientRepository.updateClientSecret(
{
Expand Down Expand Up @@ -139,7 +136,6 @@ export class ClientService {
{ name, urls }: UpdateClientDto,
user: UserInfo,
): Promise<ClientResDto> {
this.logger.log(`updateClient: uuid=${uuid}`);
return this.convertToClientResDto(
await this.clientRepository.updateClient({ uuid, name, urls }, user.uuid),
);
Expand All @@ -163,7 +159,6 @@ export class ClientService {
* @param user user who sends the permission request
*/
async adminRequest(uuid: string, user: UserInfo): Promise<void> {
this.logger.log(`adminRequest: uuid=${uuid}`);
const { name } = await this.clientRepository.findClientByUuidAndUserUuid(
uuid,
user.uuid,
Expand Down
5 changes: 2 additions & 3 deletions src/idp/idp.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import { LoginDto } from './dto/req/login.dto';
import { User } from '@prisma/client';
import { LoginResultType } from './types/loginResult.type';
import { CacheService } from 'src/cache/cache.service';
import { Loggable } from '@lib/logger/decorator/loggable';

@Injectable()
@Loggable()
export class IdpService {
private readonly logger = new Logger(IdpService.name);
private readonly refreshTokenPrefix = 'refreshToken';
Expand All @@ -18,7 +20,6 @@ export class IdpService {
) {}

async login({ email, password }: LoginDto): Promise<LoginResultType> {
this.logger.log(`login: ${email}`);
const user: User = await this.userService
.validateUserPassword({
email,
Expand Down Expand Up @@ -46,14 +47,12 @@ export class IdpService {
}

async logout(refreshToken: string): Promise<void> {
this.logger.log(`logout: ${refreshToken}`);
await this.cacheService.del(refreshToken, {
prefix: this.refreshTokenPrefix,
});
}

async refresh(refreshToken: string): Promise<LoginResultType> {
this.logger.log(`refresh: ${refreshToken}`);
if (!refreshToken) throw new UnauthorizedException();
const user: Pick<User, 'uuid'> = await this.cacheService
.getOrThrow<Pick<User, 'uuid'>>(refreshToken, {
Expand Down
3 changes: 2 additions & 1 deletion src/oauth/oauth.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import { Scope } from './types/Scopes.type';
import { UserInfo } from 'src/idp/types/userInfo.type';
import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library';
import { ExtendedRefreshToken } from './types/extendedRefreshToken.type';
import { Loggable } from '@lib/logger/decorator/loggable';

const MAX_REFRESH_TOKEN_COUNT = 10;

@Injectable()
@Loggable()
export class OauthRepository {
private readonly logger = new Logger(OauthRepository.name);
constructor(private readonly prismaService: PrismaService) {}
Expand All @@ -22,7 +24,6 @@ export class OauthRepository {
scope: Readonly<Scope[]>,
clientId: string,
): Promise<void> {
this.logger.log(`updateUserConsent: user=${JSON.stringify(user)}`);
// TODO: reduce this query
const client = await this.prismaService.client.findUniqueOrThrow({
where: {
Expand Down
7 changes: 2 additions & 5 deletions src/oauth/oauth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ import { Client } from '@prisma/client';
import { RevokeDto } from './dto/req/revoke.dto';
import { JwtPayload } from 'jsonwebtoken';
import { CacheService } from 'src/cache/cache.service';
import { Loggable } from '@lib/logger/decorator/loggable';

@Injectable()
@Loggable()
export class OauthService {
private readonly logger = new Logger(OauthService.name);
private readonly CodePrefix = 'code';
Expand All @@ -46,7 +48,6 @@ export class OauthService {
* @returns certificate for jwt
*/
certs(): object {
this.logger.log('certs');
return {
keys: [this.cert()],
};
Expand All @@ -62,8 +63,6 @@ export class OauthService {
{ clientId, redirectUri, nonce, scope, responseType }: AuthorizeDto,
userInfo: UserInfo,
): Promise<AuthorizeResType> {
this.logger.log('authorize');

// if the client is not valid, it throws an error
if (!(await this.clientService.validateUri(clientId, redirectUri))) {
throw new UnauthorizedException('unauthorized_client');
Expand Down Expand Up @@ -127,7 +126,6 @@ export class OauthService {
{ code, redirectUri, grantType, refreshToken, ...clientInfo }: TokenDto,
client?: Client,
): Promise<AuthorizeResType> {
this.logger.log('token');
const clientId = client === undefined ? clientInfo.clientId : client.id;
if (
clientInfo.clientId &&
Expand Down Expand Up @@ -173,7 +171,6 @@ export class OauthService {
{ token, tokenTypeHint, ...clientInfo }: RevokeDto,
client?: Client,
): Promise<void> {
this.logger.log('revoke');
const clientId = client === undefined ? clientInfo.clientId : client.id;
if (tokenTypeHint === 'access_token') {
await this.revokeAccessToken(token, clientId);
Expand Down
Loading

0 comments on commit 4de34de

Please sign in to comment.