Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update mentee application status with revoke status #148

Merged
merged 3 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ jobs:
echo "DB_PORT=5432" >> .env
echo "SERVER_PORT=4000" >> .env
echo "JWT_SECRET=your_jwt_secret_key" >> .env
echo "GOOGLE_CLIENT_ID=your_google_client_id" >> .env
echo "GOOGLE_CLIENT_SECRET=your_google_client_secret" >> .env
echo "GOOGLE_REDIRECT_URL=http://localhost:${SERVER_PORT}/api/auth/google/callback" >> .env
echo "CLIENT_URL=http://localhost:5173" >> .env
echo "IMG_HOST=http://localhost:${SERVER_PORT}" >> .env
echo "SMTP_MAIL=your_smtp_mail" >> .env
echo "SMTP_PASSWORD=your_smtp_password" >> .env
echo "LINKEDIN_CLIENT_ID=your_linkedin_client_id" >> .env
echo "LINKEDIN_CLIENT_SECRET=your_linkedin_client_secret" >> .env
echo "LINKEDIN_REDIRECT_URL=http://localhost:${SERVER_PORT}/api/auth/linkedin/callback" >> .env

- name: Run tests
run: npm run test
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ node_modules/
dist/
.idea
uploads/
certificates/
6 changes: 6 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ import emailRouter from './routes/emails/emails.route'
import menteeRouter from './routes/mentee/mentee.route'
import mentorRouter from './routes/mentor/mentor.route'
import profileRouter from './routes/profile/profile.route'
import path from 'path'

const app = express()
const staticFolder = 'uploads'
export const certificatesDir = path.join(__dirname, 'certificates')

app.use(cookieParser())
app.use(bodyParser.json())
Expand Down Expand Up @@ -51,6 +53,10 @@ if (!fs.existsSync(staticFolder)) {
console.log('Directory already exists.')
}

if (!fs.existsSync(certificatesDir)) {
fs.mkdirSync(certificatesDir)
}

export const startServer = async (port: number): Promise<Express> => {
try {
await dataSource.initialize()
Expand Down
22 changes: 12 additions & 10 deletions src/controllers/admin/mentee.controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import type { Request, Response } from 'express'
import { ApplicationStatus, ProfileTypes, StatusUpdatedBy } from '../../enums'
import {
MenteeApplicationStatus,
ProfileTypes,
StatusUpdatedBy
} from '../../enums'
import type Profile from '../../entities/profile.entity'
import type Mentee from '../../entities/mentee.entity'
import type { ApiResponse } from '../../types'
Expand All @@ -16,15 +20,15 @@ export const getMentees = async (
): Promise<ApiResponse<Mentee[]>> => {
try {
const user = req.user as Profile
const status: ApplicationStatus | undefined = req.query.status as
| ApplicationStatus
const status: MenteeApplicationStatus | undefined = req.query.status as
| MenteeApplicationStatus
| undefined

if (user.type !== ProfileTypes.ADMIN) {
return res.status(403).json({ message: 'Only Admins are allowed' })
}

if (status && !(status.toUpperCase() in ApplicationStatus)) {
if (status && !(status.toUpperCase() in MenteeApplicationStatus)) {
return res.status(400).json({ message: 'Please provide a valid status' })
}

Expand Down Expand Up @@ -101,12 +105,10 @@ export const getAllMenteeEmails = async (
res: Response
): Promise<ApiResponse<string[]>> => {
try {
const status = req.query.status
if (
status === ApplicationStatus.APPROVED ||
status === ApplicationStatus.REJECTED ||
status === ApplicationStatus.PENDING
) {
const status: MenteeApplicationStatus | undefined = req.query.status as
| MenteeApplicationStatus
| undefined
if (status && status.toUpperCase() in MenteeApplicationStatus) {
const { emails, statusCode, message } = await getAllMenteeEmailsService(
status
)
Expand Down
16 changes: 8 additions & 8 deletions src/controllers/admin/mentor.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
updateMentorStatus,
getMentor
} from '../../services/admin/mentor.service'
import { ApplicationStatus, ProfileTypes } from '../../enums'
import { MentorApplicationStatus, ProfileTypes } from '../../enums'
import type Profile from '../../entities/profile.entity'
import type Mentor from '../../entities/mentor.entity'
import type { ApiResponse } from '../../types'
Expand All @@ -27,7 +27,7 @@ export const mentorStatusHandler = async (
return res.status(403).json({ message: 'Only Admins are allowed' })
}

if (!(state.toUpperCase() in ApplicationStatus)) {
if (!(state.toUpperCase() in MentorApplicationStatus)) {
return res.status(400).json({ message: 'Please provide a valid status' })
}

Expand All @@ -54,15 +54,15 @@ export const getAllMentorsByStatus = async (
): Promise<ApiResponse<Mentor>> => {
try {
const user = req.user as Profile
const status: ApplicationStatus | undefined = req.query.status as
| ApplicationStatus
const status: MentorApplicationStatus | undefined = req.query.status as
| MentorApplicationStatus
| undefined

if (user.type !== ProfileTypes.ADMIN) {
return res.status(403).json({ message: 'Only Admins are allowed' })
}

if (status && !(status.toUpperCase() in ApplicationStatus)) {
if (status && !(status.toUpperCase() in MentorApplicationStatus)) {
return res.status(400).json({ message: 'Please provide a valid status' })
}

Expand All @@ -86,15 +86,15 @@ export const getAllMentorEmails = async (
): Promise<ApiResponse<string[]>> => {
try {
const user = req.user as Profile
const status: ApplicationStatus | undefined = req.query.status as
| ApplicationStatus
const status: MentorApplicationStatus | undefined = req.query.status as
| MentorApplicationStatus
| undefined

if (user.type !== ProfileTypes.ADMIN) {
return res.status(403).json({ message: 'Only Admins are allowed' })
}

if (status && !(status.toUpperCase() in ApplicationStatus)) {
if (status && !(status.toUpperCase() in MentorApplicationStatus)) {
return res.status(400).json({ message: 'Please provide a valid status' })
}

Expand Down
4 changes: 2 additions & 2 deletions src/controllers/mentee.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type ApiResponse } from '../types'
import type Mentee from '../entities/mentee.entity'
import type Profile from '../entities/profile.entity'
import { getMentee, updateStatus } from '../services/admin/mentee.service'
import { ApplicationStatus, StatusUpdatedBy } from '../enums'
import { MentorApplicationStatus, StatusUpdatedBy } from '../enums'
import { addMentee } from '../services/mentee.service'

export const menteeApplicationHandler = async (
Expand Down Expand Up @@ -42,7 +42,7 @@ export const updateMenteeStatus = async (

if (
!user.mentor?.filter(
(mentor) => mentor.state === ApplicationStatus.APPROVED
(mentor) => mentor.state === MentorApplicationStatus.APPROVED
)
) {
return res.status(403).json({ message: 'Only mentors are allowed' })
Expand Down
8 changes: 4 additions & 4 deletions src/controllers/mentor.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type Profile from '../entities/profile.entity'
import type Mentor from '../entities/mentor.entity'
import type { ApiResponse } from '../types'
import type Mentee from '../entities/mentee.entity'
import { ApplicationStatus } from '../enums'
import { MenteeApplicationStatus } from '../enums'
import { getAllMenteesByMentor } from '../services/admin/mentee.service'

export const mentorApplicationHandler = async (
Expand Down Expand Up @@ -117,11 +117,11 @@ export const getMenteesByMentor = async (
): Promise<ApiResponse<Mentee[]>> => {
try {
const user = req.user as Profile
const status: ApplicationStatus | undefined = req.query.status as
| ApplicationStatus
const status: MenteeApplicationStatus | undefined = req.query.status as
| MenteeApplicationStatus
| undefined

if (status && !(status.toUpperCase() in ApplicationStatus)) {
if (status && !(status.toUpperCase() in MenteeApplicationStatus)) {
return res.status(400).json({ message: 'Please provide a valid status' })
}

Expand Down
12 changes: 6 additions & 6 deletions src/entities/mentee.entity.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { Column, Entity, ManyToOne } from 'typeorm'
import Mentor from './mentor.entity'
import profileEntity from './profile.entity'
import { ApplicationStatus, StatusUpdatedBy } from '../enums'
import { MenteeApplicationStatus, StatusUpdatedBy } from '../enums'
import BaseEntity from './baseEntity'
import { UUID } from 'typeorm/driver/mongodb/bson.typings'

@Entity('mentee')
class Mentee extends BaseEntity {
@Column({
type: 'enum',
enum: ApplicationStatus,
default: ApplicationStatus.PENDING
enum: MenteeApplicationStatus,
default: MenteeApplicationStatus.PENDING
})
state: ApplicationStatus
state: MenteeApplicationStatus

@Column({ type: 'enum', enum: StatusUpdatedBy, nullable: true })
status_updated_by!: StatusUpdatedBy
Expand All @@ -36,13 +36,13 @@ class Mentee extends BaseEntity {
mentor: Mentor

constructor(
state: ApplicationStatus,
state: MenteeApplicationStatus,
application: Record<string, unknown>,
profile: profileEntity,
mentor: Mentor
) {
super()
this.state = state || ApplicationStatus.PENDING
this.state = state || MenteeApplicationStatus.PENDING
this.application = application
this.profile = profile
this.mentor = mentor
Expand Down
10 changes: 5 additions & 5 deletions src/entities/mentor.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from 'typeorm'
import Profile from './profile.entity'
import Mentee from './mentee.entity'
import Category from './category.entity'
import { ApplicationStatus } from '../enums'
import { MentorApplicationStatus } from '../enums'
import BaseEntity from './baseEntity'

@Entity('mentor')
class Mentor extends BaseEntity {
@Column({
type: 'enum',
enum: ApplicationStatus,
default: ApplicationStatus.PENDING
enum: MentorApplicationStatus,
default: MentorApplicationStatus.PENDING
})
state: ApplicationStatus
state: MentorApplicationStatus

@ManyToOne(() => Category, (category) => category.mentors)
@JoinColumn()
Expand All @@ -32,7 +32,7 @@ class Mentor extends BaseEntity {
mentees?: Mentee[]

constructor(
state: ApplicationStatus,
state: MentorApplicationStatus,
category: Category,
application: Record<string, unknown>,
availability: boolean,
Expand Down
11 changes: 9 additions & 2 deletions src/enums/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,18 @@ export enum EmailStatusTypes {
FAILED = 'failed'
}

export enum ApplicationStatus {
export enum MentorApplicationStatus {
PENDING = 'pending',
REJECTED = 'rejected',
APPROVED = 'approved'
}

export enum MenteeApplicationStatus {
PENDING = 'pending',
REJECTED = 'rejected',
APPROVED = 'approved',
COMPLETED = 'completed'
COMPLETED = 'completed',
REVOKED = 'revoked'
}

export enum StatusUpdatedBy {
Expand Down
49 changes: 49 additions & 0 deletions src/migrations/1722749907154-AddNewApplicationStates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { type MigrationInterface, type QueryRunner } from 'typeorm'

export class AddNewApplicationStates1722749907154
implements MigrationInterface
{
name = 'AddNewApplicationStates1722749907154'

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TYPE "public"."mentee_state_enum" RENAME TO "mentee_state_enum_old"`
)
await queryRunner.query(
`CREATE TYPE "public"."mentee_state_enum" AS ENUM('pending', 'rejected', 'approved', 'completed', 'revoked')`
)
await queryRunner.query(
`ALTER TABLE "mentee" ALTER COLUMN "state" DROP DEFAULT`
)
await queryRunner.query(
`ALTER TABLE "mentee" ALTER COLUMN "state" TYPE "public"."mentee_state_enum" USING "state"::"text"::"public"."mentee_state_enum"`
)
await queryRunner.query(
`ALTER TABLE "mentee" ALTER COLUMN "state" SET DEFAULT 'pending'`
)
await queryRunner.query(`DROP TYPE "public"."mentee_state_enum_old"`)
await queryRunner.query(`ALTER TABLE "mentee" DROP COLUMN "certificate_id"`)
await queryRunner.query(`ALTER TABLE "mentee" ADD "certificate_id" uuid`)
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "mentee" DROP COLUMN "certificate_id"`)
await queryRunner.query(`ALTER TABLE "mentee" ADD "certificate_id" bigint`)
await queryRunner.query(
`CREATE TYPE "public"."mentee_state_enum_old" AS ENUM('pending', 'rejected', 'approved')`
)
await queryRunner.query(
`ALTER TABLE "mentee" ALTER COLUMN "state" DROP DEFAULT`
)
await queryRunner.query(
`ALTER TABLE "mentee" ALTER COLUMN "state" TYPE "public"."mentee_state_enum_old" USING "state"::"text"::"public"."mentee_state_enum_old"`
)
await queryRunner.query(
`ALTER TABLE "mentee" ALTER COLUMN "state" SET DEFAULT 'pending'`
)
await queryRunner.query(`DROP TYPE "public"."mentee_state_enum"`)
await queryRunner.query(
`ALTER TYPE "public"."mentee_state_enum_old" RENAME TO "mentee_state_enum"`
)
}
}
10 changes: 7 additions & 3 deletions src/scripts/seed-db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import Email from '../entities/email.entity'
import Mentee from '../entities/mentee.entity'
import Mentor from '../entities/mentor.entity'
import Profile from '../entities/profile.entity'
import { ApplicationStatus, EmailStatusTypes, ProfileTypes } from '../enums'
import {
EmailStatusTypes,
MenteeApplicationStatus,
ProfileTypes
} from '../enums'

export const seedDatabaseService = async (): Promise<string> => {
try {
Expand Down Expand Up @@ -74,7 +78,7 @@ export const seedDatabaseService = async (): Promise<string> => {
const mentor =
mentors[faker.number.int({ min: 0, max: mentors.length - 1 })]
return new Mentee(
faker.helpers.enumValue(ApplicationStatus),
faker.helpers.enumValue(MenteeApplicationStatus),
{
firstName: faker.person.firstName(),
lastName: faker.person.lastName(),
Expand Down Expand Up @@ -125,7 +129,7 @@ const createRandomProfile = (): Partial<Profile> => {

const createMentor = (category: Category, profile: Profile): Mentor => {
return {
state: faker.helpers.enumValue(ApplicationStatus),
state: faker.helpers.enumValue(MenteeApplicationStatus),
category,
application: {
firstName: faker.person.firstName(),
Expand Down
Loading
Loading