Files
panel/AUTHORIZATION_IMPLEMENTATION.md
Chop 294d8343d3 feat: Implement user tracking in projects
- Added user tracking features to the projects module, including:
  - Database schema updates to track project creator and assignee.
  - API enhancements for user management and project filtering by user.
  - UI components for user assignment in project forms and listings.
  - New query functions for retrieving users and filtering projects.
  - Security integration with role-based access and authentication requirements.

chore: Create utility scripts for database checks and project testing

- Added scripts to check the structure of the projects table.
- Created tests for project creation and user tracking functionality.
- Implemented API tests to verify project retrieval and user assignment.

fix: Update project creation and update functions to include user tracking

- Modified createProject and updateProject functions to handle user IDs for creator and assignee.
- Ensured that project updates reflect the correct user assignments and timestamps.
2025-06-25 23:08:15 +02:00

951 lines
25 KiB
Markdown

# Authorization Implementation Guide
## Project Overview
This document outlines the implementation strategy for adding authentication and authorization to the Project Management Panel - a Next.js 15 application with SQLite database.
## Current State Analysis (Updated: June 25, 2025)
### ✅ What We Have Implemented
- **Framework**: Next.js 15 with App Router
- **Database**: SQLite with better-sqlite3
- **Authentication**: NextAuth.js v5 with credentials provider
- **User Management**: Complete user CRUD operations with bcrypt password hashing
- **Database Schema**: Users table with roles, audit logs, sessions
- **API Protection**: Middleware system with role-based access control
- **Session Management**: JWT-based sessions with 30-day expiration
- **Security Features**: Account lockout, failed login tracking, password validation
- **UI Components**: Authentication provider, navigation with user context
- **Auth Pages**: Sign-in page implemented
### ✅ What's Protected
- **API Routes**: All major endpoints (projects, contracts, tasks, notes) are protected
- **Role Hierarchy**: admin > project_manager > user > read_only
- **Navigation**: Role-based menu items (admin sees user management)
- **Session Security**: Automatic session management and validation
### 🔄 Partially Implemented
- **Auth Pages**: Sign-in exists, missing sign-out and error pages
- **User Interface**: Basic auth integration, could use more polish
- **Admin Features**: User management backend exists, UI needs completion
- **Audit Logging**: Database schema exists, not fully integrated
### ❌ Still Missing
- Complete user management UI for admins
- Password reset functionality
- Rate limiting implementation
- Enhanced input validation schemas
- CSRF protection
- Security headers middleware
- Comprehensive error handling
- Email notifications
## Recommended Implementation Strategy
### 1. Authentication Solution: NextAuth.js
**Why NextAuth.js?**
- ✅ Native Next.js 15 App Router support
- ✅ Database session management
- ✅ Built-in security features (CSRF, JWT handling)
- ✅ Flexible provider system
- ✅ SQLite adapter available
### 2. Role-Based Access Control (RBAC)
**Proposed User Roles:**
| Role | Permissions | Use Case |
| ------------------- | --------------------------------------- | ----------------------- |
| **Admin** | Full system access, user management | System administrators |
| **Project Manager** | Manage all projects/tasks, view reports | Team leads, supervisors |
| **User** | View/edit assigned projects/tasks | Regular employees |
| **Read-only** | View-only access to data | Clients, stakeholders |
## Implementation Status
### ✅ Phase 1: Foundation Setup - COMPLETED
#### 1.1 Dependencies - ✅ INSTALLED
- NextAuth.js v5 (beta)
- bcryptjs for password hashing
- Zod for validation
- Better-sqlite3 adapter compatibility
#### 1.2 Environment Configuration - ✅ COMPLETED
- `.env.local` configured with NEXTAUTH_SECRET and NEXTAUTH_URL
- Database URL configuration
- Development environment setup
#### 1.3 Database Schema - ✅ IMPLEMENTED
- Users table with roles and security features
- Sessions table for NextAuth.js
- Audit logs table for security tracking
- Proper indexes for performance
#### 1.4 Initial Admin User - ✅ COMPLETED
- `scripts/create-admin.js` script available
- Default admin user: admin@localhost.com / admin123456
### ✅ Phase 2: Authentication Core - COMPLETED
#### 2.1 NextAuth.js Configuration - ✅ IMPLEMENTED
- **File**: `src/lib/auth.js`
- Credentials provider with email/password
- JWT session strategy with 30-day expiration
- Account lockout after 5 failed attempts (15-minute lockout)
- Password verification with bcrypt
- Failed login attempt tracking
- Session callbacks for role management
#### 2.2 API Route Handlers - ✅ IMPLEMENTED
- **File**: `src/app/api/auth/[...nextauth]/route.js`
- NextAuth.js handlers properly configured
#### 2.3 User Management System - ✅ IMPLEMENTED
- **File**: `src/lib/userManagement.js`
- Complete CRUD operations for users
- Password hashing and validation
- Role management functions
- User lookup by ID and email
### ✅ Phase 3: Authorization Middleware - COMPLETED
#### 3.1 API Protection Middleware - ✅ IMPLEMENTED
- **File**: `src/lib/middleware/auth.js`
- `withAuth()` function for protecting routes
- Role hierarchy enforcement (admin=4, project_manager=3, user=2, read_only=1)
- Helper functions: `withReadAuth`, `withUserAuth`, `withAdminAuth`, `withManagerAuth`
- Proper error handling and status codes
#### 3.2 Protected API Routes - ✅ IMPLEMENTED
Example in `src/app/api/projects/route.js`:
- GET requests require read_only access
- POST requests require user access
- All major API endpoints are protected
#### 3.3 Session Provider - ✅ IMPLEMENTED
- **File**: `src/components/auth/AuthProvider.js`
- NextAuth SessionProvider wrapper
- Integrated into root layout
### 🔄 Phase 4: User Interface - PARTIALLY COMPLETED
#### 4.1 Authentication Pages - 🔄 PARTIAL
-**Sign-in page**: `src/app/auth/signin/page.js` - Complete with form validation
-**Sign-out page**: Missing
- 🔄 **Error page**: `src/app/auth/error/page.js` - Basic implementation
-**Unauthorized page**: Missing
#### 4.2 Navigation Updates - ✅ COMPLETED
- **File**: `src/components/ui/Navigation.js`
- User session integration with useSession
- Role-based menu items (admin sees user management)
- Sign-out functionality
- Conditional rendering based on auth status
#### 4.3 User Management Interface - ❌ MISSING
- Backend exists in userManagement.js
- Admin UI for user CRUD operations needed
- Role assignment interface needed
### ❌ Phase 5: Security Enhancements - NOT STARTED
#### 5.1 Input Validation Schemas - ❌ MISSING
- Zod schemas for API endpoints
- Request validation middleware
#### 5.2 Rate Limiting - ❌ MISSING
- Rate limiting middleware
- IP-based request tracking
#### 5.3 Security Headers - ❌ MISSING
- CSRF protection
- Security headers middleware
- Content Security Policy
```javascript
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { BetterSQLite3Adapter } from "@auth/better-sqlite3-adapter";
import db from "./db.js";
import bcrypt from "bcryptjs";
import { z } from "zod";
const loginSchema = z.object({
email: z.string().email("Invalid email format"),
password: z.string().min(6, "Password must be at least 6 characters"),
});
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: BetterSQLite3Adapter(db),
session: {
strategy: "database",
maxAge: 30 * 24 * 60 * 60, // 30 days
updateAge: 24 * 60 * 60, // 24 hours
},
providers: [
CredentialsProvider({
name: "credentials",
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" },
},
async authorize(credentials, req) {
try {
// Validate input
const validatedFields = loginSchema.parse(credentials);
// Check if user exists and is active
const user = db
.prepare(
`
SELECT id, email, name, password_hash, role, is_active,
failed_login_attempts, locked_until
FROM users
WHERE email = ? AND is_active = 1
`
)
.get(validatedFields.email);
if (!user) {
throw new Error("Invalid credentials");
}
// Check if account is locked
if (user.locked_until && new Date(user.locked_until) > new Date()) {
throw new Error("Account temporarily locked");
}
// Verify password
const isValidPassword = await bcrypt.compare(
validatedFields.password,
user.password_hash
);
if (!isValidPassword) {
// Increment failed attempts
db.prepare(
`
UPDATE users
SET failed_login_attempts = failed_login_attempts + 1,
locked_until = CASE
WHEN failed_login_attempts >= 4
THEN datetime('now', '+15 minutes')
ELSE locked_until
END
WHERE id = ?
`
).run(user.id);
throw new Error("Invalid credentials");
}
// Reset failed attempts and update last login
db.prepare(
`
UPDATE users
SET failed_login_attempts = 0,
locked_until = NULL,
last_login = CURRENT_TIMESTAMP
WHERE id = ?
`
).run(user.id);
// Log successful login
logAuditEvent(user.id, "LOGIN_SUCCESS", "user", user.id, req);
return {
id: user.id,
email: user.email,
name: user.name,
role: user.role,
};
} catch (error) {
console.error("Login error:", error);
return null;
}
},
}),
],
callbacks: {
async jwt({ token, user, account }) {
if (user) {
token.role = user.role;
token.userId = user.id;
}
return token;
},
async session({ session, token, user }) {
if (token) {
session.user.id = token.userId || token.sub;
session.user.role = token.role || user?.role;
}
return session;
},
async signIn({ user, account, profile, email, credentials }) {
// Additional sign-in logic if needed
return true;
},
},
pages: {
signIn: "/auth/signin",
signOut: "/auth/signout",
error: "/auth/error",
},
events: {
async signOut({ session, token }) {
if (session?.user?.id) {
logAuditEvent(session.user.id, "LOGOUT", "user", session.user.id);
}
},
},
});
// Audit logging helper
function logAuditEvent(userId, action, resourceType, resourceId, req = null) {
try {
db.prepare(
`
INSERT INTO audit_logs (user_id, action, resource_type, resource_id, ip_address, user_agent)
VALUES (?, ?, ?, ?, ?, ?)
`
).run(
userId,
action,
resourceType,
resourceId,
req?.ip || "unknown",
req?.headers?.["user-agent"] || "unknown"
);
} catch (error) {
console.error("Audit log error:", error);
}
}
```
#### 2.2 API Route Handlers
Create `src/app/api/auth/[...nextauth]/route.js`:
```javascript
import { handlers } from "@/lib/auth";
export const { GET, POST } = handlers;
```
### Phase 3: Authorization Middleware
#### 3.1 API Protection Middleware
Create `src/lib/middleware/auth.js`:
```javascript
import { auth } from "@/lib/auth";
import { NextResponse } from "next/server";
import { z } from "zod";
// Role hierarchy for permission checking
const ROLE_HIERARCHY = {
admin: 4,
project_manager: 3,
user: 2,
read_only: 1,
};
export function withAuth(handler, options = {}) {
return async (req, context) => {
try {
const session = await auth();
// Check if user is authenticated
if (!session?.user) {
return NextResponse.json(
{ error: "Authentication required" },
{ status: 401 }
);
}
// Check if user account is active
const user = db
.prepare("SELECT is_active FROM users WHERE id = ?")
.get(session.user.id);
if (!user?.is_active) {
return NextResponse.json(
{ error: "Account deactivated" },
{ status: 403 }
);
}
// Check role-based permissions
if (
options.requiredRole &&
!hasPermission(session.user.role, options.requiredRole)
) {
logAuditEvent(
session.user.id,
"ACCESS_DENIED",
options.resource || "api",
req.url
);
return NextResponse.json(
{ error: "Insufficient permissions" },
{ status: 403 }
);
}
// Check resource-specific permissions
if (options.checkResourceAccess) {
const hasAccess = await options.checkResourceAccess(
session.user,
context.params
);
if (!hasAccess) {
return NextResponse.json(
{ error: "Access denied to this resource" },
{ status: 403 }
);
}
}
// Validate request body if schema provided
if (
options.bodySchema &&
(req.method === "POST" ||
req.method === "PUT" ||
req.method === "PATCH")
) {
try {
const body = await req.json();
options.bodySchema.parse(body);
} catch (error) {
return NextResponse.json(
{ error: "Invalid request data", details: error.errors },
{ status: 400 }
);
}
}
// Add user info to request
req.user = session.user;
req.session = session;
// Call the original handler
return await handler(req, context);
} catch (error) {
console.error("Auth middleware error:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 }
);
}
};
}
export function hasPermission(userRole, requiredRole) {
return ROLE_HIERARCHY[userRole] >= ROLE_HIERARCHY[requiredRole];
}
// Helper for read-only operations
export function withReadAuth(handler) {
return withAuth(handler, { requiredRole: "read_only" });
}
// Helper for user-level operations
export function withUserAuth(handler) {
return withAuth(handler, { requiredRole: "user" });
}
// Helper for project manager operations
export function withManagerAuth(handler) {
return withAuth(handler, { requiredRole: "project_manager" });
}
// Helper for admin operations
export function withAdminAuth(handler) {
return withAuth(handler, { requiredRole: "admin" });
}
```
#### 3.2 Client-Side Route Protection
Create `src/components/auth/ProtectedRoute.js`:
```javascript
"use client";
import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
export function ProtectedRoute({
children,
requiredRole = null,
fallback = null,
}) {
const { data: session, status } = useSession();
const router = useRouter();
useEffect(() => {
if (status === "loading") return; // Still loading
if (!session) {
router.push("/auth/signin");
return;
}
if (requiredRole && !hasPermission(session.user.role, requiredRole)) {
router.push("/unauthorized");
return;
}
}, [session, status, router, requiredRole]);
if (status === "loading") {
return (
<div className="flex justify-center items-center h-64">Loading...</div>
);
}
if (!session) {
return fallback || <div>Redirecting to login...</div>;
}
if (requiredRole && !hasPermission(session.user.role, requiredRole)) {
return fallback || <div>Access denied</div>;
}
return children;
}
function hasPermission(userRole, requiredRole) {
const roleHierarchy = {
admin: 4,
project_manager: 3,
user: 2,
read_only: 1,
};
return roleHierarchy[userRole] >= roleHierarchy[requiredRole];
}
```
### Phase 4: User Interface Components
#### 4.1 Authentication Pages
Pages to create:
- `src/app/auth/signin/page.js` - Login form
- `src/app/auth/signout/page.js` - Logout confirmation
- `src/app/auth/error/page.js` - Error handling
- `src/app/unauthorized/page.js` - Access denied page
#### 4.2 Navigation Updates
Update `src/components/ui/Navigation.js` to include:
- Login/logout buttons
- User info display
- Role-based menu items
#### 4.3 User Management Interface
For admin users:
- User listing and management
- Role assignment
- Account activation/deactivation
### Phase 5: Security Enhancements
#### 5.1 Input Validation Schemas
Create `src/lib/schemas/` with Zod schemas for all API endpoints:
```javascript
// src/lib/schemas/project.js
import { z } from "zod";
export const createProjectSchema = z.object({
contract_id: z.number().int().positive(),
project_name: z.string().min(1).max(255),
project_number: z.string().min(1).max(50),
address: z.string().optional(),
// ... other fields
});
export const updateProjectSchema = createProjectSchema.partial();
```
#### 5.2 Rate Limiting
Implement rate limiting for sensitive endpoints:
```javascript
// src/lib/middleware/rateLimit.js
const attempts = new Map();
export function withRateLimit(
handler,
options = { maxAttempts: 5, windowMs: 15 * 60 * 1000 }
) {
return async (req, context) => {
const key = req.ip || "unknown";
const now = Date.now();
const window = attempts.get(key) || {
count: 0,
resetTime: now + options.windowMs,
};
if (now > window.resetTime) {
window.count = 1;
window.resetTime = now + options.windowMs;
} else {
window.count++;
}
attempts.set(key, window);
if (window.count > options.maxAttempts) {
return NextResponse.json({ error: "Too many requests" }, { status: 429 });
}
return handler(req, context);
};
}
```
## Implementation Checklist (Updated Status)
### ✅ Phase 1: Foundation - COMPLETED
- [x] Install dependencies (NextAuth.js v5, bcryptjs, zod)
- [x] Create environment configuration (.env.local)
- [x] Extend database schema (users, sessions, audit_logs)
- [x] Create initial admin user script
### ✅ Phase 2: Authentication - COMPLETED
- [x] Configure NextAuth.js with credentials provider
- [x] Create API route handlers (/api/auth/[...nextauth])
- [x] Implement user management system
- [x] Test login/logout functionality
### ✅ Phase 3: Authorization - COMPLETED
- [x] Implement API middleware (withAuth, role hierarchy)
- [x] Protect existing API routes (projects, contracts, tasks, notes)
- [x] Create role-based helper functions
- [x] Integrate session provider in app layout
### 🔄 Phase 4: User Interface - IN PROGRESS
- [x] Create sign-in page with form validation
- [x] Update navigation component with auth integration
- [x] Add role-based menu items
- [ ] Create sign-out confirmation page
- [ ] Create error handling page
- [ ] Create unauthorized access page
- [ ] Build admin user management interface
### ❌ Phase 5: Security Enhancements - NOT STARTED
- [ ] Add input validation schemas to all endpoints
- [ ] Implement rate limiting for sensitive operations
- [ ] Add comprehensive audit logging
- [ ] Create security headers middleware
- [ ] Implement CSRF protection
- [ ] Add password reset functionality
## Current Working Features
### 🔐 Authentication System
- **Login/Logout**: Fully functional with NextAuth.js
- **Session Management**: JWT-based with 30-day expiration
- **Password Security**: bcrypt hashing with salt rounds
- **Account Lockout**: 5 failed attempts = 15-minute lockout
- **Role System**: 4-tier hierarchy (admin, project_manager, user, read_only)
### 🛡️ Authorization System
- **API Protection**: All major endpoints require authentication
- **Role-Based Access**: Different permission levels per endpoint
- **Middleware**: Clean abstraction with helper functions
- **Session Validation**: Automatic session verification
### 📱 User Interface
- **Navigation**: Context-aware with user info and sign-out
- **Auth Pages**: Professional sign-in form with error handling
- **Role Integration**: Admin users see additional menu items
- **Responsive**: Works across device sizes
### 🗄️ Database Security
- **User Management**: Complete CRUD with proper validation
- **Audit Schema**: Ready for comprehensive logging
- **Indexes**: Optimized for performance
- **Constraints**: Role validation and data integrity
## Next Priority Tasks
1. **Complete Auth UI** (High Priority)
- Sign-out confirmation page
- Unauthorized access page
- Enhanced error handling
2. **Admin User Management** (High Priority)
- User listing interface
- Create/edit user forms
- Role assignment controls
3. **Security Enhancements** (Medium Priority)
- Input validation schemas
- Rate limiting middleware
- Comprehensive audit logging
4. **Password Management** (Medium Priority)
- Password reset functionality
- Password strength requirements
- Password change interface
## User Tracking in Projects - NEW FEATURE ✅
### 📊 Project User Management Implementation
We've successfully implemented comprehensive user tracking for projects:
#### Database Schema Updates ✅
- **created_by**: Tracks who created the project (user ID)
- **assigned_to**: Tracks who is assigned to work on the project (user ID)
- **created_at**: Timestamp when project was created
- **updated_at**: Timestamp when project was last modified
- **Indexes**: Performance optimized with proper foreign key indexes
#### API Enhancements ✅
- **Enhanced Queries**: Projects now include user names and emails via JOIN operations
- **User Assignment**: New `/api/projects/users` endpoint for user management
- **Query Filters**: Support for filtering projects by assigned user or creator
- **User Context**: Create/update operations automatically capture authenticated user ID
#### UI Components ✅
- **Project Form**: User assignment dropdown in create/edit forms
- **Project Listing**: "Created By" and "Assigned To" columns in project table
- **User Selection**: Dropdown populated with active users for assignment
#### New Query Functions ✅
- `getAllUsersForAssignment()`: Get active users for assignment dropdown
- `getProjectsByAssignedUser(userId)`: Filter projects by assignee
- `getProjectsByCreator(userId)`: Filter projects by creator
- `updateProjectAssignment(projectId, userId)`: Update project assignment
#### Security Integration ✅
- **Authentication Required**: All user operations require valid session
- **Role-Based Access**: User assignment respects role hierarchy
- **Audit Ready**: Infrastructure prepared for comprehensive user action logging
### Usage Examples
#### Creating Projects with User Tracking
```javascript
// Projects are automatically assigned to the authenticated user as creator
POST /api/projects
{
"project_name": "New Project",
"assigned_to": "user-id-here", // Optional assignment
// ... other project data
}
```
#### Filtering Projects by User
```javascript
// Get projects assigned to specific user
GET /api/projects?assigned_to=user-id
// Get projects created by specific user
GET /api/projects?created_by=user-id
```
#### Updating Project Assignment
```javascript
POST /api/projects/users
{
"projectId": 123,
"assignedToUserId": "new-user-id"
}
```
### Next Enhancements
1. **Dashboard Views** (Recommended)
- "My Projects" dashboard showing assigned projects
- Project creation history per user
- Workload distribution reports
2. **Advanced Filtering** (Future)
- Multi-user assignment support
- Team-based project assignments
- Role-based project visibility
3. **Notifications** (Future)
- Email alerts on project assignment
- Deadline reminders for assigned users
- Status change notifications
## Security Best Practices
### 1. Password Security
- Minimum 8 characters
- Require special characters, numbers
- Hash with bcrypt (cost factor 12+)
- Implement password history
### 2. Session Security
- Secure cookies
- Session rotation
- Timeout handling
- Device tracking
### 3. API Security
- Input validation on all endpoints
- SQL injection prevention (prepared statements)
- XSS protection
- CSRF tokens
### 4. Audit & Monitoring
- Log all authentication events
- Monitor failed login attempts
- Track permission changes
- Alert on suspicious activity
## Testing Status
### ✅ Completed Tests
- **Authentication Flow**: Login/logout working correctly
- **API Protection**: All endpoints properly secured
- **Role Validation**: Permission levels enforced
- **Session Management**: JWT tokens and expiration working
- **Password Security**: bcrypt hashing and verification functional
- **Account Lockout**: Failed attempt tracking and temporary lockout
### 🔧 Available Test Scripts
- `test-auth.mjs` - Tests API route protection and auth endpoints
- `test-auth-detailed.mjs` - Comprehensive authentication flow testing
- `test-complete-auth.mjs` - Full system authentication validation
- `test-logged-in-flow.mjs` - Authenticated user session testing
### ✅ Verified Security Features
- Unauthorized API requests return 401
- Role-based access control working
- Session tokens properly validated
- Password attempts tracked and limited
- Admin user creation and management functional
## Deployment Considerations
### 1. Environment Variables
- Use strong, random secrets
- Different keys per environment
- Secure secret management
### 2. Database Security
- Regular backups
- Encryption at rest
- Network security
- Access logging
### 3. Application Security
- HTTPS enforcement
- Security headers
- Content Security Policy
- Regular security updates
## Migration Strategy
### 1. Development Phase
- Implement on development branch
- Test thoroughly with sample data
- Document all changes
### 2. Staging Deployment
- Deploy to staging environment
- Performance testing
- Security testing
- User acceptance testing
### 3. Production Deployment
- Database backup before migration
- Gradual rollout
- Monitor for issues
- Rollback plan ready
## Resources and Documentation
### NextAuth.js
- [Official Documentation](https://next-auth.js.org/)
- [Better SQLite3 Adapter](https://authjs.dev/reference/adapter/better-sqlite3)
### Security Libraries
- [Zod Validation](https://zod.dev/)
- [bcryptjs](https://www.npmjs.com/package/bcryptjs)
### Best Practices
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [Next.js Security Guidelines](https://nextjs.org/docs/advanced-features/security-headers)
---
**Next Steps**: Choose which phase to implement first and create detailed implementation tickets for development.