EDMS/docs/Technical_Guide.md
2025-05-30 21:08:11 +08:00

29 KiB

Electronic Document Management System (EDMS) - Technical Guide

Table of Contents

  1. System Overview
  2. Architecture
  3. Technology Stack
  4. Database Schema
  5. Installation & Setup
  6. Development Environment
  7. Component Structure
  8. API & Data Management
  9. Security & Authentication
  10. Deployment
  11. Maintenance & Monitoring
  12. Extension & Customization

System Overview

The Electronic Document Management System (EDMS) is a modern web application built with Nuxt.js 3 and Vue.js 3, designed to provide a comprehensive document management solution for organizations. The system implements a hierarchical document organization structure with role-based access control (RBAC) and supports integration with external authentication providers like Authentik.

Key Technical Features

  • Modern Frontend: Vue.js 3 with Composition API and script setup syntax
  • SSR/SPA Support: Nuxt.js 3 for optimal performance and SEO
  • Database: Prisma ORM with MySQL/PostgreSQL support and migrations
  • Styling: TailwindCSS with custom component system
  • State Management: Pinia for reactive state management with persistence
  • Authentication: Flexible authentication with JWT tokens and RBAC
  • File Management: Server-side file handling with metadata and versioning
  • Real-time Features: Vue reactivity for live updates and notifications
  • Responsive Design: Mobile-first approach with adaptive layouts

Architecture

System Architecture

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Frontend      │    │   Backend       │    │   Database      │
│   (Nuxt.js)     │◄──►│   (Server API)  │◄──►│   (MySQL/PG)    │
│                 │    │                 │    │                 │
│ • Vue.js 3      │    │ • Prisma ORM    │    │ • User Data     │
│ • TailwindCSS   │    │ • File System   │    │ • Documents     │
│ • Pinia Store   │    │ • Authentication│    │ • Permissions   │
│ • Components    │    │ • API Routes    │    │ • Audit Logs    │
└─────────────────┘    └─────────────────┘    └─────────────────┘
        │                       │                       │
        │              ┌─────────────────┐             │
        │              │ File Storage    │             │
        └──────────────►│ • Documents     │◄────────────┘
                       │ • Versions      │
                       │ • Thumbnails    │
                       │ • Temp Files    │
                       └─────────────────┘

Application Flow

  1. Authentication: User authenticates via configured authentication provider
  2. Authorization: System validates user permissions against RBAC rules
  3. Navigation: User navigates document hierarchy with tree-based structure
  4. Data Fetching: Pinia store manages API calls with caching and error handling
  5. Rendering: Vue components render UI with reactive updates
  6. File Operations: Server handles secure file upload/download/preview
  7. Access Control: System enforces granular document permissions
  8. Audit Trail: All actions are logged for compliance and security

Technology Stack

Frontend Dependencies

{
  "core": {
    "nuxt": "^3.6.5",
    "vue": "^3.x",
    "@pinia/nuxt": "^0.4.11",
    "@pinia-plugin-persistedstate/nuxt": "^1.1.1"
  },
  "styling": {
    "@nuxtjs/tailwindcss": "^6.8.0",
    "sass": "^1.62.0",
    "postcss-import": "^15.1.0"
  },
  "forms": {
    "@formkit/nuxt": "^1.0.0",
    "@formkit/themes": "^1.0.0",
    "@formkit/addons": "^1.0.0",
    "@formkit/pro": "^0.115.3"
  },
  "ui": {
    "apexcharts": "^3.36.0",
    "vue3-apexcharts": "^1.4.1",
    "@vueuse/core": "^9.5.0",
    "@vueuse/nuxt": "^9.5.0",
    "floating-vue": "^2.0.0-beta.24",
    "vue3-dropzone": "^2.0.1"
  },
  "utilities": {
    "luxon": "^3.1.0",
    "uuid": "^10.0.0",
    "crypto-js": "^4.1.1",
    "@shimyshack/uid": "^0.1.7"
  }
}

Backend Dependencies

{
  "database": {
    "@prisma/client": "^5.1.1",
    "prisma": "^5.1.1"
  },
  "authentication": {
    "jsonwebtoken": "^8.5.1"
  },
  "file-handling": {
    "jspdf": "^2.5.1"
  },
  "security": {
    "nuxt-security": "^0.13.0"
  }
}

Development Tools

  • ESLint: Code linting with Vue.js specific rules
  • TypeScript: Type safety with Nuxt TypeScript integration
  • Prettier: Consistent code formatting
  • Vite: Lightning-fast build tool and HMR
  • PostCSS: Advanced CSS processing with plugins

Database Schema

Core Models

User Management

model user {
  userID           Int                @id @default(autoincrement())
  userSecretKey    String?            @db.VarChar(255)
  userUsername     String?            @unique @db.VarChar(255)
  userPassword     String?            @db.VarChar(255)
  userFullName     String?            @db.VarChar(255)
  userEmail        String?            @unique @db.VarChar(255)
  userPhone        String?            @db.VarChar(255)
  userStatus       String?            @db.VarChar(255)
  userCreatedDate  DateTime?          @default(now()) @db.DateTime(0)
  userModifiedDate DateTime?          @updatedAt @db.DateTime(0)
  
  // Relationships
  userrole         userrole[]
  accessRequests   AccessRequest[]
  permissions      AccessPermission[]
  documents        Document[]         @relation("DocumentCreator")
  cabinets         Cabinet[]          @relation("CabinetCreator")
  drawers          Drawer[]           @relation("DrawerCreator")
  folders          Folder[]           @relation("FolderCreator")
  subfolders       Subfolder[]        @relation("SubfolderCreator")
}

model role {
  roleID              Int                @id @default(autoincrement())
  roleName            String             @unique @db.VarChar(255)
  roleDescription     String?            @db.Text
  rolePermissions     Json?              // Flexible permissions structure
  roleCreatedDate     DateTime           @default(now()) @db.DateTime(0)
  roleModifiedDate    DateTime           @updatedAt @db.DateTime(0)
  
  userrole            userrole[]
  permissions         AccessPermission[]
}

Document Hierarchy

// Cabinet → Drawer → Folder → Subfolder → Document

model Cabinet {
  id          Int        @id @default(autoincrement())
  name        String     @db.VarChar(255)
  description String?    @db.Text
  metadata    Json?      // Flexible metadata storage
  createdAt   DateTime   @default(now()) @db.DateTime(0)
  updatedAt   DateTime   @updatedAt @db.DateTime(0)
  createdBy   Int
  status      String     @default("active") @db.VarChar(50)
  
  user        user       @relation("CabinetCreator", fields: [createdBy], references: [userID])
  drawers     Drawer[]
  permissions AccessPermission[]
  
  @@index([createdBy])
  @@index([status])
}

model Document {
  id              Int        @id @default(autoincrement())
  name            String     @db.VarChar(255)
  description     String?    @db.Text
  fileSize        Int        @default(0)
  fileType        String     @db.VarChar(100)
  fileExtension   String     @db.VarChar(20)
  filePath        String     @db.VarChar(500)
  thumbnailPath   String?    @db.VarChar(500)
  checksum        String?    @db.VarChar(64)
  version         Int        @default(1)
  isTemplate      Boolean    @default(false)
  isPublic        Boolean    @default(false)
  metadata        Json?      // Custom metadata fields
  tags            String?    @db.Text
  folderId        Int?
  subfolderId     Int?
  createdAt       DateTime   @default(now()) @db.DateTime(0)
  updatedAt       DateTime   @updatedAt @db.DateTime(0)
  createdBy       Int
  status          String     @default("active") @db.VarChar(50)
  
  folder          Folder?    @relation("FolderDocuments", fields: [folderId], references: [id], onDelete: SetNull)
  subfolder       Subfolder? @relation("SubfolderDocuments", fields: [subfolderId], references: [id], onDelete: SetNull)
  user            user       @relation("DocumentCreator", fields: [createdBy], references: [userID])
  accessRequests  AccessRequest[]
  permissions     AccessPermission[]
  versions        DocumentVersion[]
  
  @@index([folderId])
  @@index([subfolderId])
  @@index([createdBy])
  @@index([fileType])
  @@index([status])
  @@fulltext([name, description, tags])
}

Access Control & Workflow

model AccessPermission {
  id              Int       @id @default(autoincrement())
  userId          Int?
  roleId          Int?
  documentId      Int?
  cabinetId       Int?
  drawerId        Int?
  folderId        Int?
  subfolderId     Int?
  permissionLevel String    @db.VarChar(50) // view, download, print, edit, full, admin
  conditions      Json?     // Additional permission conditions
  createdAt       DateTime  @default(now()) @db.DateTime(0)
  updatedAt       DateTime  @updatedAt @db.DateTime(0)
  expiresAt       DateTime? @db.DateTime(0)
  createdBy       Int?
  
  user            user?     @relation(fields: [userId], references: [userID], onDelete: SetNull)
  role            role?     @relation(fields: [roleId], references: [roleID], onDelete: SetNull)
  document        Document? @relation(fields: [documentId], references: [id], onDelete: Cascade)
  cabinet         Cabinet?  @relation(fields: [cabinetId], references: [id], onDelete: Cascade)
  drawer          Drawer?   @relation(fields: [drawerId], references: [id], onDelete: Cascade)
  folder          Folder?   @relation(fields: [folderId], references: [id], onDelete: Cascade)
  subfolder       Subfolder? @relation(fields: [subfolderId], references: [id], onDelete: Cascade)
  
  @@index([userId])
  @@index([roleId])
  @@index([documentId])
  @@index([expiresAt])
}

model AccessRequest {
  id              Int       @id @default(autoincrement())
  documentId      Int
  userId          Int
  requestedLevel  String    @db.VarChar(50) // view, download, print, edit, full
  duration        String?   @db.VarChar(50) // 7d, 14d, 30d, 60d, 90d, permanent
  justification   String?   @db.Text
  status          String    @default("pending") @db.VarChar(50) // pending, approved, rejected, expired
  responseNote    String?   @db.Text
  requestedAt     DateTime  @default(now()) @db.DateTime(0)
  respondedAt     DateTime? @db.DateTime(0)
  respondedBy     Int?
  expiresAt       DateTime? @db.DateTime(0)
  
  document        Document  @relation(fields: [documentId], references: [id], onDelete: Cascade)
  user            user      @relation(fields: [userId], references: [userID])
  
  @@index([documentId])
  @@index([userId])
  @@index([status])
}

Installation & Setup

Prerequisites

  • Node.js 18+ and npm/yarn/pnpm
  • MySQL 8.0+ or PostgreSQL 13+
  • Git for version control
  • Optional: Docker for containerized deployment

Installation Steps

  1. Clone Repository
git clone <repository-url>
cd edms
  1. Install Dependencies
# Using npm
npm install

# Using yarn
yarn install

# Using pnpm
pnpm install
  1. Environment Configuration Create .env file:
# Database Configuration
DATABASE_URL="mysql://username:password@localhost:3306/edms_db"
# For PostgreSQL: DATABASE_URL="postgresql://username:password@localhost:5432/edms_db"

# Authentication
JWT_SECRET="your-jwt-secret-key-min-256-bits"
SESSION_SECRET="your-session-secret-key"

# External Authentication (Optional)
AUTHENTIK_BASE_URL="https://auth.yourdomain.com"
AUTHENTIK_CLIENT_ID="your-client-id"
AUTHENTIK_CLIENT_SECRET="your-client-secret"

# File Storage
UPLOAD_PATH="/var/uploads/edms"
TEMP_PATH="/var/tmp/edms"
MAX_FILE_SIZE="104857600" # 100MB in bytes
ALLOWED_FILE_TYPES="pdf,doc,docx,xls,xlsx,ppt,pptx,txt,jpg,jpeg,png,gif"

# Application Configuration
NUXT_SECRET_KEY="your-nuxt-app-secret"
BASE_URL="http://localhost:3000"
NODE_ENV="development"

# Security
CORS_ORIGIN="http://localhost:3000"
RATE_LIMIT_MAX="100" # requests per window
RATE_LIMIT_WINDOW="15" # minutes

# Monitoring & Logging
LOG_LEVEL="info"
LOG_FILE="/var/log/edms/app.log"
  1. Database Setup
# Generate Prisma client
npx prisma generate

# Run database migrations
npx prisma db push

# Seed initial data (optional)
npx prisma db seed

# View database in Prisma Studio (optional)
npx prisma studio
  1. Development Server
# Start development server
npm run dev

# Access application at http://localhost:3000

Development Environment

Project Structure

edms/
├── components/          # Vue components
│   ├── dms/            # DMS-specific components
│   │   ├── explorer/   # Document explorer interface
│   │   ├── dialogs/    # Modal dialogs and forms
│   │   ├── viewers/    # Document preview components
│   │   └── navigation/ # Tree and breadcrumb navigation
│   ├── layouts/        # Layout components
│   ├── formkit/        # FormKit custom components
│   └── [Rs*].vue       # Reusable UI components (RsButton, RsCard, etc.)
├── pages/              # Nuxt pages (file-based routing)
│   ├── dms/           # DMS-related pages
│   ├── dashboard/     # Dashboard and analytics
│   ├── login/         # Authentication pages
│   └── index.vue      # Homepage
├── stores/            # Pinia state stores
│   ├── dms.js         # Document management store
│   ├── auth.js        # Authentication store
│   └── app.js         # Global application store
├── middleware/        # Route middleware
│   ├── auth.js        # Authentication middleware
│   └── rbac.js        # Role-based access control
├── layouts/           # Nuxt layouts
│   ├── default.vue    # Default application layout
│   └── auth.vue       # Authentication layout
├── server/            # Server-side code
│   ├── api/           # API routes
│   └── middleware/    # Server middleware
├── prisma/            # Database configuration
│   ├── schema.prisma  # Database schema
│   └── migrations/    # Database migrations
├── public/            # Static assets
├── assets/            # Build-time assets
├── plugins/           # Nuxt plugins
├── composables/       # Vue composables
└── utils/             # Utility functions

Component Architecture

Core EDMS Components

  1. DMSExplorer.vue: Main document browser with tree navigation, content views, and details panel
  2. DMSTreeView.vue: Recursive tree navigation for hierarchical structure
  3. DMSDocumentViewer.vue: Multi-format document viewer with zoom and controls
  4. DMSAccessRequestDialog.vue: Access request form with approval workflow
  5. DMSUploadDialog.vue: File upload interface with metadata assignment

Custom UI Components (Rs Prefix)

  • RsButton.vue: Standardized button component with variants
  • RsCard.vue: Container component with consistent styling
  • RsModal.vue: Modal dialog base component
  • RsInput.vue: Standardized input field component
  • RsSelect.vue: Standardized dropdown/select component
  • RsTextarea.vue: Standardized textarea component
  • RsTable.vue: Data table with sorting and filtering
  • RsDropdown.vue: Dropdown menu component

Design System

Overview

The EDMS implements a comprehensive design system built on a standardized component library with the "Rs" prefix (Reusable System). This ensures consistency, maintainability, and accessibility across the entire application.

Design Principles

  • 🎯 Consistency: All components follow unified design patterns and naming conventions
  • 🔧 Modularity: Components are reusable and composable for complex interfaces
  • 🌙 Dark Mode: Universal support for both light and dark themes via CSS variables
  • 📱 Responsive: Mobile-first approach with adaptive layouts
  • Accessibility: WCAG-compliant with proper ARIA attributes and keyboard navigation

Component Library

Form Components

RsInput.vue
<rs-input
  v-model="value"
  label="Field Label"
  placeholder="Enter text..."
  :required="true"
  :error="validationError"
  size="md"
  :disabled="false"
/>

Props:

  • modelValue: String/Number - Input value
  • label: String - Field label
  • placeholder: String - Placeholder text
  • type: String - Input type (text, email, password, etc.)
  • required: Boolean - Required field indicator
  • error: String - Error message
  • size: String - Size variant (sm, md, lg)
  • disabled: Boolean - Disabled state
RsSelect.vue
<rs-select
  v-model="selectedValue"
  :options="optionsList"
  label="Select Option"
  placeholder="Choose..."
  :multiple="false"
  :required="true"
/>

Props:

  • modelValue: String/Number/Array - Selected value(s)
  • options: Array - Options list (objects with value/label or simple strings)
  • label: String - Field label
  • placeholder: String - Placeholder text
  • multiple: Boolean - Multiple selection support
  • required: Boolean - Required field indicator
  • error: String - Error message
  • disabled: Boolean - Disabled state
RsTextarea.vue
<rs-textarea
  v-model="content"
  label="Message"
  placeholder="Enter message..."
  :rows="4"
  resize="vertical"
  :required="true"
/>

Props:

  • modelValue: String - Textarea content
  • label: String - Field label
  • placeholder: String - Placeholder text
  • rows: Number - Number of visible rows
  • resize: String - Resize behavior (none, both, horizontal, vertical)
  • required: Boolean - Required field indicator
  • error: String - Error message
  • disabled: Boolean - Disabled state

UI Components

RsButton.vue
<rs-button
  variant="primary"
  size="md"
  :disabled="false"
  @click="handleClick"
>
  Button Text
</rs-button>

Variants:

  • primary: Blue primary button
  • secondary: Gray secondary button
  • info: Blue info button
  • success: Green success button
  • warning: Yellow warning button
  • danger: Red danger button
  • primary-outline: Outlined primary button
  • secondary-outline: Outlined secondary button
  • primary-text: Text-only primary button

Sizes:

  • sm: Small button (padding: 0.25rem 0.75rem)
  • md: Medium button (padding: 0.5rem 1rem)
  • lg: Large button (padding: 0.75rem 1.25rem)
RsCard.vue
<rs-card>
  <template #header>
    Card Header
  </template>
  <template #body>
    Card content goes here
  </template>
  <template #footer>
    Card footer with actions
  </template>
</rs-card>
RsModal.vue
<rs-modal :visible="showModal" @close="closeModal" size="md">
  <template #header>
    Modal Title
  </template>
  <template #body>
    Modal content
  </template>
  <template #footer>
    <rs-button variant="secondary" @click="closeModal">Cancel</rs-button>
    <rs-button variant="primary" @click="confirm">Confirm</rs-button>
  </template>
</rs-modal>

Sizes:

  • sm: 300px width
  • md: 500px width
  • lg: 800px width
  • xl: 1000px width
  • full: Full screen width

Color System

The design system uses CSS custom properties for consistent theming:

:root {
  /* Primary Colors */
  --color-primary: 59 130 246;    /* Blue */
  --color-secondary: 100 116 139; /* Gray */
  --color-info: 14 165 233;       /* Sky Blue */
  --color-success: 34 197 94;     /* Green */
  --color-warning: 251 191 36;    /* Yellow */
  --color-danger: 239 68 68;      /* Red */
  
  /* Background Colors */
  --bg-1: 248 250 252;            /* Light Gray */
  --bg-2: 255 255 255;            /* White */
  
  /* Text Colors */
  --text-color: 15 23 42;         /* Slate 900 */
  --text-muted: 100 116 139;      /* Slate 500 */
  
  /* Border Colors */
  --border-color: 226 232 240;    /* Slate 200 */
  --fk-border-color: 209 213 219; /* Gray 300 */
}

Typography Scale

/* Font Sizes */
.text-xs    { font-size: 0.75rem; }   /* 12px */
.text-sm    { font-size: 0.875rem; }  /* 14px */
.text-base  { font-size: 1rem; }      /* 16px */
.text-lg    { font-size: 1.125rem; }  /* 18px */
.text-xl    { font-size: 1.25rem; }   /* 20px */
.text-2xl   { font-size: 1.5rem; }    /* 24px */
.text-3xl   { font-size: 1.875rem; }  /* 30px */

/* Font Weights */
.font-light     { font-weight: 300; }
.font-normal    { font-weight: 400; }
.font-medium    { font-weight: 500; }
.font-semibold  { font-weight: 600; }
.font-bold      { font-weight: 700; }

Spacing Scale

/* Spacing (padding/margin) */
.p-1    { padding: 0.25rem; }    /* 4px */
.p-2    { padding: 0.5rem; }     /* 8px */
.p-3    { padding: 0.75rem; }    /* 12px */
.p-4    { padding: 1rem; }       /* 16px */
.p-6    { padding: 1.5rem; }     /* 24px */
.p-8    { padding: 2rem; }       /* 32px */

Usage Guidelines

Best Practices

  1. Always use Rs components for UI elements instead of custom styling
  2. Use semantic variants (primary, secondary, danger) rather than color names
  3. Follow consistent spacing using the predefined scale
  4. Use CSS variables for colors instead of hardcoded values
  5. Test in both themes (light and dark mode)
  6. Maintain accessibility with proper labels and ARIA attributes

Anti-patterns

  1. Don't use manual Tailwind classes for buttons (e.g., px-4 py-2 bg-blue-500)
  2. Don't create custom input styling without extending Rs components
  3. Don't hardcode colors or spacing values
  4. Don't mix different component styling approaches
  5. Don't forget dark mode support in custom components

FormKit Integration

The design system integrates with FormKit for advanced form handling:

// FormKit theme configuration
export default {
  global: {
    label: "formkit-label-global",
    outer: "formkit-outer-global",
    wrapper: "formkit-wrapper-global",
  },
  button: {
    wrapper: "formkit-wrapper-button",
    input: "formkit-input-button",
  },
  text: {
    label: "formkit-outer-text",
    inner: "formkit-inner-text",
    input: "formkit-input-text",
  }
}

Component Registration

All Rs components are globally registered via the component index:

// pages/devtool/code-playground/index.js
export {
  RsAlert,
  RsBadge,
  RsButton,
  RsCard,
  RsInput,
  RsModal,
  RsSelect,
  RsTextarea,
  RsTable,
  // ... other components
};

Design System Documentation

Access the interactive design system documentation at /dms/design-system to:

  • View all components with live examples
  • Test different variants and states
  • Copy code snippets for implementation
  • Understand usage guidelines and best practices

Future Enhancements

Planned design system improvements:

  • Animation Library: Consistent micro-interactions and transitions
  • Icon System: Standardized icon library with consistent sizing
  • Layout Components: Grid and flexbox utilities
  • Advanced Form Components: Date pickers, multi-select, autocomplete
  • Data Visualization: Chart and graph components
  • Notification System: Toast and alert components

API & Data Management

Server API Routes

Document Management

// server/api/dms/documents/[id].get.js
export default defineEventHandler(async (event) => {
  const id = getRouterParam(event, 'id')
  // Fetch document with access control
})

// server/api/dms/upload.post.js
export default defineEventHandler(async (event) => {
  // Handle file upload with validation
})

// server/api/dms/search.get.js
export default defineEventHandler(async (event) => {
  const query = getQuery(event)
  // Perform document search
})

Access Control

// server/api/dms/access-request.post.js
export default defineEventHandler(async (event) => {
  // Process access requests
})

// server/api/dms/permissions/[id].get.js
export default defineEventHandler(async (event) => {
  // Get user permissions for item
})

Data Validation

Prisma Schema Validation

  • Field constraints and types
  • Relationship integrity
  • Index optimization

Frontend Validation

// FormKit validation rules
const documentValidation = {
  title: 'required|length:3,255',
  description: 'length:0,1000',
  fileType: 'required|in:pdf,doc,docx,xls,xlsx,jpg,png',
  accessLevel: 'required|in:public,private,personal'
}

Security & Authentication

Authentication Flow

  1. User Login: Redirect to Authentik
  2. Token Exchange: Receive JWT token
  3. Token Validation: Verify on each request
  4. Session Management: Store in secure cookie
  5. Token Refresh: Automatic renewal

Authorization Levels

  • System Admin: Full system access
  • Department Admin: Department-wide permissions
  • Document Owner: Full access to owned documents
  • User: Access based on granted permissions

File Security

  • Path Traversal Protection: Validate file paths
  • File Type Validation: Whitelist allowed formats
  • Size Limits: Prevent large file uploads
  • Virus Scanning: Optional integration
  • Access Logging: Track file access

Data Protection

  • SQL Injection Prevention: Parameterized queries via Prisma
  • XSS Protection: Input sanitization
  • CSRF Protection: Token validation
  • Secure Headers: Security-focused HTTP headers

Deployment

Production Build

# Build for production
npm run build

# Generate static files (if needed)
npm run generate

# Preview production build
npm run preview

Environment Configuration

Production Environment Variables

NODE_ENV=production
DATABASE_URL="mysql://prod_user:password@db.server:3306/edms_prod"
NUXT_SECRET_KEY="production-secret-key"
BASE_URL="https://dms.jkr-kotabharu.gov.my"

Docker Deployment

FROM node:18-alpine

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

COPY . .
RUN npm run build

EXPOSE 3000
CMD ["npm", "run", "start"]

Nginx Configuration

server {
    listen 80;
    server_name dms.jkr-kotabharu.gov.my;
    
    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    location /uploads/ {
        alias /var/www/uploads/;
        expires 1y;
    }
}

Maintenance & Monitoring

Database Maintenance

-- Regular maintenance queries
OPTIMIZE TABLE document;
ANALYZE TABLE access_permission;

-- Cleanup old access requests
DELETE FROM access_request 
WHERE status = 'rejected' 
AND requested_at < DATE_SUB(NOW(), INTERVAL 30 DAY);

Backup Strategy

  • Database Backups: Daily automated backups
  • File Storage Backups: Incremental file backups
  • Configuration Backups: Version control for configs

Monitoring

  • Application Performance: Response times, error rates
  • Database Performance: Query performance, connection counts
  • File Storage: Disk usage, file integrity
  • Security Events: Failed logins, access violations

Logging

// Server-side logging
import { createLogger } from 'winston'

const logger = createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' })
  ]
})

Extension & Customization

Adding New Document Types

  1. Update Prisma schema with new file types
  2. Add validation rules for the file type
  3. Implement viewer component for the format
  4. Update upload dialog to support the type

Custom Access Control

  1. Extend AccessPermission model
  2. Implement custom permission logic
  3. Update UI to reflect new permissions
  4. Add admin interface for permission management

Integration Points

  • External Authentication: LDAP/Active Directory
  • Document Processing: OCR, text extraction
  • Workflow Systems: Approval workflows
  • Notification Systems: Email/SMS notifications
  • Analytics: Document usage analytics

API Extensions

// Custom API endpoint example
// server/api/custom/analytics.get.js
export default defineEventHandler(async (event) => {
  // Custom analytics logic
  return {
    totalDocuments: count,
    storageUsed: size,
    activeUsers: userCount
  }
})

Theme Customization

// tailwind.config.js extensions
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: {
          50: '#eff6ff',
          500: '#3b82f6',
          900: '#1e3a8a'
        }
      }
    }
  }
}

Document Version: 2.0
Last Updated: December 2024
System Version: EDMS v1.0
Technology Stack: Nuxt.js 3, Vue.js 3, Prisma, TailwindCSS
Database: MySQL/PostgreSQL
Authentication: JWT with optional external providers