Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.git
.github
.env
.env.*
!.env.example
.venv
venv
__pycache__
*.py[cod]
.pytest_cache

backups
chroma
data
logs
staging
storage
uploads

assets
tests
README.md
Dockerfile.dev
setup.ps1
setup.sh
50 changes: 50 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copy this file to .env. Never commit real credentials.

# Security
SECRET_KEY=
JWT_SECRET_KEY=
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
ENVIRONMENT=production
CORS_ORIGINS=http://localhost:8000,http://127.0.0.1:8000
TRUSTED_PROXY_IPS=127.0.0.1,::1

# Database and storage
DATABASE_URL=sqlite:///./data/documents.db
DATA_FOLDER=./data
STAGING_FOLDER=./data/staging
STORAGE_FOLDER=./data/storage
LOGS_FOLDER=./data/logs
BACKUP_FOLDER=./data/backups

# AI provider: openai or azure
AI_PROVIDER=openai
OPENAI_API_KEY=
EMBEDDING_MODEL=text-embedding-3-small
CHAT_MODEL=gpt-4o-mini
ANALYSIS_MODEL=gpt-4o-mini

# Azure OpenAI
AZURE_OPENAI_API_KEY=
AZURE_OPENAI_ENDPOINT=
AZURE_OPENAI_API_VERSION=2024-08-01-preview
AZURE_OPENAI_CHAT_DEPLOYMENT=
AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT=

# ChromaDB. The localhost defaults use the embedded persistent client.
CHROMA_HOST=localhost
CHROMA_PORT=8001
CHROMA_COLLECTION_NAME=documents

# OCR and file processing
TESSERACT_PATH=/usr/bin/tesseract
POPPLER_PATH=/usr/bin
MAX_FILE_SIZE=100MB
ALLOWED_EXTENSIONS=pdf,png,jpg,jpeg,tiff,bmp,txt,text,md,markdown

# Runtime behavior
LOG_LEVEL=INFO
AI_TEXT_LIMIT=16000
AI_CONTEXT_LIMIT=10000
AI_REQUEST_TIMEOUT=30
AI_MAX_RETRIES=2
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
python-version: "3.12"
cache: pip
- name: Install test dependencies
run: pip install fastapi pydantic-settings sqlalchemy loguru watchdog pytest
run: pip install fastapi pydantic-settings sqlalchemy loguru watchdog passlib pytesseract Pillow pytest
- name: Run regression tests
run: python -m pytest tests -q
- name: Parse PowerShell scripts
Expand Down
35 changes: 22 additions & 13 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
chroma/chroma.sqlite3
data/documents.db
data/documents.db-*
data/.local-smoke-credentials.json
data/chroma/
data/logs/
data/staging/
data/storage/
data/uploads/
data/backups/
__pycache__/
*.py[cod]
.DS_Store
# Local credentials and environments
.env
.venv/
venv/

# Runtime data
/backups/
/chroma/
/data/
/logs/
/staging/
/storage/
/uploads/
.local-smoke-credentials.json

# Python bytecode and test caches
__pycache__/
*.py[cod]
.pytest_cache/
.coverage
htmlcov/

# Editors and operating systems
.DS_Store
.idea/
.vscode/
19 changes: 6 additions & 13 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ RUN apt-get update && apt-get install -y \
libmagic1 \
# Health check
curl \
# Process management for all-in-one mode
supervisor \
# Clean up
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
Expand All @@ -66,15 +64,11 @@ WORKDIR /app
COPY --chown=appuser:appuser app/ ./app/
COPY --chown=appuser:appuser frontend/ ./frontend/
COPY --chown=appuser:appuser docker-entrypoint.sh ./
COPY --chown=appuser:appuser docker-entrypoint-aio.sh ./
COPY --chown=appuser:appuser supervisord.conf /etc/supervisor/conf.d/

# Create necessary directories with correct permissions
RUN mkdir -p data data/logs data/staging data/storage data/uploads backups chroma && \
chmod +x docker-entrypoint.sh docker-entrypoint-aio.sh && \
chown -R appuser:appuser /app && \
mkdir -p /var/log/supervisor && \
chown -R appuser:appuser /var/log/supervisor
RUN mkdir -p data/logs data/staging data/storage data/uploads data/backups && \
chmod +x docker-entrypoint.sh && \
chown -R appuser:appuser /app

# Switch to non-root user
USER appuser
Expand All @@ -86,17 +80,16 @@ ENV PYTHONUNBUFFERED=1 \
# Tesseract and Poppler paths
TESSERACT_PATH=/usr/bin/tesseract \
POPPLER_PATH=/usr/bin \
# Application settings (should be overridden in production)
# Application settings
DATABASE_URL=sqlite:///./data/documents.db \
SECRET_KEY=MUST-BE-SET-IN-PRODUCTION \
AI_PROVIDER=openai \
TRUSTED_PROXY_IPS=127.0.0.1

# Add metadata labels
LABEL maintainer="Document Manager Team" \
LABEL maintainer="Jannik Reinhard" \
version="1.0.0" \
description="AI-powered document management system" \
org.opencontainers.image.source="https://github.com/yourusername/documentmanager"
org.opencontainers.image.source="https://github.com/JayRHa/DocumentManager"

# Expose application port
EXPOSE 8000
Expand Down
14 changes: 4 additions & 10 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ RUN apt-get update && apt-get install -y \
libmagic1 libmagic-dev \
# Health check
curl \
# Process management
supervisor \
# Development tools
vim nano htop \
&& apt-get clean \
Expand All @@ -29,20 +27,17 @@ WORKDIR /app

# Copy requirements and install Python packages
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt && \
pip install --no-cache-dir chromadb watchdog
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY app/ ./app/
COPY frontend/ ./frontend/
COPY cli.py ./
COPY docker-entrypoint.sh ./
COPY docker-entrypoint-aio.sh ./
COPY supervisord.conf /etc/supervisor/conf.d/

# Create necessary directories
RUN mkdir -p data data/logs data/staging data/storage data/uploads backups chroma /var/log/supervisor && \
chmod +x docker-entrypoint.sh docker-entrypoint-aio.sh
RUN mkdir -p data/logs data/staging data/storage data/uploads data/backups && \
chmod +x docker-entrypoint.sh

# Development environment variables
ENV PYTHONUNBUFFERED=1 \
Expand All @@ -51,12 +46,11 @@ ENV PYTHONUNBUFFERED=1 \
ENVIRONMENT=development \
LOG_LEVEL=DEBUG \
DATABASE_URL=sqlite:///./data/documents.db \
SECRET_KEY=dev-secret-key-only-for-development \
TESSERACT_PATH=/usr/bin/tesseract \
POPPLER_PATH=/usr/bin

# Expose ports
EXPOSE 8000

# Use the same entrypoint as production
ENTRYPOINT ["/app/docker-entrypoint.sh"]
ENTRYPOINT ["/app/docker-entrypoint.sh"]
62 changes: 38 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
</div>
<!-- jr-brand:end -->

> **Canonical repository:** This repository supersedes the legacy
> `JayRHa/DocumentManagement` project and contains the maintained application,
> runtime configuration, tests, and deployment path.

## Features

### AI-Powered Intelligence
Expand Down Expand Up @@ -93,15 +97,20 @@ The beauty of open source? You can have this running on your machine right now:
git clone https://github.com/JayRHa/DocumentManager.git
cd DocumentManager

# Run the setup script
# Build and run with a generated local .env file
./setup.sh build
./setup.sh prod

# Or manually with Docker
docker build -t documentmanager:local .
cp .env.example .env
# Set a strong SECRET_KEY and optional AI credentials in .env first.
docker run -d \
--name documentmanager-local \
-p 127.0.0.1:8000:8000 \
--env-file .env \
-v $(pwd)/data:/app/data \
-v $(pwd)/backups:/app/data/backups \
documentmanager:local
```

Expand Down Expand Up @@ -205,57 +214,62 @@ uvicorn app.main:app --reload --host 127.0.0.1 --port 8000

```
DocumentManager/
├── app/ # Backend FastAPI application
│ ├── api/ # REST API endpoints
│ ├── core/ # Core business logic
│ ├── models/ # SQLAlchemy models
│ └── services/ # AI, OCR, and storage services
├── frontend/ # Vanilla JS frontend
├── docker/ # Docker configuration
├── tests/ # Test suite
└── docs/ # Documentation
├── app/ # FastAPI backend
│ ├── middleware/ # Authentication, CSRF, rate limiting, logging
│ ├── routers/ # REST API endpoints
│ ├── services/ # AI, OCR, search, and document processing
│ └── utils/ # Backup, validation, and file security
├── frontend/ # Vanilla JavaScript frontend
├── tests/ # Regression tests
├── Dockerfile # Production container
├── Dockerfile.dev # Development container
└── setup.sh / setup.ps1 # Runtime helpers
```

### Technology Stack

- **Backend**: FastAPI, SQLAlchemy, Pydantic
- **AI/ML**: OpenAI GPT-4, Azure OpenAI, ChromaDB
- **OCR**: Tesseract (50+ languages)
- **Database**: SQLite (default), PostgreSQL (production)
- **Database**: SQLite
- **Frontend**: Vanilla JavaScript, modern CSS
- **Deployment**: Docker, Docker Compose
- **Deployment**: Docker or Podman

## Configuration

### Environment Variables

Create a `.env` file in the root directory:
Copy `.env.example` to `.env`. The setup script does this automatically and
generates a strong `SECRET_KEY` when `.env` does not exist.

```bash
# Security - CHANGE IN PRODUCTION!
SECRET_KEY=your-secret-key-here
cp .env.example .env
python -c 'import secrets; print(secrets.token_urlsafe(32))'
```

Place the generated value in `SECRET_KEY` and configure the required provider:

```dotenv
SECRET_KEY=replace-with-generated-value
ENVIRONMENT=production

# Database
DATABASE_URL=sqlite:///./data/documents.db
# For PostgreSQL: postgresql://user:pass@localhost/dbname

# AI Provider
AI_PROVIDER=openai
OPENAI_API_KEY=sk-...
# Or for Azure:
# AI_PROVIDER=azure
# AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com
# AZURE_OPENAI_KEY=your-key
# AZURE_OPENAI_API_KEY=your-key
# AZURE_OPENAI_CHAT_DEPLOYMENT=your-chat-deployment
# AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT=your-embedding-deployment

# Application Settings
ENVIRONMENT=production
LOG_LEVEL=INFO
MAX_UPLOAD_SIZE=104857600 # 100MB
ALLOWED_EXTENSIONS=pdf,jpg,jpeg,png,txt,md,markdown,doc,docx

# Storage
STORAGE_TYPE=local
STORAGE_PATH=/app/data/storage
MAX_FILE_SIZE=100MB
ALLOWED_EXTENSIONS=pdf,png,jpg,jpeg,tiff,bmp,txt,text,md,markdown
```

## API Documentation
Expand Down
1 change: 1 addition & 0 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class Settings(BaseSettings):
data_folder: str = "./data"
storage_folder: str = "./data/storage"
logs_folder: str = "./data/logs"
backup_folder: str = "./data/backups"

# OCR
tesseract_path: str = "/usr/bin/tesseract"
Expand Down
4 changes: 2 additions & 2 deletions app/routers/backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class BackupConfigRequest(BaseModel):
interval_hours: int = 24
max_backups: int = 7
include_files: bool = True
backup_path: str = "backups"
backup_path: str = "data/backups"


class ManualBackupRequest(BaseModel):
Expand Down Expand Up @@ -412,4 +412,4 @@ def backup_health_check(
"message": f"Health check failed: {str(e)}",
"recommendation": "Check backup system configuration"
}]
}
}
6 changes: 3 additions & 3 deletions app/services/backup_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def __init__(self):
"interval_hours": 24, # Default: daily backups
"max_backups": 7, # Keep last 7 backups
"include_files": True,
"backup_path": "backups"
"backup_path": "data/backups"
}
self.last_backup: Optional[datetime] = None
self.backup_history = []
Expand All @@ -38,7 +38,7 @@ def configure(
interval_hours: int = 24,
max_backups: int = 7,
include_files: bool = True,
backup_path: str = "backups"
backup_path: str = "data/backups"
):
"""
Configure backup scheduler settings.
Expand Down Expand Up @@ -384,4 +384,4 @@ def get_backup_recommendations(self) -> Dict[str, Any]:


# Global backup scheduler instance
backup_scheduler = BackupScheduler()
backup_scheduler = BackupScheduler()
Loading