Skip to content

Commit

Permalink
chore(project): finish docs and clear project (#230)
Browse files Browse the repository at this point in the history
* feat: refactor environment variables (#227)

* feat: refactor environment variables

* chore: remove unused line in docker-compose.yml

* feat: remove FORTYTWO_API_CALLBACK

* feat: add signup endpoint to backend API

---------

Co-authored-by: Tanguy Rossel <tanguy.rossel@tyrossel.ch>

* fix(game): repair websockets

* docs(project): finishing docs (#229)

* chore(clean): remove dead docs and prepare screenshots in readme

* docs(backend): clear and finish backend docs

* docs(readme): docs done

* docs(readme): trying to reduce image size

* docs(readme): trying to reduce image size

* docs(readme): trying to reduce image size

* docs(readme): trying to reduce image size

* docs(readme): trying to reduce image size

* docs(readme): trying to reduce image size

* docs(readme): trying to reduce image size

* docs(readme): trying to reduce image size

* docs(readme): trying to reduce image size

* docs(readme): trying to reduce image size

* docs(readme): trying to reduce image size

* docs(backend): finish docs

---------

Co-authored-by: Tanguy Rossel <trossel@student.42lausanne.ch>
Co-authored-by: Tanguy Rossel <tanguy.rossel@tyrossel.ch>
  • Loading branch information
3 people committed Aug 5, 2023
1 parent a4ae8a5 commit 0ccd2cd
Show file tree
Hide file tree
Showing 45 changed files with 1,151 additions and 1,394 deletions.
14 changes: 6 additions & 8 deletions env/.backend.env.example → .env.example
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
# Backend

# Change them to your uid/gid for the volumes ownership (defaults to yours)
# UID=1000
# GID=1000

# Name of the cookie. Must be the same as in frontend
FRONTEND_URL=https://localhost:4443
BACKEND_URL=https://localhost:4443/api

# Name of the cookie where the user info are stored
JWT_COOKIE=access_token

# Change me and keep me secret !
# Can for example be generated with `openssl rand -hex 32`
JWT_KEY=mySecretKey

# 42 Oauth variables
FORTYTWO_API_UID=
FORTYTWO_API_SECRET=
FORTYTWO_API_CALLBACK=https://localhost:4443/api/auth/42/callback
FRONTEND_URL=https://localhost:4443
FORTYTWO_API_UID=u-s4t2ud-e8dbb95b572290b805d9c2c148f53c1872a965830dd887fc7f90c9e77a377db2
FORTYTWO_API_SECRET=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

# Postgres
POSTGRES_HOST=db
POSTGRES_PORT=5432
POSTGRES_DB=postgres
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ compile_commands.json
# Vue

# Env files
env/*.env
.env
56 changes: 54 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# ft_transcendence
Single Page Application Website. This is the last project of 42 School common core.
Single Page Application Website. This is the last project of 42 School common core.
This project is a website that includes a multiplayer pong game.

## Launch the project locally
### Clone the repository
Expand All @@ -9,16 +10,67 @@ git clone git@github.com:Bima42/ft_transcendence.git
cd ft_transcendence
```

### Setting up environment variables
- Rename `.env.example` to `.env`
- Change the values of the variables `FORTYTWO_API_UID` and `FORTYTWO_API_SECRET` in `.env` to match your environment
- You should also configure `JWT_KEY`

### Run containers
- Use `--build` to rebuild images
- Use `--force-recreate` to force recreate image and containers
- Use `-d` to run containers in background

```bash
docker compose up -d
```

### Reach the website
- Go to `https://localhost:4443`

## Documentation
- ### [Summary](docs/Summary.md)
- ### [Docker](docs/docker/0-what-is-docker.md)
- ### [Docker Commands](docs/docker/3-docker-usefull-commands.md)
- ### [NestJS](docs/nestjs/0-what-is-nestjs.md)
- ### [Backend](docs/backend/0-what-is-nestjs.md)

## Website overview
### Login

<p align="center">
<img src="docs/images/login_page.png">
</p>

### Home
<p align="center">
<img src="docs/images/home_page.png">
</p>

### Profile
<p align="center">
<img src="docs/images/profile_page.png">
</p>

### Chat
<p align="center">
<img src="docs/images/chat_page.png">
</p>

#### Chat with a friend
<p align="center">
<img src="docs/images/chat_with_a_friend.png">
</p>

### Game
<p align="center">
<img src="docs/images/game_page.png">
</p>

#### In game
<p align="center">
<img src="docs/images/in_game_page.png">
</p>

### Leaderboard
<p align="center">
<img src="docs/images/leaderboard_page.png">
</p>
2 changes: 1 addition & 1 deletion backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ $ npm run start:prod

## Backend Structure
<p align="center">
<img src="../docs/nestjs/database_structure.png">
<img src="../docs/backend/database_structure.png">
</p>

## License
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "User" ALTER COLUMN "avatar" DROP DEFAULT;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "User" ALTER COLUMN "avatar" SET DEFAULT '';
2 changes: 1 addition & 1 deletion backend/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ model User {
fortyTwoId Int?
username String @unique @db.VarChar(255)
email String @unique
avatar String
avatar String @default("")
firstName String?
lastName String?
phone String?
Expand Down
2 changes: 1 addition & 1 deletion backend/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export class AuthController {
phone: null,
status: 'OFFLINE',
}
bob = await this.usersService.create(bob, username);
bob = await this.usersService.create(bob, true);
}
// If a real user is using this pseudo, abort
if (bob.fortyTwoId != null) {
Expand Down
7 changes: 4 additions & 3 deletions backend/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { User } from '@prisma/client';
import { UsersService } from '../users/users.service';
import { RequestWithUser } from '../interfaces/request-with-user.interface';
import { generateUsername } from 'unique-username-generator';
import { CreateUserDto } from 'src/users/dto/user.dto';

@Injectable()
export class AuthService {
Expand Down Expand Up @@ -33,7 +34,7 @@ export class AuthService {
client_id: process.env.FORTYTWO_API_UID,
client_secret: process.env.FORTYTWO_API_SECRET,
code: code,
redirect_uri: process.env.FORTYTWO_API_CALLBACK,
redirect_uri: process.env.BACKEND_URL + "/auth/42/callback",
}),
});
const tokenData = await tokenResponse.json();
Expand Down Expand Up @@ -87,7 +88,7 @@ export class AuthService {
});

if (!user) {
const data = {
const data: CreateUserDto = {
username: username,
email: email,
firstName: firstName,
Expand All @@ -96,7 +97,7 @@ export class AuthService {
fortyTwoId: fortyTwoId,
avatar: avatar
}
const newUser = await this.usersService.create(data, username);
const newUser = await this.usersService.create(data, true);
return {
user: newUser,
firstLogin: true
Expand Down
37 changes: 37 additions & 0 deletions backend/src/users/dto/user.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
IsEmail,
IsEnum,
IsNotEmpty,
IsNumber,
IsOptional,
IsPhoneNumber,
IsString,
Expand All @@ -13,6 +14,42 @@ import {
MinLength
} from 'class-validator';

export class CreateUserDto {

@MinLength(2)
@MaxLength(20)
@Matches(/^[a-zA-Z0-9_-]+$/, {message: "Username must contains only letters, numbers or -_"})
username: string

@IsEmail()
email: string

@IsOptional()
@IsString()
@IsNotEmpty()
@ApiProperty({required: false})
avatar?: string;

@IsOptional()
@IsNumber()
@IsNotEmpty()
@ApiProperty({required: false})
fortyTwoId?: number;

@MinLength(1)
@MaxLength(60)
firstName: string

@MinLength(1)
@MaxLength(60)
lastName: string

@IsOptional()
@IsPhoneNumber()
@ApiProperty({required: false})
phone?: string
}

export class UpdateUserDto {

@IsOptional()
Expand Down
12 changes: 10 additions & 2 deletions backend/src/users/users.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import {
Param,
Delete,
ParseIntPipe,
UseInterceptors, UploadedFile, ParseFilePipeBuilder, Req, Logger
UseInterceptors,
UploadedFile,
ParseFilePipeBuilder,
Req,
} from '@nestjs/common';
import { UsersService } from './users.service';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
Expand All @@ -16,7 +19,7 @@ import { FileInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import * as path from 'path';
import { toUserDto } from 'src/shared/mapper/user.mapper';
import { UpdateUserDto, UserDto } from './dto/user.dto';
import { CreateUserDto, UpdateUserDto, UserDto } from './dto/user.dto';


const storage = {
Expand All @@ -39,6 +42,11 @@ export class UsersController {
private readonly usersService: UsersService
) {}

@Post('signup')
async signup(@Body() newUser: CreateUserDto) : Promise<UserDto> {
return toUserDto(await this.usersService.create(newUser, false))
}

@Get('all')
async getAllUsers(): Promise<UserDto[]> {
return await this.usersService.findAll();
Expand Down
1 change: 1 addition & 0 deletions backend/src/users/users.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export class UsersModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(UsersMiddleware)
.exclude('users/signup')
.forRoutes(UsersController, UserStatsController, FriendsController);
}
}
12 changes: 8 additions & 4 deletions backend/src/users/users.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { BadRequestException, NotFoundException, Injectable, InternalServerErrorException } from '@nestjs/common';
import { BadRequestException, NotFoundException, Injectable, InternalServerErrorException, ConflictException } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { User } from '@prisma/client';
import { UpdateUserDto, UserDto } from './dto/user.dto';
import { CreateUserDto, UpdateUserDto, UserDto } from './dto/user.dto';
import { toUserDto } from '../shared/mapper/user.mapper';
import { generateUsername } from 'unique-username-generator';

Expand All @@ -11,16 +11,18 @@ export class UsersService {
private readonly prismaService: PrismaService
) { }

async create(data: any, username: string): Promise<User> {
async create(data: CreateUserDto, generateNewUsername: boolean): Promise<User> {
// Verify if username is already taken
const existingUser = await this.prismaService.user.findUnique({
where: {
username: username
username: data.username
},
select: {
username: true
}
});
if (existingUser && !generateNewUsername)
throw new ConflictException("Username already exists")

while (existingUser?.username) {
existingUser.username = generateUsername();
Expand All @@ -35,6 +37,8 @@ export class UsersService {
}
}

if (!data.avatar)
data.avatar = process.env.BACKEND_URL + "/uploads/default.png"
let newUser: User | null = null;
try {
newUser = await this.prismaService.user.create({
Expand Down
Loading

0 comments on commit 0ccd2cd

Please sign in to comment.