Skip to content

Commit

Permalink
Merge pull request #65 from SarahAbuirmeileh/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
kldoon authored Oct 31, 2023
2 parents d661f2d + 4f3f08f commit aabe240
Show file tree
Hide file tree
Showing 71 changed files with 19,857 additions and 1,238 deletions.
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
dist
.env
88 changes: 88 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: Docker Image CI

on:
push:
branches:
- main
pull_request:
branches:
- main


jobs:
build:
runs-on: ubuntu-latest

permissions:
contents: read
packages: write

outputs:
ec2_ips: ${{ steps.get_instance_ips.outputs.ips }}
image_version: ${{ steps.image_version.outputs.gitsha }}

steps:
- uses: actions/checkout@v3

- name: Set image version (tag)
id: image_version
run: echo "gitsha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT

- name: login to Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: sarahabuirmeileh
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build the Docker image
run: docker build . --file Dockerfile --tag ghcr.io/sarahabuirmeileh/serve-and-shine:${{ steps.image_version.outputs.gitsha }}
- name: Puplish docker image
run: docker push ghcr.io/sarahabuirmeileh/serve-and-shine:${{ steps.image_version.outputs.gitsha }}

- name: Get EC2 Instance IPs
id: get_instance_ips
run: |
instances=$(aws ec2 describe-instances --filters "Name=tag:aws:autoscaling:groupName,Values=serve-and-shine-asg" --query 'Reservations[*].Instances[*].[PublicIpAddress]' --output json | jq --compact-output 'flatten')
echo "ips=$instances" >> $GITHUB_OUTPUT
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }}


deploy:
needs: ["build"]
runs-on: ubuntu-latest
strategy:
matrix:
ip: ${{ fromJson(needs.build.outputs.ec2_ips) }}
steps:
- uses: actions/checkout@v3
- name: configure docker host
uses: khaledez/configure-docker-host@v1
with:
host: ${{ matrix.ip }}
user: github
ssh-private-key: ${{ secrets.DEPLOYMENT_KEY }}
- name: login to Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: sarahabuirmeileh
password: ${{ secrets.GITHUB_TOKEN }}
- name: deploy
run: docker compose -f docker-compose-prod.yml up -d
env:
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
GIT_VERSISON: ${{ needs.build.outputs.image_version }}
SECRET_KEY: ${{ secrets.SECRET_KEY }}
DB_HOST: ${{ secrets.DB_HOST }}
DB_PORT: ${{ secrets.DB_PORT }}
DB_USERNAME: ${{ secrets.DB_USERNAME }}
DB_NAME: ${{ secrets.DB_NAME }}
AWS_BUCKET_NAME: ${{ secrets.AWS_BUCKET_NAME }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }}
AWS_CERTIFICATES_BUCKET_NAME: ${{ secrets.AWS_CERTIFICATES_BUCKET_NAME }}
PORT: ${{ secrets.PORT }}
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
node_modules
dist
.env
.env
.env.test
logger
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"cSpell.words": [
"Deregistration"
]
}
16 changes: 16 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM node:20-alpine

WORKDIR /user/app
COPY package.json package-lock.json ./

RUN npm ci

RUN apk add curl

ADD . .
RUN npm run build

HEALTHCHECK --interval=10s --timeout=3s \
CMD curl -f http://localhost/ || exit 1

CMD node --loader ts-node/esm ./dist/app.js
21 changes: 21 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Security Policy

## Supported Versions

Use this section to tell people about which versions of your project are
currently being supported with security updates.

| Version | Supported |
| ------- | ------------------ |
| 5.1.x | :white_check_mark: |
| 5.0.x | :x: |
| 4.0.x | :white_check_mark: |
| < 4.0 | :x: |

## Reporting a Vulnerability

Use this section to tell people how to report a vulnerability.

Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
declined, etc.
123 changes: 123 additions & 0 deletions __test__/route.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import "../dist/config.js";
import express from "express";
import request from "supertest";
import { createOrganizationAdmin } from "../dist/src/controllers/organizationAdmin.js";
import organizationProfileRouter from "../dist/src/routes/organizationProfile.js";
import organizationAdminRouter from "../dist/src/routes/organizationAdmin.js";
import volunteerRouter from "../dist/src/routes/volunteer.js";
import permissionRouter from "../dist/src/routes/permission.js";
import dataSource from "../dist/src/db/dataSource.js";
import { deleteOrganizationProfile } from "../dist/src/controllers/OrganizationProfile .js";
import dotenv from "dotenv";

dotenv.config();
const app = express();
app.use(express.json());

app.use('/organizationProfile', organizationProfileRouter);
app.use("/volunteer", volunteerRouter);
app.use('/organizationAdmin', organizationAdminRouter);
app.use('/permission', permissionRouter);
app.use(express.urlencoded({ extended: false }));


beforeAll(async () => {
await dataSource.initialize().then(() => {
console.log('DB connected');
}).catch(err => {
console.log("DB connection failed", err);
});
}, 30000);

afterAll(async () => {
await dataSource.destroy();
});

describe("Organization profile", () => {
it("should Create an Organization profile", async () => {
const org = {
name: "TestName",
description: "..."
};

const response = await request(app).post("/organizationProfile").send(org);

expect(response.status).toBe(201);

});
});

describe("Register process", () => {
it("should register a Volunteer in app", async () => {
const volunteer = {
name: "Tarteel",
email: "tamimitarteel@gamil.com",
password: "Tarteel123456?",
availableTime: ["Afternoon"],
availableLocation: "Hebron",
availableDays: ["Friday"],
skills: ["softskills"]
};

const response = await request(app).post("/volunteer/register").send(volunteer);

expect(response.status).toBe(201);
});
});

describe("Login process", () => {
it("should login a Volunteer in app", async () => {
const volunteer = {
name: "Tarteel",
email: "tamimitarteel@gamil.com",
id: "......"
};

const response = await request(app).post("/volunteer/login").send(volunteer);

expect(response.status).toBe(201);
});
});

describe("Logout process", () => {
it("should logout a Volunteer in app", async () => {

const response = await request(app).get("/volunteer/logout");

expect(response.status).toBe(200);
});
});

describe("Permission", () => {
it("should get all permissions", async () => {

const response = await request(app).get("/permission").send(volunteer);

expect(response.status).toBe(200);
});
});

describe("Organization admin", () => {
it("should create an Organization admin", async () => {
const admin = {
name: "Tarteel",
email: "tamimitarteel@gmail.com",
password: "Tarteel123>>",
organizationId: "60eb3e1b-e7b0-4186-9189-9e860c3164dd"
};

const response = await createOrganizationAdmin(admin);

expect(response.name).toBe("Tarteel");
});
});

describe("Organization profile", () => {
it("should delete an Organization profile", async () => {
const orgId = "cdcc9407-aa39-4b88-99b8-7ae06378eedf"

const response = await deleteOrganizationProfile(orgId);

expect(response).toEqual({"affected": 0, "raw": []});
});
});
50 changes: 29 additions & 21 deletions app.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,56 @@
import "./config.js"
import swaggerUi from 'swagger-ui-express';
import express from 'express'
import dotenv from 'dotenv'
import createError from 'http-errors'
import dataSource from './src/db/dataSource.js'
import { initDB } from './src/db/dataSource.js'
import logger from 'morgan'
import cookieParser from 'cookie-parser'
import fileUpload from 'express-fileupload';

import indexRouter from "./src/routes/index.js"
import permissionRouter from "./src/routes/permission.js"
import roleRouter from "./src/routes/role.js"
import voluntaryWorkRouter from "./src/routes/voluntaryWork.js"
import organizationAdminRouter from "./src/routes/organizationAdmin.js"
import organizationProfileRouter from "./src/routes/organizationProfile.js"
import volunteerRouter from "./src/routes/volunteer.js"
import { authenticate } from "./src/middleware/auth/authenticate.js"
import { errorHandler } from "./src/middleware/errorHandler/errorHandler.js"
import { swaggerSpec } from "./swaggerConfig.js";

const app = express();
dotenv.config();
const PORT = process.env.PORT || 3000;

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(fileUpload({ limits: { fileSize: 50 * 1024 * 1024 } }))
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
app.get("/health", function (req, res) {
res.sendStatus(200);
})

app.use('/', indexRouter);
// app.use('/users', usersRouter);
app.use('/permission', authenticate, permissionRouter);
app.use('/role', authenticate, roleRouter);
app.use('/voluntaryWork', authenticate, voluntaryWorkRouter);
app.use('/organizationAdmin', organizationAdminRouter);
app.use('/organizationProfile', authenticate, organizationProfileRouter);
app.use("/volunteer", volunteerRouter);

// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
next(createError(404, "The page"));
});


// error handler
app.use(function (err: any, req: any, res: any, next: any) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};

// render the error page
res.status(err.status || 500).send({ error: err.message });
});

dataSource.initialize().then(() => {
console.log("Connected to DB!");
}).catch(err => {
console.error('Failed to connect to DB: ' + err);
});
app.use(errorHandler);

app.listen(PORT, () => {
logger(`App is listening on port ${PORT}`);
console.log(`App is listening on port ${PORT} and host http://localhost:${PORT}`);
console.log(`App is listening on port ${PORT}`);
initDB();
});


export default app;
1 change: 1 addition & 0 deletions babel.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = { presets: ["@babel/preset-env"] };
Loading

0 comments on commit aabe240

Please sign in to comment.