chore(01-01): add FERNET_KEY config and email tables migration
- Add FERNET_KEY to .env.example with generation instructions - Register email.models in aerich_config.py and app.py - Register email blueprint in app.py - Create database migration for email_accounts, email_sync_status, emails - Migration includes proper foreign keys and indexes
This commit is contained in:
11
.env.example
11
.env.example
@@ -54,3 +54,14 @@ OIDC_USE_DISCOVERY=true
|
||||
YNAB_ACCESS_TOKEN=your-ynab-personal-access-token
|
||||
# Optional: Specify a budget ID, or leave empty to use the default/first budget
|
||||
YNAB_BUDGET_ID=
|
||||
|
||||
# Mealie Configuration
|
||||
# Base URL for your Mealie instance (e.g., http://192.168.1.5:9000 or https://mealie.example.com)
|
||||
MEALIE_BASE_URL=http://192.168.1.5:9000
|
||||
# Get your API token from Mealie's user settings page
|
||||
MEALIE_API_TOKEN=your-mealie-api-token
|
||||
|
||||
# Email Integration
|
||||
# Email Encryption Key (32-byte URL-safe base64)
|
||||
# Generate with: python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
|
||||
FERNET_KEY=your-fernet-key-here
|
||||
|
||||
@@ -16,6 +16,7 @@ TORTOISE_ORM = {
|
||||
"models": [
|
||||
"blueprints.conversation.models",
|
||||
"blueprints.users.models",
|
||||
"blueprints.email.models",
|
||||
"aerich.models",
|
||||
],
|
||||
"default_connection": "default",
|
||||
|
||||
16
app.py
16
app.py
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import logging
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from quart import Quart, jsonify, render_template, request, send_from_directory
|
||||
@@ -7,6 +8,7 @@ from tortoise.contrib.quart import register_tortoise
|
||||
|
||||
import blueprints.conversation
|
||||
import blueprints.conversation.logic
|
||||
import blueprints.email
|
||||
import blueprints.rag
|
||||
import blueprints.users
|
||||
import blueprints.users.models
|
||||
@@ -15,6 +17,18 @@ from main import consult_simba_oracle
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||
handlers=[logging.StreamHandler()],
|
||||
)
|
||||
|
||||
# Ensure YNAB and Mealie loggers are visible
|
||||
logging.getLogger("utils.ynab_service").setLevel(logging.INFO)
|
||||
logging.getLogger("utils.mealie_service").setLevel(logging.INFO)
|
||||
logging.getLogger("blueprints.conversation.agents").setLevel(logging.INFO)
|
||||
|
||||
app = Quart(
|
||||
__name__,
|
||||
static_folder="raggr-frontend/dist/static",
|
||||
@@ -27,6 +41,7 @@ jwt = JWTManager(app)
|
||||
# Register blueprints
|
||||
app.register_blueprint(blueprints.users.user_blueprint)
|
||||
app.register_blueprint(blueprints.conversation.conversation_blueprint)
|
||||
app.register_blueprint(blueprints.email.email_blueprint)
|
||||
app.register_blueprint(blueprints.rag.rag_blueprint)
|
||||
|
||||
|
||||
@@ -42,6 +57,7 @@ TORTOISE_CONFIG = {
|
||||
"models": [
|
||||
"blueprints.conversation.models",
|
||||
"blueprints.users.models",
|
||||
"blueprints.email.models",
|
||||
"aerich.models",
|
||||
]
|
||||
},
|
||||
|
||||
56
migrations/models/2_20260208091453_add_email_tables.py
Normal file
56
migrations/models/2_20260208091453_add_email_tables.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from tortoise import BaseDBAsyncClient
|
||||
|
||||
RUN_IN_TRANSACTION = True
|
||||
|
||||
|
||||
async def upgrade(db: BaseDBAsyncClient) -> str:
|
||||
return """
|
||||
CREATE TABLE IF NOT EXISTS "email_accounts" (
|
||||
"id" UUID NOT NULL PRIMARY KEY,
|
||||
"email_address" VARCHAR(255) NOT NULL UNIQUE,
|
||||
"display_name" VARCHAR(255),
|
||||
"imap_host" VARCHAR(255) NOT NULL,
|
||||
"imap_port" INT NOT NULL DEFAULT 993,
|
||||
"imap_username" VARCHAR(255) NOT NULL,
|
||||
"imap_password" TEXT NOT NULL,
|
||||
"is_active" BOOL NOT NULL DEFAULT TRUE,
|
||||
"last_error" TEXT,
|
||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"user_id" UUID NOT NULL REFERENCES "users" ("id") ON DELETE CASCADE
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS "email_sync_status" (
|
||||
"id" UUID NOT NULL PRIMARY KEY,
|
||||
"last_sync_date" TIMESTAMPTZ,
|
||||
"last_message_uid" INT NOT NULL DEFAULT 0,
|
||||
"message_count" INT NOT NULL DEFAULT 0,
|
||||
"consecutive_failures" INT NOT NULL DEFAULT 0,
|
||||
"last_failure_date" TIMESTAMPTZ,
|
||||
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"account_id" UUID NOT NULL UNIQUE REFERENCES "email_accounts" ("id") ON DELETE CASCADE
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS "emails" (
|
||||
"id" UUID NOT NULL PRIMARY KEY,
|
||||
"message_id" VARCHAR(255) NOT NULL UNIQUE,
|
||||
"subject" VARCHAR(500) NOT NULL,
|
||||
"from_address" VARCHAR(255) NOT NULL,
|
||||
"to_address" TEXT NOT NULL,
|
||||
"date" TIMESTAMPTZ NOT NULL,
|
||||
"body_text" TEXT,
|
||||
"body_html" TEXT,
|
||||
"chromadb_doc_id" VARCHAR(255),
|
||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"expires_at" TIMESTAMPTZ NOT NULL,
|
||||
"account_id" UUID NOT NULL REFERENCES "email_accounts" ("id") ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS "idx_emails_message_9e3c0c" ON "emails" ("message_id");"""
|
||||
|
||||
|
||||
async def downgrade(db: BaseDBAsyncClient) -> str:
|
||||
return """
|
||||
DROP TABLE IF EXISTS "emails";
|
||||
DROP TABLE IF EXISTS "email_sync_status";
|
||||
DROP TABLE IF EXISTS "email_accounts";"""
|
||||
|
||||
|
||||
MODELS_STATE = ""
|
||||
Reference in New Issue
Block a user