Skip to content

Commit

Permalink
Merge branch 'sef-global:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
mayura-andrew authored Jun 1, 2024
2 parents c47b9e1 + a859f04 commit c156b39
Show file tree
Hide file tree
Showing 23 changed files with 786 additions and 250 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ GOOGLE_CLIENT_SECRET='your_google_client_secret'
GOOGLE_REDIRECT_URL=http://localhost:${SERVER_PORT}/api/auth/google/callback
CLIENT_URL=http://localhost:5173
IMG_HOST=http://localhost:${SERVER_PORT}
SMTP_MAIL=your_smtp_mail
SMTP_PASSWORD=your_smtp_password
41 changes: 31 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"ejs": "^3.1.10",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.2",
"multer": "^1.4.5-lts.1",
"nodemailer": "^6.9.13",
"passport": "^0.6.0",
"passport-google-oauth20": "^2.0.0",
"passport-jwt": "^4.0.1",
Expand All @@ -36,11 +38,13 @@
"@types/body-parser": "^1.19.2",
"@types/cookie-parser": "^1.4.3",
"@types/cors": "^2.8.13",
"@types/ejs": "^3.1.5",
"@types/express": "^4.17.17",
"@types/jest": "^29.5.3",
"@types/jsonwebtoken": "^9.0.2",
"@types/multer": "^1.4.11",
"@types/node": "^20.1.4",
"@types/nodemailer": "^6.4.15",
"@types/passport": "^1.0.12",
"@types/passport-google-oauth20": "^2.0.14",
"@types/passport-jwt": "^3.0.9",
Expand Down
2 changes: 2 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { CLIENT_URL } from './configs/envConfig'
import cookieParser from 'cookie-parser'
import menteeRouter from './routes/mentee/mentee.route'
import fs from 'fs'
import emailRouter from './routes/emails/emails.route'

const app = express()
const staticFolder = 'uploads'
Expand All @@ -39,6 +40,7 @@ app.use('/api/admin', adminRouter)
app.use('/api/mentors', mentorRouter)
app.use('/api/mentees', menteeRouter)
app.use('/api/categories', categoryRouter)
app.use('/api/emails', emailRouter)

if (!fs.existsSync(staticFolder)) {
fs.mkdirSync(staticFolder, { recursive: true })
Expand Down
2 changes: 2 additions & 0 deletions src/configs/envConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ export const GOOGLE_CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET ?? ''
export const GOOGLE_REDIRECT_URL = process.env.GOOGLE_REDIRECT_URL ?? ''
export const CLIENT_URL = process.env.CLIENT_URL ?? ''
export const IMG_HOST = process.env.IMG_HOST ?? ''
export const SMTP_MAIL = process.env.SMTP_MAIL ?? ''
export const SMTP_PASS = process.env.SMTP_PASS ?? ''
44 changes: 24 additions & 20 deletions src/controllers/admin/email.controller.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
import type { Request, Response } from 'express'
import type { ApiResponse } from '../../types'
import { getAllMenteeEmailsService } from '../../services/admin/email.service'
import { ApplicationStatus } from '../../enums'
import { type Request, type Response } from 'express'
import type Profile from '../../entities/profile.entity'
import { type ApiResponse } from '../../types'
import type Email from '../../entities/email.entity'
import { ProfileTypes } from '../../enums'
import { sendEmail } from '../../services/admin/email.service'

export const getAllMenteeEmails = async (
export const sendEmailController = async (
req: Request,
res: Response
): Promise<ApiResponse<string[]>> => {
): Promise<ApiResponse<Email>> => {
const { to, subject, text } = req.body

try {
const status = req.query.status
if (
status === ApplicationStatus.APPROVED ||
status === ApplicationStatus.REJECTED ||
status === ApplicationStatus.PENDING
) {
const { emails, statusCode, message } = await getAllMenteeEmailsService(
status
)
return res.status(statusCode).json({ emails, message })
} else {
return res.status(400).json({ message: 'Invalid Status' })
const user = req.user as Profile

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

const { statusCode, message } = await sendEmail(to, subject, text)
return res.status(statusCode).json({ message })
} catch (err) {
console.error(err)
return res.status(500).json({ error: err || 'Internal Server Error' })
if (err instanceof Error) {
console.error('Error executing query', err)
return res
.status(500)
.json({ error: 'Internal server error', message: err.message })
}
throw err
}
}
25 changes: 25 additions & 0 deletions src/controllers/admin/mentee.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type Profile from '../../entities/profile.entity'
import type Mentee from '../../entities/mentee.entity'
import type { ApiResponse } from '../../types'
import {
getAllMenteeEmailsService,
getAllMentees,
getMentee,
updateStatus
Expand Down Expand Up @@ -90,3 +91,27 @@ export const getMenteeDetails = async (
throw err
}
}

export const getAllMenteeEmails = async (
req: Request,
res: Response
): Promise<ApiResponse<string[]>> => {
try {
const status = req.query.status
if (
status === ApplicationStatus.APPROVED ||
status === ApplicationStatus.REJECTED ||
status === ApplicationStatus.PENDING
) {
const { emails, statusCode, message } = await getAllMenteeEmailsService(
status
)
return res.status(statusCode).json({ emails, message })
} else {
return res.status(400).json({ message: 'Invalid Status' })
}
} catch (err) {
console.error(err)
return res.status(500).json({ error: err || 'Internal Server Error' })
}
}
9 changes: 8 additions & 1 deletion src/controllers/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ export const register = async (
first_name,
last_name
)

const { user } = await loginUser(email, password)

if (user?.uuid) {
signAndSetCookie(res, user.uuid)
}

return res.status(statusCode).json({ message, profile })
} catch (err) {
if (err instanceof Error) {
Expand Down Expand Up @@ -130,7 +137,7 @@ export const requireAuth = (
const token = req.cookies.jwt

if (!token) {
return res.status(401).json({ error: 'No token provided' })
return res.status(401).json({ error: 'Use is not authenticated' })
}

try {
Expand Down
23 changes: 22 additions & 1 deletion src/controllers/mentee.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import type { Request, Response } from 'express'
import { type ApiResponse } from '../types'
import type Mentee from '../entities/mentee.entity'
import type Profile from '../entities/profile.entity'
import { addMentee, updateStatus } from '../services/admin/mentee.service'
import { getMentee, updateStatus } from '../services/admin/mentee.service'
import { ApplicationStatus } from '../enums'
import { addMentee } from '../services/mentee.service'

export const menteeApplicationHandler = async (
req: Request,
Expand Down Expand Up @@ -59,3 +60,23 @@ export const updateMenteeStatus = async (
throw err
}
}

export const getMenteeDetails = async (
req: Request,
res: Response
): Promise<ApiResponse<Mentee>> => {
try {
const { menteeId } = req.params

const { statusCode, message, mentee } = await getMentee(menteeId)
return res.status(statusCode).json({ mentee, message })
} catch (err) {
if (err instanceof Error) {
console.error('Error executing query', err)
return res
.status(500)
.json({ error: 'Internal server error', message: err.message })
}
throw err
}
}
2 changes: 1 addition & 1 deletion src/entities/email.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Email extends BaseEntity {
@Column({ type: 'varchar', length: 255 })
subject: string

@Column({ type: 'varchar', length: 655 })
@Column('varchar')
content: string

@Column({ type: 'enum', enum: EmailStatusTypes })
Expand Down
4 changes: 2 additions & 2 deletions src/entities/mentee.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class Mentee extends BaseEntity {
state: ApplicationStatus

@Column({ type: 'json' })
application: JSON
application: Record<string, unknown>

@Column({ type: 'bigint', nullable: true, default: null })
certificate_id!: bigint
Expand All @@ -31,7 +31,7 @@ class Mentee extends BaseEntity {

constructor(
state: ApplicationStatus,
application: JSON,
application: Record<string, unknown>,
profile: profileEntity,
mentor: Mentor
) {
Expand Down
2 changes: 1 addition & 1 deletion src/routes/admin/mentee/mentee.route.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import express from 'express'
import { requireAuth } from '../../../controllers/auth.controller'
import { getAllMenteeEmails } from '../../../controllers/admin/email.controller'
import {
getMentees,
updateMenteeStatus,
getAllMenteeEmails,
getMenteeDetails
} from '../../../controllers/admin/mentee.controller'

Expand Down
9 changes: 9 additions & 0 deletions src/routes/emails/emails.route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import express from 'express'
import { sendEmailController } from '../../controllers/admin/email.controller'
import { requireAuth } from '../../controllers/auth.controller'

const emailRouter = express.Router()

emailRouter.post('/send', requireAuth, sendEmailController)

export default emailRouter
4 changes: 3 additions & 1 deletion src/routes/mentee/mentee.route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import express from 'express'
import { requireAuth } from '../../controllers/auth.controller'
import {
menteeApplicationHandler,
updateMenteeStatus
updateMenteeStatus,
getMenteeDetails
} from '../../controllers/mentee.controller'

const menteeRouter = express.Router()

menteeRouter.post('/', requireAuth, menteeApplicationHandler)
menteeRouter.get('/:menteeId', getMenteeDetails)
menteeRouter.put('/:menteeId/status/', requireAuth, updateMenteeStatus)

export default menteeRouter
Loading

0 comments on commit c156b39

Please sign in to comment.