Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@
"seed:users": "ts-node -r tsconfig-paths/register src/scripts/seed-users-teams.ts"
},
"dependencies": {
"@nestjs/common": "^11.1.13",
"@nestjs/common": "^11.1.14",
"@nestjs/config": "^4.0.3",
"@nestjs/core": "^11.1.13",
"@nestjs/core": "^11.1.14",
"@nestjs/jwt": "^11.0.2",
"@nestjs/microservices": "^11.1.13",
"@nestjs/microservices": "^11.1.14",
"@nestjs/passport": "^11.0.5",
"@nestjs/platform-express": "^11.1.13",
"@nestjs/platform-express": "^11.1.14",
"@nestjs/schedule": "^6.1.1",
"@nestjs/swagger": "^11.2.6",
"@nestjs/typeorm": "^11.0.0",
Expand All @@ -47,11 +47,14 @@
"cookie-parser": "^1.4.7",
"crypto-js": "^4.2.0",
"jiti": "^2.6.1",
"nestjs-pino": "^4.6.0",
"passport": "^0.7.0",
"passport-github2": "^0.1.12",
"passport-jwt": "^4.0.1",
"passport-oauth2": "^1.8.0",
"pg": "^8.18.0",
"pino": "^10.3.1",
"pino-http": "^11.0.0",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.2",
"tournament-pairings": "^2.0.1",
Expand All @@ -62,21 +65,22 @@
"@eslint/js": "^10.0.1",
"@nestjs/cli": "^11.0.16",
"@nestjs/schematics": "^11.0.9",
"@nestjs/testing": "^11.1.13",
"@nestjs/testing": "^11.1.14",
"@swc/cli": "^0.8.0",
"@swc/core": "^1.15.11",
"@types/cookie-parser": "^1.4.10",
"@types/express": "^5.0.6",
"@types/jest": "^30.0.0",
"@types/node": "^25.2.3",
"@types/node": "^25.3.0",
"@types/passport-local": "^1.0.38",
"@types/supertest": "^6.0.3",
"dotenv": "^17.3.1",
"eslint": "^10.0.0",
"eslint": "^10.0.1",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.5",
"globals": "^17.3.0",
"jest": "^30.2.0",
"pino-pretty": "^13.1.3",
"prettier": "^3.8.1",
"source-map-support": "^0.5.21",
"supertest": "^7.2.2",
Expand Down
1,203 changes: 710 additions & 493 deletions api/pnpm-lock.yaml

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions api/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { DatabaseConfig } from "./DatabaseConfig";
import { GithubApiModule } from "./github-api/github-api.module";
import { ScheduleModule } from "@nestjs/schedule";
import { StatsModule } from "./stats/stats.module";
import { LoggerModule } from "nestjs-pino";
import { Request } from "express";

@Module({
imports: [
Expand All @@ -20,6 +22,44 @@ import { StatsModule } from "./stats/stats.module";
isGlobal: true,
envFilePath: ".env",
}),
LoggerModule.forRoot({
pinoHttp: {
autoLogging: true,
transport:
process.env.NODE_ENV !== "production"
? {
target: "pino-pretty",
options: {
singleLine: true,
colorize: true,
ignore: "pid,hostname",
messageFormat: "[{context}] {msg}",
},
}
: undefined,
customProps: (req: Request) => {
const customReq = req as Request & { user?: { id: string } };
const user = customReq.user;
return {
userId: user?.id,
};
},
serializers: {
req: (req) => {
return {
id: req.id,
method: req.method,
url: req.url,
};
},
res: (res) => {
return {
statusCode: res.statusCode,
};
},
},
},
}),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: (config: ConfigService) => {
Expand Down
9 changes: 8 additions & 1 deletion api/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Req,
Res,
UseGuards,
Logger,
} from "@nestjs/common";
import { UserEntity } from "../user/entities/user.entity";
import { AuthGuard } from "@nestjs/passport";
Expand All @@ -21,6 +22,8 @@ import { SocialPlatform } from "../user/entities/social-account.entity";

@Controller("auth")
export class AuthController {
private readonly logger = new Logger(AuthController.name);

constructor(
private readonly auth: AuthService,
private readonly configService: ConfigService,
Expand All @@ -32,6 +35,8 @@ export class AuthController {
@UseGuards(AuthGuard("github"))
githubCallback(@Req() req: Request, @Res() res: Response) {
const user = req.user as UserEntity;
this.logger.log({ action: "github_login", userId: user.id });

const token = this.auth.signToken(user);
const redirectUrl = this.configService.getOrThrow<string>(
"OAUTH_SUCCESS_REDIRECT_URL",
Expand Down Expand Up @@ -105,14 +110,16 @@ export class AuthController {
username: request.user.fortyTwoAccount.username,
});

this.logger.log({ action: "fortytwo_link", userId });

const redirectUrl = this.configService.getOrThrow<string>(
"OAUTH_42_SUCCESS_REDIRECT_URL",
);

return res.redirect(redirectUrl);
} catch (e) {
// Use a more detailed log, and preserve specific error messages for BadRequestException
console.error("Error in FortyTwo callback:", e);
this.logger.error("Error in FortyTwo callback:", e);
if (e instanceof BadRequestException) {
throw e;
}
Expand Down
56 changes: 56 additions & 0 deletions api/src/common/AllExceptionsFilter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpException,
HttpStatus,
Logger,
} from "@nestjs/common";
import { HttpAdapterHost } from "@nestjs/core";

@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
private readonly logger = new Logger(AllExceptionsFilter.name);

constructor(private readonly httpAdapterHost: HttpAdapterHost) {}

catch(exception: unknown, host: ArgumentsHost): void {
const { httpAdapter } = this.httpAdapterHost;
const ctx = host.switchToHttp();

const httpStatus =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;

const responseBody = {
statusCode: httpStatus,
timestamp: new Date().toISOString(),
path: httpAdapter.getRequestUrl(ctx.getRequest()),
message:
exception instanceof HttpException
? exception.message
: "Internal server error",
};

if (httpStatus >= 500) {
if (exception instanceof Error) {
this.logger.error(exception.message, exception.stack);
} else {
this.logger.error(`Unhandled Exception: ${exception}`);
}
} else {
// 4xx errors
if (exception instanceof Error) {
this.logger.warn(
`HTTP Exception: ${exception.message}`,
exception.stack,
);
} else {
this.logger.warn(`HTTP Exception: ${exception}`);
}
}

httpAdapter.reply(ctx.getResponse(), responseBody, httpStatus);
}
}
11 changes: 10 additions & 1 deletion api/src/common/TypeormExceptionFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,23 @@ import {
Catch,
ArgumentsHost,
HttpStatus,
Logger,
} from "@nestjs/common";
import { Response } from "express";
import { Response, Request } from "express";

@Catch(EntityNotFoundError)
export class TypeormExceptionFilter implements ExceptionFilter {
catch(exception: EntityNotFoundError, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();

// Log the error
Logger.error(
`Entity not found for request ${request.method} ${request.url}`,
exception.stack,
"TypeormExceptionFilter",
);

response.status(HttpStatus.NOT_FOUND).json({
statusCode: HttpStatus.NOT_FOUND,
Expand Down
2 changes: 1 addition & 1 deletion api/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ export const enum LockKeys {
AUTO_LOCK_EVENTS = 12345,
CREATE_TEAM_REPOS = 12346,
PROCESS_QUEUE_MATCHES = 12347,
}
}
1 change: 0 additions & 1 deletion api/src/event/dtos/createEventDto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,4 @@ export class CreateEventDto {
@ApiProperty()
@IsBoolean()
isPrivate: boolean;

}
1 change: 0 additions & 1 deletion api/src/event/dtos/updateEventSettingsDto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,3 @@ export class UpdateEventSettingsDto {
@IsString()
serverConfig?: string;
}

Loading