Production deployment with Docker and full system fixes

- Added Docker support (Dockerfiles, docker-compose.yml)
- Fixed authentication and authorization (token storage, CORS, permissions)
- Fixed API response transformations for all modules
- Added production deployment scripts and guides
- Fixed frontend permission checks and module access
- Added database seeding script for production
- Complete documentation for deployment and configuration

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Talal Sharabi
2026-02-11 11:25:20 +04:00
parent 35daa52767
commit f31d71ff5a
52 changed files with 9359 additions and 1578 deletions

View File

@@ -3,6 +3,8 @@
import React, { createContext, useContext, useState, useEffect } from 'react'
import { useRouter } from 'next/navigation'
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5001/api/v1'
interface User {
id: string
employeeId: string
@@ -20,12 +22,13 @@ interface User {
interface Permission {
id: string
module: string
canView: boolean
canCreate: boolean
canEdit: boolean
canDelete: boolean
canExport: boolean
canApprove: boolean
actions?: string[]
canView?: boolean
canCreate?: boolean
canEdit?: boolean
canDelete?: boolean
canExport?: boolean
canApprove?: boolean
}
interface AuthContextType {
@@ -46,7 +49,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
// Check for existing token on mount
useEffect(() => {
const token = localStorage.getItem('token')
const token = localStorage.getItem('accessToken')
if (token) {
// Verify token and get user data
fetchUserData(token)
@@ -55,9 +58,24 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
}
}, [])
// Transform backend permissions format to frontend format
const transformPermissions = (permissions: any[]): Permission[] => {
return permissions.map(p => ({
id: p.id,
module: p.module,
actions: p.actions,
canView: p.actions?.includes('read') || false,
canCreate: p.actions?.includes('create') || false,
canEdit: p.actions?.includes('update') || false,
canDelete: p.actions?.includes('delete') || false,
canExport: p.actions?.includes('export') || false,
canApprove: p.actions?.includes('approve') || false,
}))
}
const fetchUserData = async (token: string) => {
try {
const response = await fetch('http://localhost:5001/api/v1/auth/me', {
const response = await fetch(`${API_URL}/auth/me`, {
headers: {
'Authorization': `Bearer ${token}`
}
@@ -65,13 +83,17 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
if (response.ok) {
const userData = await response.json()
setUser(userData.data)
const user = userData.data
if (user.role?.permissions) {
user.role.permissions = transformPermissions(user.role.permissions)
}
setUser(user)
} else {
localStorage.removeItem('token')
localStorage.removeItem('accessToken')
}
} catch (error) {
console.error('Failed to fetch user data:', error)
localStorage.removeItem('token')
localStorage.removeItem('accessToken')
} finally {
setIsLoading(false)
}
@@ -79,7 +101,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
const login = async (email: string, password: string) => {
try {
const response = await fetch('http://localhost:5001/api/v1/auth/login', {
const response = await fetch(`${API_URL}/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@@ -94,10 +116,15 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
}
// Store token
localStorage.setItem('token', data.data.accessToken)
localStorage.setItem('accessToken', data.data.accessToken)
localStorage.setItem('refreshToken', data.data.refreshToken)
// Set user data
setUser(data.data.user)
// Transform permissions and set user data
const userData = data.data.user
if (userData.role?.permissions) {
userData.role.permissions = transformPermissions(userData.role.permissions)
}
setUser(userData)
// Redirect to dashboard
router.push('/dashboard')
@@ -107,7 +134,8 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
}
const logout = () => {
localStorage.removeItem('token')
localStorage.removeItem('accessToken')
localStorage.removeItem('refreshToken')
setUser(null)
router.push('/')
}