Skip to content

Commit

Permalink
Merge pull request #22 from katelovestocode/BE-20-connect-to-AWS
Browse files Browse the repository at this point in the history
BE-20-connect-to-aws
  • Loading branch information
Ivanus-Volodymyr authored Jan 4, 2024
2 parents 51b24de + c295212 commit 5b56f4f
Show file tree
Hide file tree
Showing 15 changed files with 210 additions and 62 deletions.
6 changes: 5 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ REFRESH_SECRET_KEY=
ACTION_SECRET_KEY=

AUTH0_AUDIENCE=
AUTH0_ISSUER_URL=
AUTH0_ISSUER_URL=
AUTH0_JWKS_URL=

REDIS_PASSWORD=
REDIS_URL=
16 changes: 11 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Deploy to EC2 from Develop
name: Deploy to EC2

on:
push:
Expand All @@ -21,11 +21,13 @@ jobs:
username: ${{ secrets.AWS_EC2_USERNAME }}
key: ${{ secrets.AWS_SSH_PRIVATE_KEY }}
port: ${{ secrets.AWS_PORT }}

script: |
set -x
cd app/backend-internship
git checkout develop
git pull origin develop
git fetch origin
git reset --hard origin/develop
git pull origin develop
echo "PORT=${{ secrets.PORT }}" > .env
echo "HOST=${{ secrets.HOST }}" >> .env
Expand All @@ -42,9 +44,13 @@ jobs:
echo "AUTH0_AUDIENCE=${{ secrets.AUTH0_AUDIENCE }}" >> .env
echo "AUTH0_ISSUER_URL=${{ secrets.AUTH0_ISSUER_URL }}" >> .env
echo "REDIS_URL=${{ secrets.REDIS_URL }}" >> .env
echo "REDIS_PASSWORD=${{ secrets.REDIS_PASSWORD }}" >> .env
echo "AUTH0_JWKS_URL=${{ secrets.AUTH0_JWKS_URL }}" >> .env
cp /etc/ssl/private/certificate.crt certificate.crt
cp /etc/ssl/private/private.key private.key
docker-compose stop backend
docker-compose rm -f backend
sudo chmod -R 777 pgdata
docker-compose up --build -d
docker-compose build backend
docker-compose up --no-deps -d backend
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ lerna-debug.log*
!.vscode/extensions.json

.env
pgdata/
#pgdata/
34 changes: 34 additions & 0 deletions Dockerfile.backend
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#base
FROM node:18-alpine As base

WORKDIR /app

COPY package*.json ./

COPY . .

EXPOSE 3002

RUN npm install

# to run tests
FROM base As test

WORKDIR /app

COPY test ./test

CMD [ "npm", "run", "test" ]

# to run in production
FROM base As prod

WORKDIR /app

RUN npm run build

ENV PORT=3002

ENV HOSTNAME="0.0.0.0"

CMD [ "npm", "run", "start:prod" ]
39 changes: 39 additions & 0 deletions Dockerfile.nginx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Dockerfile.nginx

FROM nginx:1.23.3-alpine

# Create a non-privileged user for running Nginx
RUN adduser --disabled-password --gecos '' nginxuser

RUN mkdir -p /var/cache/nginx/client_temp \
&& mkdir -p /var/cache/nginx/proxy_temp \
&& mkdir -p /var/cache/nginx/fastcgi_temp \
&& chown -R nginxuser:nginxuser /var/cache/nginx

# Create the directory for PID file
RUN mkdir -p /var/run/nginx/

# Set appropriate permissions for the PID directory
RUN chown -R nginxuser:nginxuser /var/run/nginx/

# Create the directory for SSL certificates
RUN mkdir -p /etc/ssl/private/

# Create the directory for Nginx cache
RUN mkdir -p /var/cache/nginx/client_temp
RUN mkdir -p /var/cache/nginx/proxy_temp
RUN mkdir -p /var/cache/nginx/fastcgi_temp

RUN chown -R nginxuser:nginxuser /var/cache/nginx

# Copy SSL certificates into the Docker image
COPY certificate.crt /etc/ssl/private/certificate.crt
COPY private.key /etc/ssl/private/private.key

# Copy Nginx configuration file
COPY nginx.conf /etc/nginx/nginx.conf

EXPOSE 80 443

USER nginxuser
CMD ["nginx", "-g", "daemon off;"]
12 changes: 6 additions & 6 deletions db/typeorm.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ export default new DataSource({
synchronize: false,
migrationsTableName: 'migrations',
logging: ['query', 'error'],
ssl: true,
extra: {
ssl: {
rejectUnauthorized: false,
}
}
// ssl: true,
// extra: {
// ssl: {
// rejectUnauthorized: false,
// }
// }
})
31 changes: 17 additions & 14 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: '3.8'
services:
db:
container_name: postgres-fullstack
Expand All @@ -9,16 +8,16 @@ services:
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB=${DB_NAME}
volumes:
- ./pgdata:/var/lib/postgresql/data
- postgres-data:/var/lib/postgresql/data
ports:
- ${DB_PORT}:${DB_PORT}
backend:
container_name: backend-fullstack
image: backend-backend:latest
volumes:
- pgdata:/pgdata
build:
context: ./
dockerfile: Dockerfile.backend
depends_on:
- db
restart: unless-stopped
Expand All @@ -33,16 +32,20 @@ services:
- DB_PASSWORD=${DB_PASSWORD}
- DB_NAME=${DB_NAME}
- DB_PORT=${DB_PORT}

# redis:
# image: redis
# ports:
# - '6379:6379'
# container_name: redis-cache
# environment:
# - REDIS_HOSTS=local:redis:6379
# volumes:
# - ./redis/data:/data

nginx:
build:
context: .
dockerfile: Dockerfile.nginx
container_name: nginx-fullstack
ports:
- '80:80'
- '443:443'
volumes:
- /etc/ssl:/etc/nginx/ssl:ro
- nginx_cache:/var/cache/nginx
user: 'nginxuser'
restart: always
volumes:
postgres-data:
pgdata:
nginx_cache:
54 changes: 54 additions & 0 deletions nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
user nginxuser;
pid /tmp/nginx.pid;

events {
}

http {
upstream backend {
server backend:3002;
}

server {
# Redirect HTTP requests to HTTPS.
listen 80;
server_name localhost;
root /srv/public;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl;

server_name localhost;
root /srv/public;
server_tokens off;

ssl_certificate /etc/ssl/private/certificate.crt;
ssl_certificate_key /etc/ssl/private/private.key;

location / {
try_files $uri $uri/ @backend;
}

location @backend {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://backend;
proxy_cookie_path / "/; HTTPOnly; Secure";
}

# WebSocket configuration
location /socket.io/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
}
}
}
Binary file modified redis/data/dump.rdb
Binary file not shown.
2 changes: 2 additions & 0 deletions src/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ export class AuthService {
adminCompanies,
quizAttempts,
notifications,
averageRating
} = await this.userService.getUserByEmail(user.email)

return {
Expand All @@ -200,6 +201,7 @@ export class AuthService {
adminCompanies,
quizAttempts,
notifications,
averageRating
},
},
}
Expand Down
24 changes: 15 additions & 9 deletions src/events/events.gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { WebSocketGateway, WebSocketServer } from '@nestjs/websockets'
import { Server, Socket } from 'socket.io'
import { NotificationPayload } from './interface/interface'
import { WebsocketJwtGuard } from './guard/websocket-jwt.guard'
import { Logger, UseGuards } from '@nestjs/common'
import { Logger } from '@nestjs/common'
import { JwtService } from '@nestjs/jwt'

@WebSocketGateway({
Expand All @@ -11,7 +11,6 @@ import { JwtService } from '@nestjs/jwt'
},
})
@WebSocketGateway()
@UseGuards(WebsocketJwtGuard)
export class EventsGateway {
constructor(private readonly jwtService: JwtService) {}
private readonly logger = new Logger(EventsGateway.name)
Expand All @@ -20,14 +19,21 @@ export class EventsGateway {
server: Server

async handleConnection(client: Socket): Promise<void> {
const user = await WebsocketJwtGuard.validateToken(this.jwtService, client)

if (user) {
await client.join(user.id.toString())
this.logger.log(`User ${user.id} is connected`)
} else {
try {
const user = await WebsocketJwtGuard.validateToken(
this.jwtService,
client,
)
if (user) {
await client.join(user.id.toString())
this.logger.log(`User ${user.id} is connected`)
} else {
client.disconnect()
this.logger.log(`User ${user.id} is disconnected`)
}
} catch (error) {
this.logger.log('JWT validation error:', error.message)
client.disconnect()
this.logger.log(`User ${user.id} is disconnected`)
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/events/guard/websocket-jwt.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export class WebsocketJwtGuard implements CanActivate {

static validateToken(jwtService: JwtService, client: Socket) {
const { authorization } = client.handshake.headers
if (!authorization) {
throw new Error('Authorization header is missing')
}
const token: string = authorization.split(' ')[1]
const payload = jwtService.verify(token, {
secret: process.env.ACCESS_SECRET_KEY,
Expand Down
45 changes: 19 additions & 26 deletions src/quiz_attempts/quiz_attempt.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,14 @@ export class QuizAttemptService {
timestamp: new Date(),
})

const currentUser = await this.userRepository.findOne({
where: { id: user.id },
})
// save averageRating into users table
currentUser.averageRating = overallRatingAcrossSystem

await this.userRepository.save(currentUser)

// check for cache first
const cachedResponse = await this.redisService.get(
`quiz_responses:${user.id}:${quiz.id}:${quiz.company}`,
Expand Down Expand Up @@ -261,35 +269,20 @@ export class QuizAttemptService {
totalQuestions: number,
) {
try {
const allUsers = await this.userRepository.find({
relations: ['quizAttempts', 'quizAttempts.quiz.company'],
})

const totalCorrectAcrossSystem = allUsers.reduce((sum, currentUser) => {
let userTotalCorrect = currentUser.quizAttempts.reduce(
(userSum, attempt) => userSum + attempt.totalCorrect,
0,
)

if (currentUser.id === user.id) {
userTotalCorrect += totalCorrect
}
const allQuizAttempts = user.quizAttempts

return sum + userTotalCorrect
}, 0)

const totalQuestionsAcrossSystem = allUsers.reduce((sum, currentUser) => {
let userTotalQuestions = currentUser.quizAttempts.reduce(
(userSum, attempt) => userSum + attempt.totalQuestions,
0,
)
let totalCorrectAcrossSystem = allQuizAttempts.reduce(
(sum, attempt) => sum + attempt.totalCorrect,
0,
)

if (currentUser.id === user.id) {
userTotalQuestions += totalQuestions
}
let totalQuestionsAcrossSystem = allQuizAttempts.reduce(
(sum, attempt) => sum + attempt.totalQuestions,
0,
)

return sum + userTotalQuestions
}, 0)
totalCorrectAcrossSystem += totalCorrect
totalQuestionsAcrossSystem += totalQuestions

const overallRatingAcrossSystem =
totalQuestionsAcrossSystem > 0
Expand Down
Loading

0 comments on commit 5b56f4f

Please sign in to comment.