diff --git a/Dockerfile b/Dockerfile index a31c46e5..9f58d8f6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,6 +21,16 @@ COPY ./frontend /app/frontend COPY ./VERSION /app/VERSION COPY ./LICENSE /app/LICENSE +# Copy build script and generate build date +COPY ./docker/build-scripts/save-build-date.sh /tmp/ +RUN mkdir -p /app/docker/build-scripts/ && \ + cp /tmp/save-build-date.sh /app/docker/build-scripts/ && \ + chmod +x /tmp/save-build-date.sh && \ + /tmp/save-build-date.sh + +# Set build date as environment variable +#ENV BUILD_DATE=$(cat /app/BUILD_DATE) + # Set Python path explicitly ENV PYTHONPATH=/app diff --git a/app/config.py b/app/config.py index ea30d184..869606c0 100644 --- a/app/config.py +++ b/app/config.py @@ -3,6 +3,7 @@ from pydantic_settings import BaseSettings from typing import Optional, List, Dict, Any import os +from datetime import datetime class Settings(BaseSettings): database_url: str @@ -121,6 +122,29 @@ class Settings(BaseSettings): # Feature flags allow_file_delete: bool = True # Default to allowing file deletion from database + # Get build date from environment or file + @property + def build_date(self) -> str: + # First try to get build date from environment + env_build_date = os.environ.get("BUILD_DATE") + if env_build_date: + return env_build_date + + # Then try to get build date from BUILD_DATE file + build_date_file = os.path.join(os.path.dirname(os.path.dirname(__file__)), "BUILD_DATE") + if os.path.exists(build_date_file): + with open(build_date_file, "r") as f: + return f.read().strip() + + # If a timestamp file doesn't exist, try to get the app.py creation/modification time + app_file = os.path.join(os.path.dirname(__file__), "app.py") + if os.path.exists(app_file): + timestamp = os.path.getmtime(app_file) + return datetime.fromtimestamp(timestamp).strftime("%B %d, %Y") + + # Default to current date if not found elsewhere + return datetime.now().strftime("%B %d, %Y") + # Get version from file or environment @property def version(self) -> str: diff --git a/app/views/general.py b/app/views/general.py index ba82c59b..ed51af7d 100644 --- a/app/views/general.py +++ b/app/views/general.py @@ -4,21 +4,55 @@ General routes for the application homepage and basic pages. from fastapi import Request, HTTPException from fastapi.responses import FileResponse from pathlib import Path +from datetime import date from app.views.base import APIRouter, templates, require_login +from app.utils.config_validator import get_provider_status, validate_storage_configs router = APIRouter() @router.get("/", include_in_schema=False) async def serve_index(request: Request): """Serve the index/home page.""" - return templates.TemplateResponse("index.html", {"request": request}) + # Get provider information from config validator + providers = get_provider_status() + + # Count configured providers + configured_providers = sum(1 for provider in providers.values() if provider['configured']) + + # Count different types of storage targets + storage_issues = validate_storage_configs() + configured_storage_targets = sum(1 for provider, issues in storage_issues.items() + if not issues and provider in ['dropbox', 'nextcloud', 'sftp', + 's3', 'ftp', 'webdav', + 'google_drive', 'onedrive']) + + # Create stats object to pass to the template + stats = { + "processed_files": 0, # Placeholder - would need actual DB query + "active_integrations": configured_providers, + "storage_targets": configured_storage_targets + } + + return templates.TemplateResponse("index.html", {"request": request, "stats": stats}) @router.get("/about", include_in_schema=False) async def serve_about(request: Request): """Serve the about page.""" return templates.TemplateResponse("about.html", {"request": request}) +@router.get("/privacy", include_in_schema=False) +async def serve_privacy(request: Request): + """Serve the privacy policy page.""" + # Pass the current date for the "Last Updated" field + current_date = date.today().strftime("%B %d, %Y") + return templates.TemplateResponse("privacy.html", {"request": request, "current_date": current_date}) + +@router.get("/imprint", include_in_schema=False) +async def serve_imprint(request: Request): + """Serve the imprint/impressum page.""" + return templates.TemplateResponse("imprint.html", {"request": request}) + @router.get("/upload", include_in_schema=False) @require_login async def serve_upload(request: Request): @@ -43,7 +77,7 @@ async def serve_license(request: Request): Path("/app/LICENSE"), # Docker container path Path.home() / "LICENSE", # Home directory (fallback) ] - + license_text = None # Try to read from any of the possible locations @@ -66,7 +100,7 @@ This software is licensed under the Apache License 2.0. The full license text could not be located on this system. Please visit http://www.apache.org/licenses/LICENSE-2.0 for the complete license text. """ - + return templates.TemplateResponse( "license.html", { @@ -74,3 +108,15 @@ Please visit http://www.apache.org/licenses/LICENSE-2.0 for the complete license "license_text": license_text } ) + +@router.get("/cookies", include_in_schema=False) +async def serve_cookies(request: Request): + """Serve the cookie policy page.""" + current_date = date.today().strftime("%B %d, %Y") + return templates.TemplateResponse("cookies.html", {"request": request, "current_date": current_date}) + +@router.get("/terms", include_in_schema=False) +async def serve_terms(request: Request): + """Serve the terms of service page.""" + current_date = date.today().strftime("%B %d, %Y") + return templates.TemplateResponse("terms.html", {"request": request, "current_date": current_date}) diff --git a/docker/build-scripts/save-build-date.sh b/docker/build-scripts/save-build-date.sh new file mode 100644 index 00000000..3a459f50 --- /dev/null +++ b/docker/build-scripts/save-build-date.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Get current date in Month DD, YYYY format (e.g., May 15, 2024) +BUILD_DATE=$(date +"%B %d, %Y") + +# Save it to the BUILD_DATE file +echo $BUILD_DATE > /app/BUILD_DATE + +# Also set it as an environment variable +echo "Setting BUILD_DATE=$BUILD_DATE" +export BUILD_DATE diff --git a/frontend/templates/about.html b/frontend/templates/about.html index 9b2b82a2..d9e00b69 100644 --- a/frontend/templates/about.html +++ b/frontend/templates/about.html @@ -15,7 +15,7 @@
DocuElevate was created with one goal in mind: to simplify and streamline document management - for everyone, whether you’re a small startup or a large enterprise. + for everyone, whether you're a small startup or a large enterprise.
We harness the power of OpenAI for metadata extraction and text refinement, integrate seamlessly @@ -24,18 +24,48 @@
- ++ We care about your privacy and data security. Please review our: +
+ +- Want to dive into the code, contribute ideas, or simply check out the magic behind DocuElevate? - Visit our GitHub repository! + Want to dive into the code, contribute ideas, or learn more about DocuElevate?
- -
- View DocuElevate on GitHub
-
+
Last Updated: {{ build_date|default(current_date|default('May 14, 2024')) }}
+ ++ Cookies are small text files that are stored on your computer or mobile device when you visit a website. They are widely used to make websites work more efficiently and provide information to the website owners. +
++ DocuElevate only uses essential session cookies for the following purpose: +
++ These cookies are mandatory for the proper functioning of our service. Without these cookies, you would be required to log in repeatedly during your browsing session. +
++ The session cookies we use are temporary and are deleted when you close your browser. +
++ DocuElevate does not use any third-party cookies, tracking cookies, advertising cookies, or analytics cookies. We respect your privacy and only implement the minimum cookies required for our service to function. +
++ For more information about how we handle your data, please see our Privacy Policy. +
++ While most web browsers allow you to control cookies through their settings, please note that blocking or deleting our session cookies will prevent DocuElevate from functioning properly, as user authentication relies on these cookies. +
++ By using DocuElevate, you consent to our use of cookies as described in this policy. This Cookie Policy is part of and incorporated into our Terms of Service. +
+Information according to § 5 TMG (German Telemedia Act)
+ +
+ DocuElevate
+ Represented by: Christian Krakau-Louis
+ Email: docuelevate@christian-louis.de
+
+ Despite careful content control, we assume no liability for the content of external links. The operators of the linked pages are solely responsible for their content. +
++ Our service is governed by the following policies: +
+- Your intelligent solution for processing, managing, and organizing documents effortlessly. -
- -- Quickly upload and process your files with our user-friendly interface. -
- - Get Started → + ++ Your intelligent solution for processing, managing, and organizing documents effortlessly. +
+ -- View, organize, and collaborate on your processed files in one central hub. +
{{ stats.processed_files|default('0') }}
+Documents Processed
+{{ stats.active_integrations|default('0') }}
+Active Integrations
+{{ stats.storage_targets|default('0') }}
+Storage Targets
++ Upload and process documents with OCR, metadata extraction, and intelligent classification.
- - View Files → + + Start processing → + ++ Connect to Dropbox, NextCloud, OneDrive and other storage solutions seamlessly. +
+ + Configure storage → + ++ Leverage AI to extract metadata, classify documents, and organize your information. +
+ + View processed files → + ++ Auto-process documents received via email with our IMAP polling capabilities. +
+ + Set up email → + ++ Create workflows to automatically process and route documents based on content. +
+ + Learn more → + ++ Your documents are processed securely with privacy-focused design principles. +
+ + Privacy policy → + +Upload your first document and see DocuElevate in action.
++ While this license governs the use of our software, please also review our + Terms of Service and + Privacy Policy for + information about using the DocuElevate service. +
++ For more information about DocuElevate, please visit the + About page. +
+Last Updated: {{ build_date|default(current_date|default('April 7, 2024')) }}
+ ++ The controller responsible for processing your personal data under the EU General Data Protection Regulation (GDPR) is DocuElevate. +
++ Contact Email: docuelevate@christian-louis.de +
++ This notice applies to the DocuElevate web application, hosted at {{ request.url.scheme }}://{{ request.url.netloc }}/. +
++ User Authentication: We use Google, Dropbox, and Microsoft OAuth for sign-in. Through these services, we may receive information such as your name, email address, and profile picture. +
++ Purpose: We use this information to authenticate you, personalize your experience, and provide the core functionality of DocuElevate. +
++ Legal Basis (GDPR Art. 6): Our primary legal bases for processing are: +
++ We may use cookies or similar technologies to maintain your session, remember your preferences, and enhance your user experience. +
++ For more information about our use of cookies, please visit our Cookie Policy. +
++ OAuth Providers: Google, Dropbox, and Microsoft. These providers may process your personal data according to their own privacy policies. +
++ No Additional Sharing: We do not share, sell, or otherwise disclose your personal data to third parties for advertising or marketing purposes. +
++ We retain your personal data only as long as necessary to provide the DocuElevate service or to comply with legal obligations. +
++ If you wish to have your data deleted or your account removed, please contact us at docuelevate@christian-louis.de. +
++ We implement appropriate technical and organizational measures to protect your personal data against unauthorized access, alteration, disclosure, or destruction. +
++ We may update this notice from time to time to reflect changes in our practices or applicable laws. Any changes will be posted at {{ request.url.scheme }}://{{ request.url.netloc }}/, and where appropriate, we will notify you via email or other channels. +
++ If you have any questions or concerns about this Privacy Notice or your personal data, please contact us at docuelevate@christian-louis.de. +
++ Please also review our Terms of Service and License Information. +
+Last Updated: {{ current_date|default('May 14, 2024') }}
+ ++ By accessing or using DocuElevate, you agree to be bound by these Terms of Service. If you do not agree to these terms, please do not use this service. +
++ DocuElevate provides document processing, OCR, metadata extraction, and storage services. We reserve the right to modify or discontinue any aspect of the service at any time. +
++ You are responsible for: +
++ By using our service, you also agree to our Privacy Policy and Cookie Policy. +
++ DocuElevate respects intellectual property rights. Users may not upload content that infringes on the intellectual property rights of others. +
++ DocuElevate provides the service "as is" without warranties of any kind. We shall not be liable for any direct, indirect, incidental, special, consequential, or punitive damages resulting from your use of or inability to use the service. +
++ These Terms shall be governed by the laws of Germany, without regard to its conflict of law provisions. +
++ If you have any questions about these Terms, please contact us at docuelevate@christian-louis.de. +
++ For information about how we use cookies, please see our Cookie Policy. For licensing information, please refer to our License Information. +
+