25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

255 lines
8.1 KiB

  1. import { NextRequestWithAuth, withAuth } from "next-auth/middleware";
  2. import { ability, authOptions } from "@/config/authConfig";
  3. import { NextFetchEvent, NextResponse } from "next/server";
  4. import { getToken } from "next-auth/jwt";
  5. // user groups
  6. export const [
  7. SUPER_ADMIN,
  8. TOP_MANAGEMENT,
  9. TEAM_LEAD,
  10. NORMAL_STAFF,
  11. SUPPORTING_STAFF
  12. ] = [
  13. "Super Admin",
  14. "Top Management",
  15. "Team Leader",
  16. "Normal Staff",
  17. "Supporting Staff"
  18. ]
  19. // abilities
  20. export const [
  21. MAINTAIN_USER,
  22. MAINTAIN_TIMESHEET,
  23. VIEW_TASK_TEMPLATE,
  24. VIEW_GROUP,
  25. VIEW_CLIENT,
  26. VIEW_SUBSIDIARY,
  27. VIEW_STAFF,
  28. VIEW_COMPANY,
  29. VIEW_SKILL,
  30. VIEW_DEPARTMENT,
  31. VIEW_POSITION,
  32. VIEW_SALARY,
  33. VIEW_TEAM,
  34. VIEW_HOLIDAY,
  35. MAINTAIN_CLIENT,
  36. MAINTAIN_SUBSIDIARY,
  37. MAINTAIN_STAFF,
  38. MAINTAIN_COMPANY,
  39. MAINTAIN_SKILL,
  40. MAINTAIN_DEPARTMENT,
  41. MAINTAIN_POSITION,
  42. MAINTAIN_SALARY,
  43. MAINTAIN_TEAM,
  44. MAINTAIN_GROUP,
  45. MAINTAIN_HOLIDAY,
  46. VIEW_DASHBOARD_SELF,
  47. VIEW_DASHBOARD_ALL,
  48. IMPORT_INVOICE,
  49. GENERATE_REPORTS,
  50. VIEW_STAFF_PROFILE,
  51. IMPORT_RECEIPT,
  52. MAINTAIN_TASK_TEMPLATE,
  53. MAINTAIN_TIMESHEET_7DAYS,
  54. VIEW_PROJECT,
  55. MAINTAIN_PROJECT,
  56. DELETE_PROJECT,
  57. MAINTAIN_TIMESHEET_FAST_TIME_ENTRY,
  58. VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING,
  59. MAINTAIN_NORMAL_STAFF_WORKSPACE,
  60. MAINTAIN_MANAGEMENT_STAFF_WORKSPACE,
  61. ] = [
  62. 'MAINTAIN_USER',
  63. 'MAINTAIN_TIMESHEET',
  64. 'VIEW_TASK_TEMPLATE',
  65. 'VIEW_GROUP',
  66. 'VIEW_CLIENT',
  67. 'VIEW_SUBSIDIARY',
  68. 'VIEW_STAFF',
  69. 'VIEW_COMPANY',
  70. 'VIEW_SKILL',
  71. 'VIEW_DEPARTMENT',
  72. 'VIEW_POSITION',
  73. 'VIEW_SALARY',
  74. 'VIEW_TEAM',
  75. 'VIEW_HOLIDAY',
  76. 'MAINTAIN_CLIENT',
  77. 'MAINTAIN_SUBSIDIARY',
  78. 'MAINTAIN_STAFF',
  79. 'MAINTAIN_COMPANY',
  80. 'MAINTAIN_SKILL',
  81. 'MAINTAIN_DEPARTMENT',
  82. 'MAINTAIN_POSITION',
  83. 'MAINTAIN_SALARY',
  84. 'MAINTAIN_TEAM',
  85. 'MAINTAIN_GROUP',
  86. 'MAINTAIN_HOLIDAY',
  87. 'VIEW_DASHBOARD_SELF',
  88. 'VIEW_DASHBOARD_ALL',
  89. 'IMPORT_INVOICE',
  90. 'GENERATE_REPORTS',
  91. 'VIEW_STAFF_PROFILE',
  92. 'IMPORT_RECEIPT',
  93. 'MAINTAIN_TASK_TEMPLATE',
  94. 'MAINTAIN_TIMESHEET_7DAYS',
  95. 'VIEW_PROJECT',
  96. 'MAINTAIN_PROJECT',
  97. 'DELETE_PROJECT',
  98. 'MAINTAIN_TIMESHEET_FAST_TIME_ENTRY',
  99. 'VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING',
  100. 'MAINTAIN_NORMAL_STAFF_WORKSPACE',
  101. 'MAINTAIN_MANAGEMENT_STAFF_WORKSPACE'
  102. ]
  103. const PRIVATE_ROUTES = [
  104. "/analytics",
  105. "/dashboard",
  106. // "/home",
  107. "/invoice",
  108. "/projects",
  109. "/tasks",
  110. "/settings",
  111. "/staffReimbursement",
  112. ];
  113. const LANG_QUERY_PARAM = "lang";
  114. export default async function middleware(
  115. req: NextRequestWithAuth,
  116. event: NextFetchEvent,
  117. ) {
  118. const langPref = req.nextUrl.searchParams.get(LANG_QUERY_PARAM);
  119. // const token = await getToken({ req: req, secret: process.env.SECRET });
  120. if (langPref) {
  121. // Redirect to same url without the lang query param + set cookies
  122. const newUrl = new URL(req.nextUrl);
  123. newUrl.searchParams.delete(LANG_QUERY_PARAM);
  124. const response = NextResponse.redirect(newUrl);
  125. response.cookies.set("i18next", langPref);
  126. return response;
  127. }
  128. const authMiddleware = withAuth({
  129. pages: authOptions.pages,
  130. callbacks: {
  131. authorized: ({ req, token }) => {
  132. let isAuth = Boolean(token);
  133. if (!Boolean(token)) {
  134. return Boolean(token)
  135. }
  136. const abilities = (token!.abilities as ability[]).map((item: ability) => item.actionSubjectCombo);
  137. if (req.nextUrl.pathname.startsWith('/projects')) {
  138. isAuth = [MAINTAIN_PROJECT].some((ability) => abilities.includes(ability));
  139. }
  140. if (req.nextUrl.pathname.startsWith('/tasks')) {
  141. isAuth = [MAINTAIN_TASK_TEMPLATE].some((ability) => abilities.includes(ability));
  142. }
  143. if (req.nextUrl.pathname.startsWith('/settings')) {
  144. isAuth = [
  145. VIEW_CLIENT,
  146. VIEW_SUBSIDIARY,
  147. VIEW_STAFF,
  148. VIEW_COMPANY,
  149. VIEW_SKILL,
  150. VIEW_DEPARTMENT,
  151. VIEW_POSITION,
  152. VIEW_SALARY,
  153. VIEW_TEAM,
  154. VIEW_GROUP,
  155. VIEW_HOLIDAY,
  156. MAINTAIN_CLIENT,
  157. MAINTAIN_SUBSIDIARY,
  158. MAINTAIN_STAFF,
  159. MAINTAIN_COMPANY,
  160. MAINTAIN_SKILL,
  161. MAINTAIN_DEPARTMENT,
  162. MAINTAIN_POSITION,
  163. MAINTAIN_SALARY,
  164. MAINTAIN_TEAM,
  165. MAINTAIN_GROUP,
  166. MAINTAIN_HOLIDAY
  167. ].some((ability) => abilities.includes(ability));
  168. }
  169. if (req.nextUrl.pathname.startsWith('/settings/customer/create') || req.nextUrl.pathname.startsWith('/settings/customer/edit')) {
  170. isAuth = [MAINTAIN_CLIENT].some((ability) => abilities.includes(ability));
  171. }
  172. if (req.nextUrl.pathname.startsWith('/settings/subsidiary/create') || req.nextUrl.pathname.startsWith('/settings/subsidiary/edit')) {
  173. isAuth = [MAINTAIN_SUBSIDIARY].some((ability) => abilities.includes(ability));
  174. }
  175. if (req.nextUrl.pathname.startsWith('/settings/staff/create') || req.nextUrl.pathname.startsWith('/settings/staff/edit')) {
  176. isAuth = [MAINTAIN_STAFF].some((ability) => abilities.includes(ability));
  177. }
  178. if (req.nextUrl.pathname.startsWith('/settings/company/create') || req.nextUrl.pathname.startsWith('/settings/company/edit')) {
  179. isAuth = [MAINTAIN_COMPANY].some((ability) => abilities.includes(ability));
  180. }
  181. if (req.nextUrl.pathname.startsWith('/settings/skill/create') || req.nextUrl.pathname.startsWith('/settings/skill/edit')) {
  182. isAuth = [MAINTAIN_SKILL].some((ability) => abilities.includes(ability));
  183. }
  184. if (req.nextUrl.pathname.startsWith('/settings/department/create') || req.nextUrl.pathname.startsWith('/settings/department/edit')) {
  185. isAuth = [MAINTAIN_DEPARTMENT].some((ability) => abilities.includes(ability));
  186. }
  187. if (req.nextUrl.pathname.startsWith('/settings/position/create') || req.nextUrl.pathname.startsWith('/settings/position/edit')) {
  188. isAuth = [MAINTAIN_POSITION].some((ability) => abilities.includes(ability));
  189. }
  190. if (req.nextUrl.pathname.startsWith('/settings/team/create') || req.nextUrl.pathname.startsWith('/settings/team/edit')) {
  191. isAuth = [MAINTAIN_TEAM].some((ability) => abilities.includes(ability));
  192. }
  193. if (req.nextUrl.pathname.startsWith('/settings/group/create') || req.nextUrl.pathname.startsWith('/settings/group/edit')) {
  194. isAuth = [MAINTAIN_GROUP].some((ability) => abilities.includes(ability));
  195. }
  196. if (req.nextUrl.pathname.startsWith('/settings/holiday/create') || req.nextUrl.pathname.startsWith('/settings/holiday/edit')) {
  197. isAuth = [MAINTAIN_HOLIDAY].some((ability) => abilities.includes(ability));
  198. }
  199. if (req.nextUrl.pathname.startsWith('/settings/user')) {
  200. isAuth = [MAINTAIN_USER].some((ability) => abilities.includes(ability));
  201. }
  202. if (req.nextUrl.pathname.startsWith('/settings/staff/user')) {
  203. isAuth = [MAINTAIN_USER].some((ability) => abilities.includes(ability));
  204. }
  205. if (req.nextUrl.pathname.startsWith('/analytics')) {
  206. isAuth = [GENERATE_REPORTS].some((ability) => abilities.includes(ability));
  207. }
  208. if (req.nextUrl.pathname.startsWith('/settings/staff/edit')) {
  209. isAuth = [VIEW_STAFF_PROFILE].some((ability) => abilities.includes(ability));
  210. }
  211. if (req.nextUrl.pathname.startsWith('/invoice')) {
  212. isAuth = [IMPORT_INVOICE, IMPORT_RECEIPT].some((ability) => abilities.includes(ability));
  213. }
  214. if (req.nextUrl.pathname.startsWith('/dashboard')) {
  215. isAuth = [VIEW_DASHBOARD_ALL, VIEW_DASHBOARD_SELF].some((ability) => abilities.includes(ability));
  216. }
  217. if (req.nextUrl.pathname.startsWith('/dashboard/ProjectResourceConsumptionRanking')) {
  218. isAuth = [VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING].some((ability) => abilities.includes(ability));
  219. }
  220. return isAuth
  221. }
  222. }
  223. });
  224. // Matcher for using the auth middleware
  225. return PRIVATE_ROUTES.some((route) => req.nextUrl.pathname.startsWith(route))
  226. ? await authMiddleware(req, event) // Let auth middleware handle response
  227. : NextResponse.next(); // Return normal response
  228. }