Skip to content

Commit

Permalink
Merge branch 'dev' into feat/9-Help_Center_Update_Topic
Browse files Browse the repository at this point in the history
  • Loading branch information
CollinDex authored Jul 22, 2024
2 parents ec890d2 + 199db35 commit ad6c68c
Show file tree
Hide file tree
Showing 30 changed files with 577 additions and 310 deletions.
10 changes: 8 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
port=8000
PORT=8000
AUTH_SECRET=
DB_USER=
DB_HOST=
DB_PASSWORD=
DB_NAME=
DB_NAME=
NODE_ENV=development
SMTP_USER=
SMTP_PASSWORD=
SMTP_HOST=
SMTP_SERVICE=

19 changes: 8 additions & 11 deletions .github/workflows/prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Build, Test, and Deploy for Prod Branch

on:
push:
branch:
branches:
- main

jobs:
Expand All @@ -13,25 +13,22 @@ jobs:
working-directory: /var/www/aihomework/prod

steps:
- name: Pull from github
id: pull
- name: Pull from GitHub
run: |
git pull origin prod
git fetch origin
git reset --hard origin/main
- name: install dependencies
- name: Install dependencies
run: yarn install

- name: buld the dist
- name: Build the dist
run: yarn build

- name: setup service file
- name: Setup service file
run: sudo cp server-script/aihomeworkprod.service /etc/systemd/system

- name: start the app
- name: Start the app
run: |
sudo systemctl daemon-reload
sudo systemctl restart aihomeworkprod
# test:
# -name: Run test
# run: yarn jest
11 changes: 11 additions & 0 deletions db/migrations/1721611425287-migration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { MigrationInterface, QueryRunner } from "typeorm";

export class Migration1721611425287 implements MigrationInterface {

public async up(queryRunner: QueryRunner): Promise<void> {
}

public async down(queryRunner: QueryRunner): Promise<void> {
}

}
11 changes: 7 additions & 4 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ const config: Config = {
verbose: true,
preset: "ts-jest",
testEnvironment: "node",
globals: {
"ts-jest": {
tsconfig: "tsconfig.jest.json",
},
transform: {
"^.+\\.tsx?$": [
"ts-jest",
{
tsconfig: "tsconfig.jest.json",
},
],
},
};

Expand Down
17 changes: 14 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,29 @@
"test": "jest ",
"typeorm": "typeorm-ts-node-commonjs",
"build": "tsc",
"prod": "node dist/index.js"
"prod": "node dist/index.js",
"migrate": "typeorm-ts-node-commonjs migration:run -d src/data-source",
"migration:create": "typeorm-ts-node-commonjs migration:create db/migrations/migration",
"migration:generate": "typeorm-ts-node-commonjs migration:generate db/migrations/migration -d src/data-source",
"migration:revert": "typeorm-ts-node-commonjs migration:revert -d src/data-source"
},
"repository": {
"type": "git",
"url": "https://github.com/hngprojects/hng_boilerplate_expressjs"
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/hngprojects/hng_boilerplate_expressjs/issues"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/jest": "^29.5.12",
"@types/node": "^16.18.103",
"@types/supertest": "^6.0.2",
"@types/swagger-jsdoc": "^6.0.4",
"@types/swagger-ui-express": "^4.1.6",
"ts-node": "^10.9.1",
"ts-node": "^10.9.2",
"typescript": "^5.5.3"
},
"dependencies": {
Expand Down Expand Up @@ -51,6 +61,7 @@
"swagger-ui-express": "^5.0.1",
"ts-jest": "^29.2.3",
"ts-node-dev": "^2.0.0",
"twilio": "^5.2.2",
"typeorm": "^0.3.20"
}
}
5 changes: 5 additions & 0 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ const config = {
SMTP_PASSWORD: process.env.SMTP_PASSWORD,
SMTP_HOST: process.env.SMTP_HOST,
SMTP_SERVICE: process.env.SMTP_SERVICE,
NODE_ENV: process.env.NODE_ENV,
TWILIO_SID: process.env.TWILIO_SID,
TWILIO_AUTH_TOKEN: process.env.TWILIO_AUTH_TOKEN,
TWILIO_PHONE_NUMBER: process.env.TWILIO_PHONE_NUMBER,

};

export default config;
96 changes: 96 additions & 0 deletions src/controllers/NotificationController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { NotificationSetting } from "../models/notification";
import { Request, Response } from "express";

// TO validate all required fields in post /api/notification-settings
interface NotificationSettings {
user_id: number;
email_notifications: boolean;
push_notifications: boolean;
sms_notifications: boolean;
}

const requiredFields: (keyof NotificationSettings)[] = [
"user_id",
"email_notifications",
"push_notifications",
"sms_notifications",
];
const validateFields = (body: Partial<NotificationSettings>) => {
const missingFields = requiredFields.filter(
(field) => body[field] === undefined
);

if (missingFields.length > 0) {
return {
valid: false,
message: `Missing required fields: ${missingFields.join(", ")}`,
};
}

return { valid: true };
};

// Create notification setting for a user
const CreateNotification = async (req: Request, res: Response) => {
try {
const validation = validateFields(req.body);

if (!validation.valid) {
return res
.status(400)
.json({ status: "error", code: 400, message: validation.message });
}
const { user_id } = req.body;

// Check if a notification setting already exists for this user_id
const existingSetting = await NotificationSetting.findOne({
where: { user_id },
});

const newSetting = NotificationSetting.create(req.body);
const result = await NotificationSetting.save(newSetting);
res.status(200).json({ status: "success", code: 200, data: result });

if (existingSetting) {
return res
.status(409)
.json({
status: "error",
code: 409,
message: "Notification settings for this user already exist.",
});
}
} catch (error) {
console.log(error);
res
.status(500)
.json({
status: "error",
code: 500,
message: "Error creating user notification",
});
}
};

// Get notification setting
const GetNotification = async (req: Request, res: Response) => {
try {
const settings = await NotificationSetting.findOne({
where: { user_id: String(req.params.user_id) },
});
if (settings === null) {
return res
.status(404)
.json({
status: "Not found",
message: "The user with the requested id cannot be found",
});
}
res.status(200).json({ status: "success", code: 200, data: settings });
} catch (error) {
res.status(500).json({ status: "error", code: 500, message: error.message });
}
};


export { CreateNotification, GetNotification };
34 changes: 34 additions & 0 deletions src/controllers/OrgController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Request, Response } from "express";
import { OrgService } from "../services/OrgService";

export class OrgController {
private orgService: OrgService;
constructor() {
this.orgService = new OrgService();
}

async removeUser(req: Request, res: Response) {
try {
const user = await this.orgService.removeUser(
req.params.org_id,
req.params.user_id,
);
if (!user) {
return res.status(404).json({
status: "forbidden",
message: "User not found in the organization",
status_code: 404,
});
}
res.status(200).json({
status: "success",
message: "User deleted succesfully",
status_code: 200,
});
} catch (error) {
res
.status(400)
.json({ message: "Failed to remove user from organization" });
}
}
}
46 changes: 46 additions & 0 deletions src/controllers/SmsController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Request, Response } from "express";
import SmsService from "../services/sms.services";
import AppDataSource from "../data-source";
import { User } from "../models";

export const sendSms = async (req: Request, res: Response): Promise<void> => {
const { phone_number, message } = req.body;
const sender_id = req.user.id;

if (!phone_number || !message || !sender_id) {
res.status(400).json({
status: "unsuccessful",
status_code: 400,
message:
"Valid phone number, message content, and sender ID must be provided.",
});
return;
}

try {
const userRepository = AppDataSource.getRepository(User);
const sender = await userRepository.findOneBy({ id: sender_id });

if (!sender) {
res.status(404).json({
status: "unsuccessful",
status_code: 404,
message: "Sender not found.",
});
return;
}

await SmsService.sendSms(sender, phone_number, message);
res.status(200).json({
status: "success",
status_code: 200,
message: "SMS sent successfully.",
});
} catch (error) {
res.status(500).json({
status: "unsuccessful",
status_code: 500,
message: "Failed to send SMS. Please try again later.",
});
}
};
41 changes: 40 additions & 1 deletion src/controllers/TestimonialsController.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Request, Response } from "express";
import { AppDataSource } from "../data-source";
import AppDataSource from "../data-source";
import { Testimonial } from "../models/Testimonial";

export default class TestimonialsController {
Expand Down Expand Up @@ -133,4 +133,43 @@ export default class TestimonialsController {
res.status(500).send({ message: error.message });
}
}

// CODE BY TOMILLA OLUWAFEMI
public async getAllTestimonials(req: Request, res: Response) {
try {
const testimonials = await AppDataSource.getRepository(Testimonial).find();
res.status(200).json({
message: "Testimonials retrieved successfully",
status_code: 200,
data: testimonials,
});
} catch (error) {
res.status(500).send({ message: error.message });
}
}

public async deleteTestimonial(req: Request, res: Response) {
try {
const { testimonial_id } = req.params;

const testimonialToDelete = await AppDataSource.getRepository(Testimonial).findOne({
where: { id: testimonial_id },
});

if (!testimonialToDelete) {
return res
.status(404)
.send({ message: "Testimonial not found", status_code: 404 });
}

await AppDataSource.getRepository(Testimonial).remove(testimonialToDelete);

res.status(200).json({
message: "Testimonial deleted successfully",
status_code: 200,
});
} catch (error) {
res.status(500).send({ message: error.message });
}
}
}
3 changes: 2 additions & 1 deletion src/controllers/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// silence is golden
export * from "./AuthController";
export * from "./UserController";
export * from "./HelpController";
export * from "./HelpController";
export * from "./NotificationController";
Loading

0 comments on commit ad6c68c

Please sign in to comment.