diff --git a/package.json b/package.json index 2719f795e..a67f46afa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iSunFA", - "version": "0.8.0+20", + "version": "0.8.0+22", "private": false, "scripts": { "dev": "next dev", diff --git a/prisma/seed_json/employee_project.json b/prisma/seed_json/employee_project.json index 8b05bcdb2..a072e6da9 100644 --- a/prisma/seed_json/employee_project.json +++ b/prisma/seed_json/employee_project.json @@ -13,7 +13,7 @@ "employeeId": 1001, "projectId": 1000, "startDate": 1635724800, - "endDate": 1635811200, + "endDate": null, "createdAt": 1635724800, "updatedAt": 1635724800 } diff --git a/prisma/seed_json/milestone.json b/prisma/seed_json/milestone.json index 2966d86ba..49cdddb4a 100644 --- a/prisma/seed_json/milestone.json +++ b/prisma/seed_json/milestone.json @@ -1,6 +1,6 @@ [ { - "id":1015, + "id": 1015, "projectId": 1001, "startDate": 1709578219, "endDate": 1712256619, @@ -81,7 +81,7 @@ "updatedAt": 1717637165 }, { - "id":1014, + "id": 1014, "projectId": 1007, "startDate": 1717637165, "endDate": 1718179676, @@ -142,5 +142,59 @@ "status": "Archived", "createdAt": 1709578219, "updatedAt": 1709578219 + }, + { + "id": 1016, + "projectId": 1009, + "startDate": 0, + "endDate": 0, + "status": "Designing", + "createdAt": 1709578219, + "updatedAt": 1709578219 + }, + { + "id": 1017, + "projectId": 1009, + "startDate": 0, + "endDate": 0, + "status": "Beta Testing", + "createdAt": 1709578219, + "updatedAt": 1709578219 + }, + { + "id": 1018, + "projectId": 1009, + "startDate": 0, + "endDate": 0, + "status": "Develop", + "createdAt": 1709578219, + "updatedAt": 1709578219 + }, + { + "id": 1019, + "projectId": 1009, + "startDate": 0, + "endDate": 0, + "status": "Selling", + "createdAt": 1709578219, + "updatedAt": 1709578219 + }, + { + "id": 1020, + "projectId": 1009, + "startDate": 0, + "endDate": 0, + "status": "Sold", + "createdAt": 1709578219, + "updatedAt": 1709578219 + }, + { + "id": 1021, + "projectId": 1009, + "startDate": 0, + "endDate": 0, + "status": "Archived", + "createdAt": 1709578219, + "updatedAt": 1709578219 } -] \ No newline at end of file +] diff --git a/prisma/seed_json/project.json b/prisma/seed_json/project.json index 6aba557b1..e504038fa 100644 --- a/prisma/seed_json/project.json +++ b/prisma/seed_json/project.json @@ -97,5 +97,16 @@ "createdAt": 1651368365, "updatedAt": 1651368365, "deletedAt": null + }, + { + "id": 1009, + "companyId": 1000, + "name": "Test update Project", + "completedPercent": 83, + "stage": "Beta Testing", + "imageId": "TP", + "createdAt": 1651368365, + "updatedAt": 1651368365, + "deletedAt": null } ] diff --git a/src/lib/utils/repo/authentication.repo.ts b/src/lib/utils/repo/authentication.repo.ts index d35feffdf..493e9c112 100644 --- a/src/lib/utils/repo/authentication.repo.ts +++ b/src/lib/utils/repo/authentication.repo.ts @@ -4,8 +4,8 @@ import { timestampInSeconds } from '@/lib/utils/common'; export async function getUserByCredential( credentialId: string -): Promise<(Authentication & { user: User }) | null> { - let user: (Authentication & { user: User }) | null = null; +): Promise<(Authentication & { user: User & { userAgreements: UserAgreement[] } }) | null> { + let user: (Authentication & { user: User & { userAgreements: UserAgreement[] } }) | null = null; if (credentialId.trim() !== '') { user = await prisma.authentication.findUnique({ where: { @@ -13,7 +13,11 @@ export async function getUserByCredential( OR: [{ deletedAt: 0 }, { deletedAt: null }], }, include: { - user: true, + user: { + include: { + userAgreements: true, + }, + }, }, }); } diff --git a/src/lib/utils/repo/employee.repo.ts b/src/lib/utils/repo/employee.repo.ts index f27426ed1..06fbad3aa 100644 --- a/src/lib/utils/repo/employee.repo.ts +++ b/src/lib/utils/repo/employee.repo.ts @@ -238,13 +238,11 @@ export async function getProjectsByEmployeeId(employeeIdNumber: number) { employeeId: employeeIdNumber, endDate: null, }, - select: { - project: { - select: { - id: true, - name: true, - }, - }, + include: { + project: true, + }, + orderBy: { + startDate: 'asc', }, }); return projects; diff --git a/src/lib/utils/repo/profit_comparison.repo.ts b/src/lib/utils/repo/profit_comparison.repo.ts index 51d5827ea..cbad8b5bf 100644 --- a/src/lib/utils/repo/profit_comparison.repo.ts +++ b/src/lib/utils/repo/profit_comparison.repo.ts @@ -9,6 +9,9 @@ export async function getProjectLists(companyId: number) { where: { companyId, }, + orderBy: { + name: 'asc', + }, }); } diff --git a/src/lib/utils/repo_test/employee.repo.test.ts b/src/lib/utils/repo_test/employee.repo.test.ts index 0ca2b95b8..2fa03c55b 100644 --- a/src/lib/utils/repo_test/employee.repo.test.ts +++ b/src/lib/utils/repo_test/employee.repo.test.ts @@ -75,11 +75,10 @@ describe('Employee Repository Tests', () => { }); describe('getProjectsByEmployeeId', () => { it('should get projects by employee id', async () => { - const employeeId = 1000; + const employeeId = 1001; const projectsFromDb = await getProjectsByEmployeeId(employeeId); expect(projectsFromDb).toBeDefined(); expect(Array.isArray(projectsFromDb)).toBe(true); - expect(projectsFromDb.length).toBeGreaterThan(0); expect(projectsFromDb[0].project.id).toEqual(employeeProjects[0].projectId); }); }); diff --git a/src/lib/utils/repo_test/trasaction_test/project_members.tx.test.ts b/src/lib/utils/repo_test/trasaction_test/project_members.tx.test.ts index d1433ac25..baeaa16a5 100644 --- a/src/lib/utils/repo_test/trasaction_test/project_members.tx.test.ts +++ b/src/lib/utils/repo_test/trasaction_test/project_members.tx.test.ts @@ -45,6 +45,18 @@ describe('ProjectMembers Transaction Tests', () => { }); expect(existingMembers.length).toBe(2); await updateProjectMembers(testProjectId, memberIdList); // Reset the members + await prisma.employeeProject.deleteMany({ + where: { + projectId: testProjectId, + employeeId: { + in: [1000, 1001, 1002], + }, + endDate: { not: null }, + id: { + gte: 10000000, + }, + }, + }); }, 10000); }); }); diff --git a/src/lib/utils/repo_test/trasaction_test/project_milestone.tx.test.ts b/src/lib/utils/repo_test/trasaction_test/project_milestone.tx.test.ts index 3375a2a52..693dd4cf2 100644 --- a/src/lib/utils/repo_test/trasaction_test/project_milestone.tx.test.ts +++ b/src/lib/utils/repo_test/trasaction_test/project_milestone.tx.test.ts @@ -10,7 +10,7 @@ import { formatMilestoneList } from '@/lib/utils/formatter/milestone.formatter'; import { IMilestone } from '@/interfaces/project'; let milestoneList: IMilestone[] = []; -const testProjectId = 1000; +const testProjectId = 1009; beforeAll(async () => { const listedMilestone = await listProjectMilestone(testProjectId); @@ -18,8 +18,8 @@ beforeAll(async () => { }); describe('Project Milestone Tests', () => { - const defaultStage = 'Beta Testing'; - const updateStage = 'Sold'; + const defaultStage = 'Develop'; + const updateStage = 'Selling'; const now = Date.now(); const nowTimestamp = timestampInSeconds(now); diff --git a/src/pages/api/v1/company/[companyId]/account/[accountId]/index.ts b/src/pages/api/v1/company/[companyId]/account/[accountId]/index.ts index 3fde7cd51..00c5be676 100644 --- a/src/pages/api/v1/company/[companyId]/account/[accountId]/index.ts +++ b/src/pages/api/v1/company/[companyId]/account/[accountId]/index.ts @@ -14,7 +14,6 @@ import { getSession } from '@/lib/utils/session'; import { AuthFunctionsKeys } from '@/interfaces/auth'; function formatParams(companyId: unknown, accountId: string | string[] | undefined) { - // ToDo: (20240613 - Murky) - need to use type guard instead const isCompanyIdValid = !Number.isNaN(Number(companyId)); const isAccountIdValid = isParamNumeric(accountId); @@ -33,6 +32,9 @@ function formatParams(companyId: unknown, accountId: string | string[] | undefin async function getCompanyIdAccountId(req: NextApiRequest, res: NextApiResponse) { const session = await getSession(req, res); const { userId, companyId } = session; + if (!userId) { + throw new Error(STATUS_MESSAGE.UNAUTHORIZED_ACCESS); + } const isAuth = await checkAuthorization([AuthFunctionsKeys.admin], { userId, companyId }); if (!isAuth) { throw new Error(STATUS_MESSAGE.FORBIDDEN); @@ -45,69 +47,86 @@ async function getCompanyIdAccountId(req: NextApiRequest, res: NextApiResponse) }; } -export async function handleGetRequest(companyIdNumber: number, accountIdNumber: number) { +async function handleGetRequest( + req: NextApiRequest, + res: NextApiResponse> +) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IAccount | null = null; + + const { companyIdNumber, accountIdNumber } = await getCompanyIdAccountId(req, res); const accountFromDb = await findFirstAccountInPrisma(accountIdNumber, companyIdNumber); const account = accountFromDb ? formatAccount(accountFromDb) : ({} as IAccount); - const { httpCode, result } = formatApiResponse(STATUS_MESSAGE.SUCCESS, account); - return { - httpCode, - result, - }; + statusMessage = STATUS_MESSAGE.SUCCESS; + payload = account; + + return { statusMessage, payload }; } -async function handlePutRequest(companyIdNumber: number, accountIdNumber: number, name: string) { +async function handlePutRequest( + req: NextApiRequest, + res: NextApiResponse> +) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IAccount | null = null; + + const { companyIdNumber, accountIdNumber } = await getCompanyIdAccountId(req, res); + const { name } = req.body; const updatedAccount = await updateAccountInPrisma(accountIdNumber, companyIdNumber, name); const account = updatedAccount ? formatAccount(updatedAccount) : ({} as IAccount); - const { httpCode, result } = formatApiResponse(STATUS_MESSAGE.SUCCESS_UPDATE, account); - return { - httpCode, - result, - }; + statusMessage = STATUS_MESSAGE.SUCCESS_UPDATE; + payload = account; + + return { statusMessage, payload }; } -async function handleDeleteRequest(companyIdNumber: number, accountIdNumber: number) { +async function handleDeleteRequest( + req: NextApiRequest, + res: NextApiResponse> +) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IAccount | null = null; + + const { companyIdNumber, accountIdNumber } = await getCompanyIdAccountId(req, res); const deletedAccount = await softDeleteAccountInPrisma(accountIdNumber, companyIdNumber); const account = deletedAccount ? formatAccount(deletedAccount) : ({} as IAccount); - const { httpCode, result } = formatApiResponse(STATUS_MESSAGE.SUCCESS_DELETE, account); - return { - httpCode, - result, - }; -} + statusMessage = STATUS_MESSAGE.SUCCESS_DELETE; + payload = account; -export function handleErrorResponse(res: NextApiResponse, message: string) { - const { httpCode, result } = formatApiResponse(message, {} as IAccount); - return { - httpCode, - result, - }; + return { statusMessage, payload }; } +const methodHandlers: { + [key: string]: ( + req: NextApiRequest, + res: NextApiResponse + ) => Promise<{ statusMessage: string; payload: IAccount | null }>; +} = { + GET: handleGetRequest, + PUT: handlePutRequest, + DELETE: handleDeleteRequest, +}; + export default async function handler( req: NextApiRequest, - res: NextApiResponse> + res: NextApiResponse> ) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IAccount | null = null; + try { - const { companyIdNumber, accountIdNumber } = await getCompanyIdAccountId(req, res); - if (req.method === 'GET') { - const { httpCode, result } = await handleGetRequest(companyIdNumber, accountIdNumber); - res.status(httpCode).json(result); - } else if (req.method === 'PUT') { - const { name } = req.body; - const { httpCode, result } = await handlePutRequest(companyIdNumber, accountIdNumber, name); - res.status(httpCode).json(result); - } else if (req.method === 'DELETE') { - const { httpCode, result } = await handleDeleteRequest(companyIdNumber, accountIdNumber); - res.status(httpCode).json(result); + const handleRequest = methodHandlers[req.method || '']; + if (handleRequest) { + ({ statusMessage, payload } = await handleRequest(req, res)); } else { - throw new Error(STATUS_MESSAGE.METHOD_NOT_ALLOWED); + statusMessage = STATUS_MESSAGE.METHOD_NOT_ALLOWED; } } catch (_error) { const error = _error as Error; - // Info Murky (20240416): Debugging - // eslint-disable-next-line no-console - console.error(error.message); - const { httpCode, result } = handleErrorResponse(res, error.message); + statusMessage = error.message; + payload = null; + } finally { + const { httpCode, result } = formatApiResponse(statusMessage, payload); res.status(httpCode).json(result); } } diff --git a/src/pages/api/v1/company/[companyId]/account/index.ts b/src/pages/api/v1/company/[companyId]/account/index.ts index c02e0c230..338a05148 100644 --- a/src/pages/api/v1/company/[companyId]/account/index.ts +++ b/src/pages/api/v1/company/[companyId]/account/index.ts @@ -173,7 +173,7 @@ export function formatGetQuery(companyId: number, req: NextApiRequest): IAccount sortBy: formattedSortBy, sortOrder: formattedSortOrder, searchKey: formattedSearchKey, - isDeleted: formattedIsDeleted + isDeleted: formattedIsDeleted, }; } @@ -220,6 +220,9 @@ export async function handlePostRequest( const session = await getSession(req, res); const { userId, companyId } = session; const { accountId, name } = req.body; + if (!userId) { + throw new Error(STATUS_MESSAGE.UNAUTHORIZED_ACCESS); + } const isAuth = await checkAuthorization([AuthFunctionsKeys.admin], { userId, companyId }); if (!isAuth) { throw new Error(STATUS_MESSAGE.FORBIDDEN); @@ -233,7 +236,7 @@ export async function handlePostRequest( } const latestSubAccount = await findLatestSubAccountInPrisma(parentAccount); const newCode = setNewCode(parentAccount, latestSubAccount); - const newName = parentAccount.name + "-" + String(name); + const newName = parentAccount.name + '-' + String(name); const newOwnAccount = { companyId: companyIdNumber, system: parentAccount.system, diff --git a/src/pages/api/v1/company/[companyId]/admin/[adminId]/index.ts b/src/pages/api/v1/company/[companyId]/admin/[adminId]/index.ts index de5a224ab..4eb5f8026 100644 --- a/src/pages/api/v1/company/[companyId]/admin/[adminId]/index.ts +++ b/src/pages/api/v1/company/[companyId]/admin/[adminId]/index.ts @@ -1,77 +1,154 @@ import { STATUS_MESSAGE } from '@/constants/status_code'; import { IResponseData } from '@/interfaces/response_data'; +import { IAdmin } from '@/interfaces/admin'; import { convertStringToNumber, formatApiResponse } from '@/lib/utils/common'; import { NextApiRequest, NextApiResponse } from 'next'; -import { IAdmin } from '@/interfaces/admin'; import { checkAuthorization } from '@/lib/utils/auth_check'; import { deleteAdminById, getAdminById, updateAdminById } from '@/lib/utils/repo/admin.repo'; import { formatAdmin } from '@/lib/utils/formatter/admin.formatter'; import { AuthFunctionsKeys } from '@/interfaces/auth'; import { getSession } from '@/lib/utils/session'; -export default async function handler( +async function handleGetRequest( req: NextApiRequest, - res: NextApiResponse> + res: NextApiResponse> ) { - try { - const { adminId } = req.query; - const adminIdNum = convertStringToNumber(adminId); - if (req.method === 'GET') { - const session = await getSession(req, res); - const { userId, companyId } = session; - const isAuth = await checkAuthorization( - [AuthFunctionsKeys.CompanyAdminMatch, AuthFunctionsKeys.admin], - { userId, companyId, adminId: adminIdNum } - ); - if (!isAuth) { - throw new Error(STATUS_MESSAGE.FORBIDDEN); - } + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IAdmin | null = null; + + const { adminId } = req.query; + const adminIdNum = convertStringToNumber(adminId); + const session = await getSession(req, res); + const { userId, companyId } = session; + + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; + } else { + const isAuth = await checkAuthorization( + [AuthFunctionsKeys.CompanyAdminMatch, AuthFunctionsKeys.admin], + { userId, companyId, adminId: adminIdNum } + ); + + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; + } else { const getAdmin = await getAdminById(adminIdNum); if (!getAdmin) { - throw new Error(STATUS_MESSAGE.RESOURCE_NOT_FOUND); - } - const admin = await formatAdmin(getAdmin); - const { httpCode, result } = formatApiResponse(STATUS_MESSAGE.SUCCESS_GET, admin); - res.status(httpCode).json(result); - // Info: (20240419 - Jacky) S010003 - PUT /subscription/:id - } else if (req.method === 'PUT') { - const { status, roleName } = req.body; - if (typeof status !== 'boolean' && !roleName) { - throw new Error(STATUS_MESSAGE.INVALID_INPUT_PARAMETER); + statusMessage = STATUS_MESSAGE.RESOURCE_NOT_FOUND; + } else { + const admin = await formatAdmin(getAdmin); + statusMessage = STATUS_MESSAGE.SUCCESS_GET; + payload = admin; } - const session = await getSession(req, res); - const { userId, companyId } = session; - const isAuth = await checkAuthorization( - [AuthFunctionsKeys.owner, AuthFunctionsKeys.CompanyAdminMatch], - { userId, companyId, adminId: adminIdNum } - ); - if (!isAuth) { - throw new Error(STATUS_MESSAGE.FORBIDDEN); - } - const updatedAdmin = await updateAdminById(adminIdNum, status, roleName); - const admin = await formatAdmin(updatedAdmin); - const { httpCode, result } = formatApiResponse(STATUS_MESSAGE.SUCCESS_UPDATE, admin); - res.status(httpCode).json(result); - } else if (req.method === 'DELETE') { - const session = await getSession(req, res); - const { userId, companyId } = session; + } + } + + return { statusMessage, payload }; +} + +async function handlePutRequest( + req: NextApiRequest, + res: NextApiResponse> +) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IAdmin | null = null; + + const { adminId } = req.query; + const adminIdNum = convertStringToNumber(adminId); + const { status, roleName } = req.body; + + if (typeof status !== 'boolean' && !roleName) { + statusMessage = STATUS_MESSAGE.INVALID_INPUT_PARAMETER; + } else { + const session = await getSession(req, res); + const { userId, companyId } = session; + + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; + } else { const isAuth = await checkAuthorization( [AuthFunctionsKeys.owner, AuthFunctionsKeys.CompanyAdminMatch], { userId, companyId, adminId: adminIdNum } ); + if (!isAuth) { - throw new Error(STATUS_MESSAGE.FORBIDDEN); + statusMessage = STATUS_MESSAGE.FORBIDDEN; + } else { + const updatedAdmin = await updateAdminById(adminIdNum, status, roleName); + const admin = await formatAdmin(updatedAdmin); + statusMessage = STATUS_MESSAGE.SUCCESS_UPDATE; + payload = admin; } + } + } + + return { statusMessage, payload }; +} + +async function handleDeleteRequest( + req: NextApiRequest, + res: NextApiResponse> +) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IAdmin | null = null; + + const { adminId } = req.query; + const adminIdNum = convertStringToNumber(adminId); + const session = await getSession(req, res); + const { userId, companyId } = session; + + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; + } else { + const isAuth = await checkAuthorization( + [AuthFunctionsKeys.owner, AuthFunctionsKeys.CompanyAdminMatch], + { userId, companyId, adminId: adminIdNum } + ); + + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; + } else { const deletedAdmin = await deleteAdminById(adminIdNum); const admin = await formatAdmin(deletedAdmin); - const { httpCode, result } = formatApiResponse(STATUS_MESSAGE.SUCCESS_DELETE, admin); - res.status(httpCode).json(result); + statusMessage = STATUS_MESSAGE.SUCCESS_DELETE; + payload = admin; + } + } + + return { statusMessage, payload }; +} + +const methodHandlers: { + [key: string]: ( + req: NextApiRequest, + res: NextApiResponse + ) => Promise<{ statusMessage: string; payload: IAdmin | null }>; +} = { + GET: handleGetRequest, + PUT: handlePutRequest, + DELETE: handleDeleteRequest, +}; + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse> +) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IAdmin | null = null; + + try { + const handleRequest = methodHandlers[req.method || '']; + if (handleRequest) { + ({ statusMessage, payload } = await handleRequest(req, res)); } else { - throw new Error(STATUS_MESSAGE.METHOD_NOT_ALLOWED); + statusMessage = STATUS_MESSAGE.METHOD_NOT_ALLOWED; } } catch (_error) { const error = _error as Error; - const { httpCode, result } = formatApiResponse(error.message, {} as IAdmin); + statusMessage = error.message; + payload = null; + } finally { + const { httpCode, result } = formatApiResponse(statusMessage, payload); res.status(httpCode).json(result); } } diff --git a/src/pages/api/v1/company/[companyId]/admin/index.ts b/src/pages/api/v1/company/[companyId]/admin/index.ts index 1a259f72e..2310347d8 100644 --- a/src/pages/api/v1/company/[companyId]/admin/index.ts +++ b/src/pages/api/v1/company/[companyId]/admin/index.ts @@ -1,39 +1,71 @@ import { STATUS_MESSAGE } from '@/constants/status_code'; import { IResponseData } from '@/interfaces/response_data'; +import { IAdmin } from '@/interfaces/admin'; import { formatApiResponse } from '@/lib/utils/common'; import { NextApiRequest, NextApiResponse } from 'next'; -import { IAdmin } from '@/interfaces/admin'; import { checkAuthorization } from '@/lib/utils/auth_check'; import { listAdminByCompanyId } from '@/lib/utils/repo/admin.repo'; import { formatAdminList } from '@/lib/utils/formatter/admin.formatter'; import { getSession } from '@/lib/utils/session'; import { AuthFunctionsKeys } from '@/interfaces/auth'; -export default async function handler( +async function handleGetRequest( req: NextApiRequest, - res: NextApiResponse> + res: NextApiResponse> ) { - try { - if (req.method === 'GET') { - const session = await getSession(req, res); - const { userId, companyId } = session; - const isAuth = await checkAuthorization([AuthFunctionsKeys.admin], { userId, companyId }); - if (!isAuth) { - throw new Error(STATUS_MESSAGE.FORBIDDEN); - } + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IAdmin[] = []; + + const session = await getSession(req, res); + const { userId, companyId } = session; + + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; + } else { + const isAuth = await checkAuthorization([AuthFunctionsKeys.admin], { userId, companyId }); + + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; + } else { const listedAdmin = await listAdminByCompanyId(companyId); const adminList = await formatAdminList(listedAdmin); - const { httpCode, result } = formatApiResponse( - STATUS_MESSAGE.SUCCESS_GET, - adminList - ); - res.status(httpCode).json(result); + statusMessage = STATUS_MESSAGE.SUCCESS_GET; + payload = adminList; + } + } + + return { statusMessage, payload }; +} + +const methodHandlers: { + [key: string]: ( + req: NextApiRequest, + res: NextApiResponse + ) => Promise<{ statusMessage: string; payload: IAdmin[] }>; +} = { + GET: handleGetRequest, +}; + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse> +) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IAdmin[] = []; + + try { + const handleRequest = methodHandlers[req.method || '']; + if (handleRequest) { + ({ statusMessage, payload } = await handleRequest(req, res)); } else { - throw new Error(STATUS_MESSAGE.METHOD_NOT_ALLOWED); + statusMessage = STATUS_MESSAGE.METHOD_NOT_ALLOWED; } } catch (_error) { const error = _error as Error; - const { httpCode, result } = formatApiResponse(error.message, {} as IAdmin); + statusMessage = error.message; + payload = []; + } finally { + const { httpCode, result } = formatApiResponse(statusMessage, payload); res.status(httpCode).json(result); } } diff --git a/src/pages/api/v1/company/[companyId]/ask_ai/[resultId]/index.ts b/src/pages/api/v1/company/[companyId]/ask_ai/[resultId]/index.ts index 2b222f2eb..9cd548b3d 100644 --- a/src/pages/api/v1/company/[companyId]/ask_ai/[resultId]/index.ts +++ b/src/pages/api/v1/company/[companyId]/ask_ai/[resultId]/index.ts @@ -1,19 +1,18 @@ -import { AICH_URI } from '@/constants/config'; +import { STATUS_MESSAGE } from '@/constants/status_code'; import { IResponseData } from '@/interfaces/response_data'; import { IVoucherDataForSavingToDB } from '@/interfaces/voucher'; import { NextApiRequest, NextApiResponse } from 'next'; -import { STATUS_MESSAGE } from '@/constants/status_code'; import { formatApiResponse, isParamString } from '@/lib/utils/common'; import { ILineItem, ILineItemFromAICH } from '@/interfaces/line_item'; import { fuzzySearchAccountByName } from '@/pages/api/v1/company/[companyId]/ask_ai/[resultId]/index.repository'; import { isILineItem } from '@/lib/utils/type_guard/line_item'; import { isIVoucherDataForSavingToDB } from '@/lib/utils/type_guard/voucher'; import { IContract } from '@/interfaces/contract'; +import { AICH_URI } from '@/constants/config'; type ApiResponseType = IVoucherDataForSavingToDB | IContract | null; -// Info: ( 20240522 - Murkky)目前只可以使用Voucher Return -export async function fetchResultFromAICH(aiApi: string, resultId: string) { +async function fetchResultFromAICH(aiApi: string, resultId: string) { let response: Response; try { response = await fetch(`${AICH_URI}/api/v1/${aiApi}/${resultId}/result`); @@ -23,17 +22,13 @@ export async function fetchResultFromAICH(aiApi: string, resultId: string) { if (response.status === 404) { throw new Error(STATUS_MESSAGE.AICH_API_NOT_FOUND); } - if (!response.ok) { throw new Error(STATUS_MESSAGE.INTERNAL_SERVICE_ERROR_AICH_FAILED); } - return response.json() as Promise<{ payload?: unknown } | null>; } -export async function getPayloadFromResponseJSON( - responseJSON: Promise<{ payload?: unknown } | null> -) { +async function getPayloadFromResponseJSON(responseJSON: Promise<{ payload?: unknown } | null>) { if (!responseJSON) { throw new Error(STATUS_MESSAGE.INTERNAL_SERVICE_ERROR_AICH_FAILED); } @@ -45,9 +40,6 @@ export async function getPayloadFromResponseJSON( try { json = await responseJSON; } catch (error) { - // Deprecated: ( 20240522 - Murky)Debugging purpose - // eslint-disable-next-line no-console - console.error(error); throw new Error(STATUS_MESSAGE.PARSE_JSON_FAILED_ERROR); } @@ -65,9 +57,7 @@ async function formatLineItemsFromAICH(rawLineItems: ILineItemFromAICH[]) { const accountInDB = await fuzzySearchAccountByName(account); if (!accountInDB) { - // Deprecated: ( 20240522 - Murkky)Debugging purpose - // eslint-disable-next-line no-console - console.log(`Account ${account} not found in database`); + throw new Error(STATUS_MESSAGE.RESOURCE_NOT_FOUND); } const resultAccount = { @@ -80,9 +70,6 @@ async function formatLineItemsFromAICH(rawLineItems: ILineItemFromAICH[]) { } as ILineItem; if (!isILineItem(resultAccount)) { - // Deprecated: ( 20240522 - Murky)Debugging purpose - // eslint-disable-next-line no-console - console.log(`LineItem ${account} is not valid`); throw new Error(STATUS_MESSAGE.INTERNAL_SERVICE_ERROR); } return resultAccount; @@ -91,72 +78,76 @@ async function formatLineItemsFromAICH(rawLineItems: ILineItemFromAICH[]) { return lineItems; } -export async function handleGetRequest(req: NextApiRequest) { +async function handleGetRequest(req: NextApiRequest) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; let payload: IVoucherDataForSavingToDB | IContract | null = null; const { resultId, aiApi = 'vouchers' } = req.query; - // Info Murky (20240416): Check if resultId is string - if (!isParamString(resultId) || !isParamString(aiApi)) { - throw new Error(STATUS_MESSAGE.INVALID_INPUT_PARAMETER); - } - const fetchResult = fetchResultFromAICH(aiApi, resultId); - - switch (aiApi) { - case 'vouchers': { - const { lineItems: rawLineItems } = (await getPayloadFromResponseJSON(fetchResult)) as { - lineItems: ILineItemFromAICH[]; - }; - - const lineItems = await formatLineItemsFromAICH(rawLineItems); - const voucher = { - lineItems, - } as IVoucherDataForSavingToDB; - if (!isIVoucherDataForSavingToDB(voucher)) { - // Deprecated: ( 20240522 - Murky)Debugging purpose - // eslint-disable-next-line no-console - console.log('Voucher is not valid'); - throw new Error(STATUS_MESSAGE.INTERNAL_SERVICE_ERROR); + if (!isParamString(resultId) || !isParamString(aiApi)) { + statusMessage = STATUS_MESSAGE.INVALID_INPUT_PARAMETER; + } else { + const fetchResult = fetchResultFromAICH(aiApi, resultId); + + switch (aiApi) { + case 'vouchers': { + const { lineItems: rawLineItems } = (await getPayloadFromResponseJSON(fetchResult)) as { + lineItems: ILineItemFromAICH[]; + }; + + const lineItems = await formatLineItemsFromAICH(rawLineItems); + const voucher = { + lineItems, + } as IVoucherDataForSavingToDB; + if (!isIVoucherDataForSavingToDB(voucher)) { + statusMessage = STATUS_MESSAGE.INTERNAL_SERVICE_ERROR; + } else { + statusMessage = STATUS_MESSAGE.SUCCESS_GET; + payload = voucher; + } + break; } - payload = voucher; - break; - } - case 'contracts': { - // Todo (20240625 - Jacky): Implement contract return - payload = (await fetchResult) as IContract; - break; + case 'contracts': { + payload = (await fetchResult) as IContract; + statusMessage = STATUS_MESSAGE.SUCCESS_GET; + break; + } + default: + statusMessage = STATUS_MESSAGE.INVALID_INPUT_PARAMETER; } - default: - throw new Error(STATUS_MESSAGE.INVALID_INPUT_PARAMETER); } - const { httpCode, result } = formatApiResponse( - STATUS_MESSAGE.SUCCESS_GET, - payload - ); - - return { httpCode, result }; + return { statusMessage, payload }; } +const methodHandlers: { + [key: string]: ( + req: NextApiRequest, + res: NextApiResponse + ) => Promise<{ statusMessage: string; payload: ApiResponseType }>; +} = { + GET: handleGetRequest, +}; + export default async function handler( req: NextApiRequest, res: NextApiResponse> ) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: ApiResponseType = null; + try { - if (req.method === 'GET') { - const { httpCode, result } = await handleGetRequest(req); - res.status(httpCode).json(result); + const handleRequest = methodHandlers[req.method || '']; + if (handleRequest) { + ({ statusMessage, payload } = await handleRequest(req, res)); } else { - throw new Error(STATUS_MESSAGE.METHOD_NOT_ALLOWED); + statusMessage = STATUS_MESSAGE.METHOD_NOT_ALLOWED; } } catch (_error) { const error = _error as Error; - // Deprecated: ( 20240522 - Murky)Debugging purpose - // eslint-disable-next-line no-console - console.error(error); - const { httpCode, result } = formatApiResponse( - error.message, - {} as ApiResponseType - ); + statusMessage = error.message; + payload = null; + } finally { + const { httpCode, result } = formatApiResponse(statusMessage, payload); res.status(httpCode).json(result); } } diff --git a/src/pages/api/v1/company/[companyId]/ask_ai/[resultId]/status.ts b/src/pages/api/v1/company/[companyId]/ask_ai/[resultId]/status.ts index 04914a81e..4d8088d9b 100644 --- a/src/pages/api/v1/company/[companyId]/ask_ai/[resultId]/status.ts +++ b/src/pages/api/v1/company/[companyId]/ask_ai/[resultId]/status.ts @@ -1,58 +1,73 @@ -import type { NextApiRequest, NextApiResponse } from 'next'; -import { AICH_URI } from '@/constants/config'; -import { IResponseData } from '@/interfaces/response_data'; -import { formatApiResponse } from '@/lib/utils/common'; import { STATUS_MESSAGE } from '@/constants/status_code'; +import { IResponseData } from '@/interfaces/response_data'; import { ProgressStatus } from '@/constants/account'; +import { formatApiResponse } from '@/lib/utils/common'; +import { NextApiRequest, NextApiResponse } from 'next'; import { isProgressStatus } from '@/lib/utils/type_guard/account'; +import { AICH_URI } from '@/constants/config'; -export default async function handler( - req: NextApiRequest, - res: NextApiResponse> -) { - try { - const { resultId, aiApi = 'vouchers' } = req.query; +async function handleGetRequest(req: NextApiRequest) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: ProgressStatus | null = null; + const { resultId, aiApi = 'vouchers' } = req.query; - // Info Murky (20240416): Check if resultId is string - if (typeof resultId !== 'string' || !resultId || Array.isArray(resultId)) { - throw new Error(STATUS_MESSAGE.INVALID_INPUT_PARAMETER); - } + if (typeof resultId !== 'string' || !resultId || Array.isArray(resultId)) { + statusMessage = STATUS_MESSAGE.INVALID_INPUT_PARAMETER; + } else { + try { + const fetchResult = await fetch(`${AICH_URI}/api/v1/${aiApi}/${resultId}/process_status`); - switch (req.method) { - case 'GET': { - const fetchResult = await fetch(`${AICH_URI}/api/v1/${aiApi}/${resultId}/process_status`); + if (fetchResult.status === 404) { + statusMessage = STATUS_MESSAGE.AICH_API_NOT_FOUND; + } else if (!fetchResult.ok) { + statusMessage = STATUS_MESSAGE.INTERNAL_SERVICE_ERROR_AICH_FAILED; + } else { + const resultJson: ProgressStatus = (await fetchResult.json()).payload; - if (fetchResult.status === 404) { - throw new Error(STATUS_MESSAGE.AICH_API_NOT_FOUND); + if (!resultJson || !isProgressStatus(resultJson)) { + statusMessage = STATUS_MESSAGE.INTERNAL_SERVICE_ERROR_DATA_FROM_AICH_IS_INVALID_TYPE; + } else { + statusMessage = STATUS_MESSAGE.SUCCESS_GET; + payload = resultJson; } + } + } catch (error) { + statusMessage = STATUS_MESSAGE.INTERNAL_SERVICE_ERROR_AICH_FAILED; + } + } - if (!fetchResult.ok) { - throw new Error(STATUS_MESSAGE.INTERNAL_SERVICE_ERROR_AICH_FAILED); - } + return { statusMessage, payload }; +} - const resultJson: ProgressStatus = (await fetchResult.json()).payload; +const methodHandlers: { + [key: string]: ( + req: NextApiRequest, + res: NextApiResponse + ) => Promise<{ statusMessage: string; payload: ProgressStatus | null }>; +} = { + GET: handleGetRequest, +}; - if (!resultJson || !isProgressStatus(resultJson)) { - throw new Error(STATUS_MESSAGE.INTERNAL_SERVICE_ERROR_DATA_FROM_AICH_IS_INVALID_TYPE); - } +export default async function handler( + req: NextApiRequest, + res: NextApiResponse> +) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: ProgressStatus | null = null; - const { httpCode, result } = formatApiResponse( - STATUS_MESSAGE.SUCCESS_GET, - resultJson - ); - res.status(httpCode).json(result); - break; - } - default: { - throw new Error(STATUS_MESSAGE.METHOD_NOT_ALLOWED); - } + try { + const handleRequest = methodHandlers[req.method || '']; + if (handleRequest) { + ({ statusMessage, payload } = await handleRequest(req, res)); + } else { + statusMessage = STATUS_MESSAGE.METHOD_NOT_ALLOWED; } } catch (_error) { const error = _error as Error; - const { httpCode, result } = formatApiResponse( - error.message, - {} as ProgressStatus - ); + statusMessage = error.message; + payload = null; + } finally { + const { httpCode, result } = formatApiResponse(statusMessage, payload); res.status(httpCode).json(result); } } diff --git a/src/pages/api/v1/company/[companyId]/index.ts b/src/pages/api/v1/company/[companyId]/index.ts index 7444b0064..309ee91ac 100644 --- a/src/pages/api/v1/company/[companyId]/index.ts +++ b/src/pages/api/v1/company/[companyId]/index.ts @@ -1,94 +1,103 @@ -import { NextApiRequest, NextApiResponse } from 'next'; import { STATUS_MESSAGE } from '@/constants/status_code'; import { IResponseData } from '@/interfaces/response_data'; -import { ICompany, ICompanyAndRole } from '@/interfaces/company'; +import { IUser } from '@/interfaces/user'; import { convertStringToNumber, formatApiResponse } from '@/lib/utils/common'; -import { checkAuthorization } from '@/lib/utils/auth_check'; +import { getUserById, updateUserById } from '@/lib/utils/repo/user.repo'; +import { formatUser } from '@/lib/utils/formatter/user.formatter'; +import { NextApiRequest, NextApiResponse } from 'next'; import { getSession } from '@/lib/utils/session'; -import { - getCompanyById, - deleteCompanyById, - updateCompanyById, -} from '@/lib/utils/repo/company.repo'; -import { formatCompany } from '@/lib/utils/formatter/company.formatter'; -import { - deleteAdminListByCompanyId, - getCompanyDetailAndRoleByCompanyId, -} from '@/lib/utils/repo/admin.repo'; -import { formatCompanyDetailAndRole } from '@/lib/utils/formatter/admin.formatter'; +import { checkAuthorization } from '@/lib/utils/auth_check'; import { AuthFunctionsKeys } from '@/interfaces/auth'; -async function handleGetRequest(req: NextApiRequest, res: NextApiResponse) { +async function checkInput( + userId: string, + name: string, + fullName: string, + email: string, + phone: string +): Promise { + return !!userId && !!name && !!fullName && !!email && !!phone; +} + +async function handleGetRequest( + req: NextApiRequest, + res: NextApiResponse> +) { let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; - let payload: ICompany | ICompanyAndRole | null = null; + let payload: IUser | null = null; - const companyIdNum = convertStringToNumber(req.query.companyId); const session = await getSession(req, res); - const { userId } = session; - const isAuth = await checkAuthorization([AuthFunctionsKeys.user], { userId }); - if (!isAuth) { - statusMessage = STATUS_MESSAGE.FORBIDDEN; + const { userId, companyId } = session; + + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; } else { - const companyWithOwner = await getCompanyDetailAndRoleByCompanyId(userId, companyIdNum); - if (companyWithOwner) { - const companyDetailAndRole = formatCompanyDetailAndRole(companyWithOwner); - statusMessage = STATUS_MESSAGE.SUCCESS_GET; - payload = companyDetailAndRole; + const isAuth = await checkAuthorization([AuthFunctionsKeys.superAdmin], { userId, companyId }); + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; + } else { + const getUser = await getUserById(userId); + if (!getUser) { + statusMessage = STATUS_MESSAGE.SUCCESS_GET; + } else { + const user = formatUser(getUser); + statusMessage = STATUS_MESSAGE.SUCCESS_GET; + payload = user; + } } } return { statusMessage, payload }; } -async function handlePutRequest(req: NextApiRequest, res: NextApiResponse) { +async function handlePutRequest( + req: NextApiRequest, + res: NextApiResponse> +) { let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; - let payload: ICompany | null = null; + let payload: IUser | null = null; - const companyIdNum = convertStringToNumber(req.query.companyId); - const { code, name, regional } = req.body; - const session = await getSession(req, res); - const { userId } = session; - const isAuth = await checkAuthorization([AuthFunctionsKeys.owner], { - userId, - companyId: companyIdNum, - }); - if (!isAuth) { - statusMessage = STATUS_MESSAGE.FORBIDDEN; + const queryUserId = req.query.userId as string; + const { name, fullName, email, phone, imageId } = req.body; + const isValid = await checkInput(queryUserId, name, fullName, email, phone); + + if (!isValid) { + statusMessage = STATUS_MESSAGE.INVALID_INPUT_PARAMETER; } else { - const getCompany = await getCompanyById(companyIdNum); - if (getCompany) { - const updatedCompany = await updateCompanyById(companyIdNum, code, name, regional); - const company = formatCompany(updatedCompany); - payload = company; - } - statusMessage = STATUS_MESSAGE.SUCCESS_UPDATE; - } + const session = await getSession(req, res); + const { userId, companyId } = session; - return { statusMessage, payload }; -} + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; + } else { + const isAuth = await checkAuthorization([AuthFunctionsKeys.superAdmin], { + userId, + companyId, + }); -async function handleDeleteRequest(req: NextApiRequest, res: NextApiResponse) { - let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; - let payload: ICompany | null = null; + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; + } else { + const userIdNum = convertStringToNumber(queryUserId); + const getUser = await getUserById(userIdNum); - const companyIdNum = convertStringToNumber(req.query.companyId); - const session = await getSession(req, res); - const { userId } = session; - const isAuth = await checkAuthorization([AuthFunctionsKeys.owner], { - userId, - companyId: companyIdNum, - }); - if (!isAuth) { - statusMessage = STATUS_MESSAGE.FORBIDDEN; - } else { - const getCompany = await getCompanyById(companyIdNum); - if (getCompany) { - const deletedCompany = await deleteCompanyById(companyIdNum); - await deleteAdminListByCompanyId(companyIdNum); - const company = formatCompany(deletedCompany); - payload = company; + if (!getUser) { + statusMessage = STATUS_MESSAGE.RESOURCE_NOT_FOUND; + } else { + const updatedUser = await updateUserById( + userIdNum, + name, + fullName, + email, + phone, + imageId + ); + const user = formatUser(updatedUser); + statusMessage = STATUS_MESSAGE.SUCCESS_UPDATE; + payload = user; + } + } } - statusMessage = STATUS_MESSAGE.SUCCESS_DELETE; } return { statusMessage, payload }; @@ -98,19 +107,18 @@ const methodHandlers: { [key: string]: ( req: NextApiRequest, res: NextApiResponse - ) => Promise<{ statusMessage: string; payload: ICompany | ICompanyAndRole | null }>; + ) => Promise<{ statusMessage: string; payload: IUser | null }>; } = { GET: handleGetRequest, - DELETE: handleDeleteRequest, PUT: handlePutRequest, }; export default async function handler( req: NextApiRequest, - res: NextApiResponse> + res: NextApiResponse> ) { let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; - let payload: ICompany | ICompanyAndRole | null = null; + let payload: IUser | null = null; try { const handleRequest = methodHandlers[req.method || '']; @@ -124,10 +132,7 @@ export default async function handler( statusMessage = error.message; payload = null; } finally { - const { httpCode, result } = formatApiResponse( - statusMessage, - payload - ); + const { httpCode, result } = formatApiResponse(statusMessage, payload); res.status(httpCode).json(result); } } diff --git a/src/pages/api/v1/company/[companyId]/project/[projectId]/milestone/[milestoneId]/index.ts b/src/pages/api/v1/company/[companyId]/project/[projectId]/milestone/[milestoneId]/index.ts deleted file mode 100644 index 9b66eca16..000000000 --- a/src/pages/api/v1/company/[companyId]/project/[projectId]/milestone/[milestoneId]/index.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { STATUS_MESSAGE } from '@/constants/status_code'; -import { IResponseData } from '@/interfaces/response_data'; -import { convertStringToNumber, formatApiResponse } from '@/lib/utils/common'; -import { checkAuthorization } from '@/lib/utils/auth_check'; -import { NextApiRequest, NextApiResponse } from 'next'; -import { IMilestone } from '@/interfaces/project'; -import { updateProjectMilestone } from '@/lib/utils/repo/transaction/project_milestone.tx'; -import { getSession } from '@/lib/utils/session'; -import { getProjectById } from '@/lib/utils/repo/project.repo'; -import { listProjectMilestone } from '@/lib/utils/repo/milestone.repo'; -import { formatMilestoneList } from '@/lib/utils/formatter/milestone.formatter'; -import { AuthFunctionsKeys } from '@/interfaces/auth'; - -async function checkInput(projectId: string, stage: string, startDate: string) { - let isValid = true; - if (!stage || !startDate || !projectId) { - isValid = false; - } - return isValid; -} - -async function checkAuth(userId: number, companyId: number, projectId: number) { - let isValid = true; - const isAdmin = await checkAuthorization([AuthFunctionsKeys.admin], { userId, companyId }); - if (!isAdmin) { - isValid = false; - } else { - const project = await getProjectById(projectId); - if (!project || project.companyId !== companyId) { - isValid = false; - } - } - - return isValid; -} - -export default async function handler( - req: NextApiRequest, - res: NextApiResponse> -) { - let shouldContinue = true; - let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; - let payload: IMilestone[] = []; - try { - switch (req.method) { - case 'PUT': { - const { projectId } = req.query; - const { stage, startDate } = req.body; - // Info: (20240703 - Jacky) should convert to string - shouldContinue = await checkInput( - projectId as string, - stage as string, - startDate as string - ); - // Info: (20240703 - Jacky) check authorization start - if (shouldContinue) { - const session = await getSession(req, res); - const { userId, companyId } = session; - const projectIdNum = convertStringToNumber(projectId); - shouldContinue = await checkAuth(userId, companyId, projectIdNum); - if (shouldContinue) { - const startDateNum = convertStringToNumber(startDate); - const listedMilestone = await listProjectMilestone(projectIdNum); - const milestoneList = formatMilestoneList(listedMilestone); - if (milestoneList.length === 0) { - statusMessage = STATUS_MESSAGE.RESOURCE_NOT_FOUND; - } else { - const { updatedMilestoneList } = await updateProjectMilestone( - projectIdNum, - milestoneList, - stage, - startDateNum - ); - statusMessage = STATUS_MESSAGE.SUCCESS_UPDATE; - payload = updatedMilestoneList; - } - } - } - break; - } - default: - statusMessage = STATUS_MESSAGE.METHOD_NOT_ALLOWED; - } - } catch (_error) { - const error = _error as Error; - statusMessage = error.message; - payload = []; - } - const { httpCode, result } = formatApiResponse(statusMessage, payload); - res.status(httpCode).json(result); -} diff --git a/src/pages/api/v1/company/[companyId]/project/[projectId]/milestone/index.ts b/src/pages/api/v1/company/[companyId]/project/[projectId]/milestone/index.ts index 19ef8a05f..01e6c0a85 100644 --- a/src/pages/api/v1/company/[companyId]/project/[projectId]/milestone/index.ts +++ b/src/pages/api/v1/company/[companyId]/project/[projectId]/milestone/index.ts @@ -1,77 +1,107 @@ import { NextApiRequest, NextApiResponse } from 'next'; +import { IClient } from '@/interfaces/client'; import { IResponseData } from '@/interfaces/response_data'; import { STATUS_MESSAGE } from '@/constants/status_code'; -import { convertStringToNumber, formatApiResponse } from '@/lib/utils/common'; -import { checkAuthorization } from '@/lib/utils/auth_check'; -import { IMilestone } from '@/interfaces/project'; -import { listProjectMilestone } from '@/lib/utils/repo/milestone.repo'; -import { formatMilestoneList } from '@/lib/utils/formatter/milestone.formatter'; +import { formatApiResponse } from '@/lib/utils/common'; +import { deleteClientById, getClientById, updateClientById } from '@/lib/utils/repo/client.repo'; import { getSession } from '@/lib/utils/session'; -import { getProjectById } from '@/lib/utils/repo/project.repo'; -import { AuthFunctionsKeys } from '@/interfaces/auth'; +import { getAdminByCompanyIdAndUserId } from '@/lib/utils/repo/admin.repo'; -async function checkInput(projectId: string) { - let isValid = true; - if (!projectId) { - isValid = false; +async function checkAuth(userId: number, companyId: number): Promise { + const admin = await getAdminByCompanyIdAndUserId(companyId, userId); + return !!admin; +} + +async function handleGetRequest(req: NextApiRequest, res: NextApiResponse) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IClient | IClient[] | null = null; + const session = await getSession(req, res); + const { userId, companyId } = session; + const isAuth = await checkAuth(userId, companyId); + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; + } else { + const clientIdNum = Number(req.query.clientId); + const getClient = await getClientById(clientIdNum); + statusMessage = STATUS_MESSAGE.SUCCESS_GET; + payload = getClient; } - return isValid; + return { statusMessage, payload }; } -async function checkAuth(userId: number, companyId: number, projectId: number) { - let isValid = true; - const isAdmin = await checkAuthorization([AuthFunctionsKeys.admin], { userId, companyId }); - if (!isAdmin) { - isValid = false; +async function handlePutRequest(req: NextApiRequest, res: NextApiResponse) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IClient | IClient[] | null = null; + const session = await getSession(req, res); + const { userId, companyId } = session; + const isAuth = await checkAuth(userId, companyId); + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; } else { - const project = await getProjectById(projectId); - if (!project || project.companyId !== companyId) { - isValid = false; - } + const clientIdNum = Number(req.query.clientId); + const { name, taxId, favorite } = req.body; + const updatedClient = await updateClientById(clientIdNum, name, taxId, favorite); + statusMessage = updatedClient + ? STATUS_MESSAGE.SUCCESS_UPDATE + : STATUS_MESSAGE.RESOURCE_NOT_FOUND; + payload = updatedClient; } + return { statusMessage, payload }; +} - return isValid; +async function handleDeleteRequest(req: NextApiRequest, res: NextApiResponse) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IClient | IClient[] | null = null; + const session = await getSession(req, res); + const { userId, companyId } = session; + const isAuth = await checkAuth(userId, companyId); + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; + } else { + const clientIdNum = Number(req.query.clientId); + const deletedClient = await deleteClientById(clientIdNum); + statusMessage = deletedClient + ? STATUS_MESSAGE.SUCCESS_DELETE + : STATUS_MESSAGE.RESOURCE_NOT_FOUND; + payload = deletedClient; + } + return { statusMessage, payload }; } +const methodHandlers: { + [key: string]: ( + req: NextApiRequest, + res: NextApiResponse + ) => Promise<{ statusMessage: string; payload: IClient | IClient[] | null }>; +} = { + GET: handleGetRequest, + PUT: handlePutRequest, + DELETE: handleDeleteRequest, +}; + export default async function handler( req: NextApiRequest, - res: NextApiResponse> + res: NextApiResponse> ) { - let shouldContinue = true; let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; - let payload: IMilestone[] = []; - try { - switch (req.method) { - case 'GET': { - const { projectId } = req.query; - shouldContinue = await checkInput(projectId as string); - if (!shouldContinue) { - statusMessage = STATUS_MESSAGE.INVALID_INPUT_PARAMETER; - } else { - const session = await getSession(req, res); - const { userId, companyId } = session; - const projectIdNum = convertStringToNumber(projectId); + let payload: IClient | IClient[] | null = null; - shouldContinue = await checkAuth(userId, companyId, projectIdNum); - if (!shouldContinue) { - statusMessage = STATUS_MESSAGE.FORBIDDEN; - } else { - const listedMilestone = await listProjectMilestone(projectIdNum); - const milestoneList = formatMilestoneList(listedMilestone); - statusMessage = STATUS_MESSAGE.SUCCESS_GET; - payload = milestoneList; - } - } - break; - } - default: - statusMessage = STATUS_MESSAGE.METHOD_NOT_ALLOWED; + try { + const handleRequest = methodHandlers[req.method || '']; + if (handleRequest) { + ({ statusMessage, payload } = await handleRequest(req, res)); + } else { + statusMessage = STATUS_MESSAGE.METHOD_NOT_ALLOWED; } } catch (_error) { const error = _error as Error; statusMessage = error.message; - payload = []; + payload = null; + } finally { + const { httpCode, result } = formatApiResponse( + statusMessage, + payload + ); + res.status(httpCode).json(result); } - const { httpCode, result } = formatApiResponse(statusMessage, payload); - res.status(httpCode).json(result); } diff --git a/src/pages/api/v1/company/[companyId]/select.ts b/src/pages/api/v1/company/[companyId]/select.ts index 5116c093d..af96ab6d3 100644 --- a/src/pages/api/v1/company/[companyId]/select.ts +++ b/src/pages/api/v1/company/[companyId]/select.ts @@ -10,23 +10,32 @@ import { formatCompany } from '@/lib/utils/formatter/company.formatter'; import { AuthFunctionsKeys } from '@/interfaces/auth'; import { NON_EXISTING_COMPANY_ID } from '@/constants/config'; -async function handlePutRequest(req: NextApiRequest, res: NextApiResponse) { +async function handlePutRequest( + req: NextApiRequest, + res: NextApiResponse> +) { let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; let payload: ICompany | null = null; const companyIdNum = convertStringToNumber(req.query.companyId); const session = await getSession(req, res); const { userId } = session; - const isAuth = await checkAuthorization([AuthFunctionsKeys.user], { userId }); - if (!isAuth) { - statusMessage = STATUS_MESSAGE.FORBIDDEN; + + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; } else { - const getCompany = await getCompanyById(companyIdNum); - statusMessage = STATUS_MESSAGE.SUCCESS_UPDATE; - const companyId = getCompany ? companyIdNum : NON_EXISTING_COMPANY_ID; - const company = getCompany ? formatCompany(getCompany) : null; - await setSession(session, undefined, companyId); - payload = company; + const isAuth = await checkAuthorization([AuthFunctionsKeys.user], { userId }); + + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; + } else { + const getCompany = await getCompanyById(companyIdNum); + statusMessage = STATUS_MESSAGE.SUCCESS_UPDATE; + const companyId = getCompany ? companyIdNum : NON_EXISTING_COMPANY_ID; + const company = getCompany ? formatCompany(getCompany) : null; + await setSession(session, undefined, companyId); + payload = company; + } } return { statusMessage, payload }; diff --git a/src/pages/api/v1/company/[companyId]/transfer_owner.ts b/src/pages/api/v1/company/[companyId]/transfer_owner.ts index a2b48e0db..c44056f9c 100644 --- a/src/pages/api/v1/company/[companyId]/transfer_owner.ts +++ b/src/pages/api/v1/company/[companyId]/transfer_owner.ts @@ -9,22 +9,33 @@ import { getSession } from '@/lib/utils/session'; import { transferOwnership } from '@/lib/utils/repo/transaction/admin_role.tx'; import { AuthFunctionsKeys } from '@/interfaces/auth'; -async function handlePutRequest(req: NextApiRequest, res: NextApiResponse) { +async function handlePutRequest( + req: NextApiRequest, + res: NextApiResponse> +) { let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; - let payload: IAdmin[] = []; + let payload: IAdmin[] | null = null; + const { newOwnerId } = req.body; const newOwnerIdNum = convertStringToNumber(newOwnerId); const session = await getSession(req, res); const { userId, companyId } = session; - const isAuth = await checkAuthorization([AuthFunctionsKeys.owner], { userId, companyId }); - if (!isAuth) { - statusMessage = STATUS_MESSAGE.FORBIDDEN; + + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; } else { - const updatedAdmin = await transferOwnership(userId, companyId, newOwnerIdNum); - const admin = await formatAdminList(updatedAdmin); - statusMessage = STATUS_MESSAGE.SUCCESS_UPDATE; - payload = admin; + const isAuth = await checkAuthorization([AuthFunctionsKeys.owner], { userId, companyId }); + + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; + } else { + const updatedAdmin = await transferOwnership(userId, companyId, newOwnerIdNum); + const admin = await formatAdminList(updatedAdmin); + statusMessage = STATUS_MESSAGE.SUCCESS_UPDATE; + payload = admin; + } } + return { statusMessage, payload }; } @@ -42,7 +53,7 @@ export default async function handler( res: NextApiResponse> ) { let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; - let payload: IAdmin | IAdmin[] | null = null; + let payload: IAdmin[] | null = null; try { const handleRequest = methodHandlers[req.method || '']; diff --git a/src/pages/api/v1/company/index.ts b/src/pages/api/v1/company/index.ts index f69fd38e5..0633ed268 100644 --- a/src/pages/api/v1/company/index.ts +++ b/src/pages/api/v1/company/index.ts @@ -9,28 +9,104 @@ import { formatCompanyAndRoleList, } from '@/lib/utils/formatter/admin.formatter'; import { createCompanyAndRole, listCompanyAndRole } from '@/lib/utils/repo/admin.repo'; -import { getUserById } from '@/lib/utils/repo/user.repo'; -import { getSession } from '@/lib/utils/session'; import { getCompanyByCode } from '@/lib/utils/repo/company.repo'; import { generateIcon } from '@/lib/utils/generate_user_icon'; +import { getSession } from '@/lib/utils/session'; +import { checkAuthorization } from '@/lib/utils/auth_check'; +import { AuthFunctionsKeys } from '@/interfaces/auth'; + +async function checkInput(code: string, name: string, regional: string): Promise { + return !!code && !!name && !!regional; +} + +async function handleGetRequest( + req: NextApiRequest, + res: NextApiResponse | null>> +) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: Array<{ company: ICompany; role: IRole }> | null = null; + const session = await getSession(req, res); + const { userId } = session; -async function checkAuth(userId: number) { - let isValid = true; - const getUser = await getUserById(userId); - if (!getUser) { - isValid = false; + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; + } else { + const isAuth = await checkAuthorization([AuthFunctionsKeys.user], { userId }); + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; + } else { + const listedCompanyAndRole = await listCompanyAndRole(userId); + const companyAndRoleList = await formatCompanyAndRoleList(listedCompanyAndRole); + statusMessage = STATUS_MESSAGE.SUCCESS_GET; + payload = companyAndRoleList; + } } - return isValid; + + return { statusMessage, payload }; } -async function checkInput(code: string, name: string, regional: string) { - let isValid = true; - if (!code || !name || !regional) { - isValid = false; +async function handlePostRequest( + req: NextApiRequest, + res: NextApiResponse> +) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: { company: ICompany; role: IRole } | null = null; + const { code, name, regional } = req.body; + const isValid = await checkInput(code, name, regional); + + if (!isValid) { + statusMessage = STATUS_MESSAGE.INVALID_INPUT_PARAMETER; + } else { + const session = await getSession(req, res); + const { userId } = session; + + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; + } else { + const isAuth = await checkAuthorization([AuthFunctionsKeys.user], { userId }); + + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; + } else { + const getCompany = await getCompanyByCode(code); + + if (getCompany) { + statusMessage = getCompany.kycStatus + ? STATUS_MESSAGE.DUPLICATE_COMPANY_KYC_DONE + : STATUS_MESSAGE.DUPLICATE_COMPANY; + } else { + const companyIcon = await generateIcon(name); + const createdCompanyRoleList = await createCompanyAndRole( + userId, + code, + name, + regional, + companyIcon + ); + const newCompanyRoleList = await formatCompanyAndRole(createdCompanyRoleList); + statusMessage = STATUS_MESSAGE.CREATED; + payload = newCompanyRoleList; + } + } + } } - return isValid; + + return { statusMessage, payload }; } +const methodHandlers: { + [key: string]: ( + req: NextApiRequest, + res: NextApiResponse + ) => Promise<{ + statusMessage: string; + payload: { company: ICompany; role: IRole } | Array<{ company: ICompany; role: IRole }> | null; + }>; +} = { + GET: handleGetRequest, + POST: handlePostRequest, +}; + export default async function handler( req: NextApiRequest, res: NextApiResponse< @@ -46,66 +122,20 @@ export default async function handler( | null = null; try { - switch (req.method) { - case 'GET': { - const session = await getSession(req, res); - const { userId } = session; - const isAuth = await checkAuth(userId); - if (!isAuth) { - statusMessage = STATUS_MESSAGE.FORBIDDEN; - } else { - const listedCompanyAndRole = await listCompanyAndRole(userId); - const companyAndRoleList = await formatCompanyAndRoleList(listedCompanyAndRole); - statusMessage = STATUS_MESSAGE.SUCCESS_GET; - payload = companyAndRoleList; - } - break; - } - case 'POST': { - const { code, name, regional } = req.body; - const isValid = await checkInput(code, name, regional); - if (!isValid) { - statusMessage = STATUS_MESSAGE.INVALID_INPUT_PARAMETER; - } else { - const session = await getSession(req, res); - const { userId } = session; - const isAuth = await checkAuth(userId); - if (!isAuth) { - statusMessage = STATUS_MESSAGE.FORBIDDEN; - } else { - const getCompany = await getCompanyByCode(code); - if (getCompany) { - statusMessage = getCompany.kycStatus - ? STATUS_MESSAGE.DUPLICATE_COMPANY_KYC_DONE - : STATUS_MESSAGE.DUPLICATE_COMPANY; - } else { - const companyIcon = await generateIcon(name); - const createdCompanyRoleList = await createCompanyAndRole( - userId, - code, - name, - regional, - companyIcon - ); - const newCompanyRoleList = await formatCompanyAndRole(createdCompanyRoleList); - statusMessage = STATUS_MESSAGE.CREATED; - payload = newCompanyRoleList; - } - } - } - break; - } - default: - statusMessage = STATUS_MESSAGE.METHOD_NOT_ALLOWED; + const handleRequest = methodHandlers[req.method || '']; + if (handleRequest) { + ({ statusMessage, payload } = await handleRequest(req, res)); + } else { + statusMessage = STATUS_MESSAGE.METHOD_NOT_ALLOWED; } } catch (_error) { const error = _error as Error; statusMessage = error.message; payload = null; + } finally { + const { httpCode, result } = formatApiResponse< + { company: ICompany; role: IRole } | Array<{ company: ICompany; role: IRole }> | null + >(statusMessage, payload); + res.status(httpCode).json(result); } - - const { httpCode, result } = formatApiResponse< - { company: ICompany; role: IRole } | Array<{ company: ICompany; role: IRole }> | null - >(statusMessage, payload); - res.status(httpCode).json(result); } diff --git a/src/pages/api/v1/sign_in.ts b/src/pages/api/v1/sign_in.ts index 9b07f1dce..f83127076 100644 --- a/src/pages/api/v1/sign_in.ts +++ b/src/pages/api/v1/sign_in.ts @@ -9,6 +9,7 @@ import { getSession, setSession } from '@/lib/utils/session'; import { useInvitation } from '@/lib/utils/invitation'; import { verifyChallengeTimestamp } from '@/lib/utils/authorization'; import { getUserByCredential } from '@/lib/utils/repo/authentication.repo'; +import { formatUser } from '@/lib/utils/formatter/user.formatter'; async function authenticateUser( authentication: AuthenticationEncoded, @@ -38,6 +39,7 @@ async function authenticateUser( }; try { await server.verifyAuthentication(authentication, registeredCredential, expected); + user = formatUser(getUser.user); } catch (error) { isValid = false; user = null; diff --git a/src/pages/api/v1/user/[userId]/index.ts b/src/pages/api/v1/user/[userId]/index.ts index 3d7ee2f8c..2187a83e2 100644 --- a/src/pages/api/v1/user/[userId]/index.ts +++ b/src/pages/api/v1/user/[userId]/index.ts @@ -16,7 +16,8 @@ async function checkInput( email: string, phone: string ): Promise { - return !!userId && !!name && !!fullName && !!email && !!phone; + const isValid = !!userId && !!name && !!fullName && !!email && !!phone; + return isValid; } async function handleGetRequest( @@ -25,21 +26,30 @@ async function handleGetRequest( ) { let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; let payload: IUser | null = null; + const session = await getSession(req, res); - const { userId, companyId } = session; - const isAuth = await checkAuthorization([AuthFunctionsKeys.superAdmin], { userId, companyId }); - if (!isAuth) { - statusMessage = STATUS_MESSAGE.FORBIDDEN; + const { userId } = session; + + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; } else { - const getUser = await getUserById(userId); - if (!getUser) { - statusMessage = STATUS_MESSAGE.SUCCESS_GET; + const isAuth = await checkAuthorization([AuthFunctionsKeys.user], { + userId, + }); + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; } else { - const user = formatUser(getUser); - statusMessage = STATUS_MESSAGE.SUCCESS_GET; - payload = user; + const getUser = await getUserById(userId); + if (!getUser) { + statusMessage = STATUS_MESSAGE.RESOURCE_NOT_FOUND; + } else { + const user = formatUser(getUser); + statusMessage = STATUS_MESSAGE.SUCCESS_GET; + payload = user; + } } } + return { statusMessage, payload }; } @@ -49,30 +59,47 @@ async function handlePutRequest( ) { let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; let payload: IUser | null = null; + const queryUserId = req.query.userId as string; const { name, fullName, email, phone, imageId } = req.body; const isValid = await checkInput(queryUserId, name, fullName, email, phone); + if (!isValid) { statusMessage = STATUS_MESSAGE.INVALID_INPUT_PARAMETER; } else { const session = await getSession(req, res); - const { userId, companyId } = session; - const isAuth = await checkAuthorization([AuthFunctionsKeys.superAdmin], { userId, companyId }); - if (!isAuth) { - statusMessage = STATUS_MESSAGE.FORBIDDEN; + const { userId } = session; + + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; } else { - const userIdNum = convertStringToNumber(queryUserId); - const getUser = await getUserById(userIdNum); - if (!getUser) { - statusMessage = STATUS_MESSAGE.RESOURCE_NOT_FOUND; + const isAuth = await checkAuthorization([AuthFunctionsKeys.user], { + userId, + }); + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; } else { - const updatedUser = await updateUserById(userIdNum, name, fullName, email, phone, imageId); - const user = formatUser(updatedUser); - statusMessage = STATUS_MESSAGE.SUCCESS_UPDATE; - payload = user; + const userIdNum = convertStringToNumber(queryUserId); + const getUser = await getUserById(userIdNum); + if (!getUser) { + statusMessage = STATUS_MESSAGE.RESOURCE_NOT_FOUND; + } else { + const updatedUser = await updateUserById( + userIdNum, + name, + fullName, + email, + phone, + imageId + ); + const user = await formatUser(updatedUser); + statusMessage = STATUS_MESSAGE.SUCCESS_UPDATE; + payload = user; + } } } } + return { statusMessage, payload }; } diff --git a/src/pages/api/v1/user/[userId]/invitation.ts b/src/pages/api/v1/user/[userId]/invitation.ts index a2b0d6c82..682d5fc0a 100644 --- a/src/pages/api/v1/user/[userId]/invitation.ts +++ b/src/pages/api/v1/user/[userId]/invitation.ts @@ -27,6 +27,9 @@ export default async function handler( case 'PUT': { const session = await getSession(req, res); const { userId } = session; + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; + } const { invitation } = req.body; const isValid = await checkInput(invitation); if (!isValid) { diff --git a/src/pages/api/v1/user/index.ts b/src/pages/api/v1/user/index.ts index 7ff3d6c15..6406dae6d 100644 --- a/src/pages/api/v1/user/index.ts +++ b/src/pages/api/v1/user/index.ts @@ -9,45 +9,51 @@ import { formatUser, formatUserList } from '@/lib/utils/formatter/user.formatter import { getSession } from '@/lib/utils/session'; import { AuthFunctionsKeys } from '@/interfaces/auth'; -export default async function handler( - req: NextApiRequest, - res: NextApiResponse> -) { - try { - // Todo: (20240419 - Jacky) add query like cursor, limit, etc. - if (req.method === 'GET') { - const session = await getSession(req, res); - const { userId, companyId } = session; - const isAuth = await checkAuthorization([AuthFunctionsKeys.superAdmin], { - userId, - companyId, - }); - if (!isAuth) { - throw new Error(STATUS_MESSAGE.FORBIDDEN); - } else { - const listedUser = await listUser(); - const userList: IUser[] = await formatUserList(listedUser); - const { httpCode, result } = formatApiResponse( - STATUS_MESSAGE.SUCCESS_LIST, - userList - ); - res.status(httpCode).json(result); - } - } else if (req.method === 'POST') { - // Handle POST request to create a new user - const { name, fullName, email, phone, credentialId, publicKey, algorithm, imageId } = - req.body; - if (!name || !credentialId || !publicKey || !algorithm) { - throw new Error(STATUS_MESSAGE.INVALID_INPUT_PARAMETER); - } - const session = await getSession(req, res); - const { userId, companyId } = session; +async function handleGetRequest(req: NextApiRequest, res: NextApiResponse) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IUser | IUser[] | null = null; + const session = await getSession(req, res); + const { userId, companyId } = session; + + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; + } else { + const isAuth = await checkAuthorization([AuthFunctionsKeys.superAdmin], { userId, companyId }); + + if (!isAuth) { + statusMessage = STATUS_MESSAGE.FORBIDDEN; + } else { + const listedUser = await listUser(); + const userList: IUser[] = await formatUserList(listedUser); + statusMessage = STATUS_MESSAGE.SUCCESS_LIST; + payload = userList; + } + } + + return { statusMessage, payload }; +} + +async function handlePostRequest(req: NextApiRequest, res: NextApiResponse) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IUser | IUser[] | null = null; + const { name, fullName, email, phone, credentialId, publicKey, algorithm, imageId } = req.body; + + if (!name || !credentialId || !publicKey || !algorithm) { + statusMessage = STATUS_MESSAGE.INVALID_INPUT_PARAMETER; + } else { + const session = await getSession(req, res); + const { userId, companyId } = session; + + if (!userId) { + statusMessage = STATUS_MESSAGE.UNAUTHORIZED_ACCESS; + } else { const isAuth = await checkAuthorization([AuthFunctionsKeys.superAdmin], { userId, companyId, }); + if (!isAuth) { - throw new Error(STATUS_MESSAGE.FORBIDDEN); + statusMessage = STATUS_MESSAGE.FORBIDDEN; } else { const createdUser = await createUser({ name, @@ -57,17 +63,45 @@ export default async function handler( imageUrl: imageId, }); const user = formatUser(createdUser); - const { httpCode, result } = formatApiResponse(STATUS_MESSAGE.CREATED, user); - res.status(httpCode).json(result); + statusMessage = STATUS_MESSAGE.CREATED; + payload = user; } + } + } + + return { statusMessage, payload }; +} + +const methodHandlers: { + [key: string]: ( + req: NextApiRequest, + res: NextApiResponse + ) => Promise<{ statusMessage: string; payload: IUser | IUser[] | null }>; +} = { + GET: handleGetRequest, + POST: handlePostRequest, +}; + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse> +) { + let statusMessage: string = STATUS_MESSAGE.BAD_REQUEST; + let payload: IUser | IUser[] | null = null; + + try { + const handleRequest = methodHandlers[req.method || '']; + if (handleRequest) { + ({ statusMessage, payload } = await handleRequest(req, res)); } else { - // Handle unsupported HTTP methods - throw new Error(STATUS_MESSAGE.METHOD_NOT_ALLOWED); + statusMessage = STATUS_MESSAGE.METHOD_NOT_ALLOWED; } } catch (_error) { - // Handle errors const error = _error as Error; - const { httpCode, result } = formatApiResponse(error.message, {} as IUser); + statusMessage = error.message; + payload = null; + } finally { + const { httpCode, result } = formatApiResponse(statusMessage, payload); res.status(httpCode).json(result); } }