Compare commits
No commits in common. "9792110560f3d16ad665ec2aecef98ce1f7dd4eb" and "4dbb85878290eebd8ef449cc98e1df35eddacbf4" have entirely different histories.
9792110560
...
4dbb858782
75
.github/README.md
vendored
75
.github/README.md
vendored
@ -1,75 +0,0 @@
|
|||||||
# CI/CD and Deployment Documentation
|
|
||||||
|
|
||||||
This directory contains the CI/CD configuration for the project.
|
|
||||||
|
|
||||||
## CI/CD Workflow
|
|
||||||
|
|
||||||
The CI/CD pipeline is configured using GitHub Actions and is defined in the `.github/workflows/ci-cd.yml` file. The workflow consists of the following steps:
|
|
||||||
|
|
||||||
### Build and Test
|
|
||||||
|
|
||||||
This job runs on every push to the main branch and on pull requests:
|
|
||||||
|
|
||||||
1. Sets up Node.js and pnpm
|
|
||||||
2. Installs dependencies
|
|
||||||
3. Builds and tests the backend
|
|
||||||
4. Builds and lints the frontend
|
|
||||||
|
|
||||||
### Build and Push Docker Images
|
|
||||||
|
|
||||||
This job runs only on pushes to the main branch:
|
|
||||||
|
|
||||||
1. Sets up Docker Buildx
|
|
||||||
2. Logs in to GitHub Container Registry
|
|
||||||
3. Builds and pushes the backend Docker image
|
|
||||||
4. Builds and pushes the frontend Docker image
|
|
||||||
|
|
||||||
## Deployment
|
|
||||||
|
|
||||||
The application is containerized using Docker. Dockerfiles are provided for both the backend and frontend:
|
|
||||||
|
|
||||||
- `backend/Dockerfile`: Multi-stage build for the NestJS backend
|
|
||||||
- `frontend/Dockerfile`: Multi-stage build for the Next.js frontend
|
|
||||||
|
|
||||||
A `docker-compose.yml` file is also provided at the root of the project for local development and as a reference for deployment.
|
|
||||||
|
|
||||||
### Running Locally with Docker Compose
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Build and start all services
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# View logs
|
|
||||||
docker-compose logs -f
|
|
||||||
|
|
||||||
# Stop all services
|
|
||||||
docker-compose down
|
|
||||||
```
|
|
||||||
|
|
||||||
### Environment Variables
|
|
||||||
|
|
||||||
The following environment variables are used in the deployment:
|
|
||||||
|
|
||||||
#### Backend
|
|
||||||
- `NODE_ENV`: Environment (development, production)
|
|
||||||
- `PORT`: Port on which the backend runs
|
|
||||||
- `POSTGRES_HOST`: PostgreSQL host
|
|
||||||
- `POSTGRES_PORT`: PostgreSQL port
|
|
||||||
- `POSTGRES_DB`: PostgreSQL database name
|
|
||||||
- `POSTGRES_USER`: PostgreSQL username
|
|
||||||
- `POSTGRES_PASSWORD`: PostgreSQL password
|
|
||||||
|
|
||||||
#### Frontend
|
|
||||||
- `NODE_ENV`: Environment (development, production)
|
|
||||||
- `PORT`: Port on which the frontend runs
|
|
||||||
- `NEXT_PUBLIC_API_URL`: URL of the backend API
|
|
||||||
|
|
||||||
## Production Deployment Considerations
|
|
||||||
|
|
||||||
For production deployment, consider the following:
|
|
||||||
|
|
||||||
1. Use a proper secrets management solution for sensitive information
|
|
||||||
2. Set up proper networking and security groups
|
|
||||||
3. Configure a reverse proxy (like Nginx) for SSL termination
|
|
||||||
4. Set up monitoring and logging
|
|
||||||
5. Configure database backups
|
|
@ -1,6 +1,5 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
import { APP_GUARD } from '@nestjs/core';
|
|
||||||
import { AppController } from './app.controller';
|
import { AppController } from './app.controller';
|
||||||
import { AppService } from './app.service';
|
import { AppService } from './app.service';
|
||||||
import { DatabaseModule } from './database/database.module';
|
import { DatabaseModule } from './database/database.module';
|
||||||
@ -9,7 +8,6 @@ import { ProjectsModule } from './modules/projects/projects.module';
|
|||||||
import { AuthModule } from './modules/auth/auth.module';
|
import { AuthModule } from './modules/auth/auth.module';
|
||||||
import { GroupsModule } from './modules/groups/groups.module';
|
import { GroupsModule } from './modules/groups/groups.module';
|
||||||
import { TagsModule } from './modules/tags/tags.module';
|
import { TagsModule } from './modules/tags/tags.module';
|
||||||
import { JwtAuthGuard } from './modules/auth/guards/jwt-auth.guard';
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@ -25,12 +23,6 @@ import { JwtAuthGuard } from './modules/auth/guards/jwt-auth.guard';
|
|||||||
TagsModule,
|
TagsModule,
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [
|
providers: [AppService],
|
||||||
AppService,
|
|
||||||
{
|
|
||||||
provide: APP_GUARD,
|
|
||||||
useClass: JwtAuthGuard,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
@ -16,7 +16,6 @@ import { GithubAuthGuard } from '../guards/github-auth.guard';
|
|||||||
import { JwtAuthGuard } from '../guards/jwt-auth.guard';
|
import { JwtAuthGuard } from '../guards/jwt-auth.guard';
|
||||||
import { JwtRefreshGuard } from '../guards/jwt-refresh.guard';
|
import { JwtRefreshGuard } from '../guards/jwt-refresh.guard';
|
||||||
import { GetUser } from '../decorators/get-user.decorator';
|
import { GetUser } from '../decorators/get-user.decorator';
|
||||||
import { Public } from '../decorators/public.decorator';
|
|
||||||
|
|
||||||
@Controller('auth')
|
@Controller('auth')
|
||||||
export class AuthController {
|
export class AuthController {
|
||||||
@ -28,7 +27,6 @@ export class AuthController {
|
|||||||
/**
|
/**
|
||||||
* Initiate GitHub OAuth flow
|
* Initiate GitHub OAuth flow
|
||||||
*/
|
*/
|
||||||
@Public()
|
|
||||||
@Get('github')
|
@Get('github')
|
||||||
@UseGuards(GithubAuthGuard)
|
@UseGuards(GithubAuthGuard)
|
||||||
githubAuth() {
|
githubAuth() {
|
||||||
@ -39,7 +37,6 @@ export class AuthController {
|
|||||||
/**
|
/**
|
||||||
* Handle GitHub OAuth callback
|
* Handle GitHub OAuth callback
|
||||||
*/
|
*/
|
||||||
@Public()
|
|
||||||
@Get('github/callback')
|
@Get('github/callback')
|
||||||
@UseGuards(GithubAuthGuard)
|
@UseGuards(GithubAuthGuard)
|
||||||
async githubAuthCallback(@Req() req: Request, @Res() res: Response) {
|
async githubAuthCallback(@Req() req: Request, @Res() res: Response) {
|
||||||
@ -64,7 +61,6 @@ export class AuthController {
|
|||||||
/**
|
/**
|
||||||
* Refresh tokens
|
* Refresh tokens
|
||||||
*/
|
*/
|
||||||
@Public()
|
|
||||||
@Post('refresh')
|
@Post('refresh')
|
||||||
@UseGuards(JwtRefreshGuard)
|
@UseGuards(JwtRefreshGuard)
|
||||||
async refreshTokens(@GetUser() user) {
|
async refreshTokens(@GetUser() user) {
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Key for the public metadata
|
|
||||||
*/
|
|
||||||
export const IS_PUBLIC_KEY = 'isPublic';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decorator to mark a route as public (not requiring authentication)
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* - @Public() - Mark a route as public
|
|
||||||
*/
|
|
||||||
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
|
|
@ -1,33 +1,11 @@
|
|||||||
import { Injectable, UnauthorizedException, ExecutionContext } from '@nestjs/common';
|
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||||
import { AuthGuard } from '@nestjs/passport';
|
import { AuthGuard } from '@nestjs/passport';
|
||||||
import { Reflector } from '@nestjs/core';
|
|
||||||
import { IS_PUBLIC_KEY } from '../decorators/public.decorator';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guard for JWT authentication
|
* Guard for JWT authentication
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class JwtAuthGuard extends AuthGuard('jwt') {
|
export class JwtAuthGuard extends AuthGuard('jwt') {
|
||||||
constructor(private reflector: Reflector) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the route is public or requires authentication
|
|
||||||
*/
|
|
||||||
canActivate(context: ExecutionContext) {
|
|
||||||
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
|
|
||||||
context.getHandler(),
|
|
||||||
context.getClass(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (isPublic) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.canActivate(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle unauthorized errors
|
* Handle unauthorized errors
|
||||||
*/
|
*/
|
||||||
@ -37,4 +15,4 @@ export class JwtAuthGuard extends AuthGuard('jwt') {
|
|||||||
}
|
}
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user