From 5eff7f39a4933d2dadecab8a98acbc6684847f7b Mon Sep 17 00:00:00 2001 From: Bryce Date: Thu, 30 Oct 2025 20:26:23 -0700 Subject: [PATCH] UnTerraform --- terraform/.terraform.lock.hcl | 41 --- terraform/Dockerfile | 28 -- terraform/FIREBASE_AUTH.md | 262 ----------------- terraform/README.md | 297 -------------------- terraform/app.yaml | 29 -- terraform/deploy.sh | 229 --------------- terraform/deployment.tf | 87 ------ terraform/main.tf | 232 --------------- terraform/modules/app_engine/main.tf | 118 -------- terraform/modules/app_engine/variables.tf | 71 ----- terraform/modules/cloud_run/main.tf | 144 ---------- terraform/modules/cloud_run/variables.tf | 71 ----- terraform/templates/email_verification.html | 95 ------- terraform/templates/email_verification.txt | 31 -- terraform/templates/reset_password.html | 78 ----- terraform/templates/reset_password.txt | 27 -- terraform/terraform.staging.tfvars | 9 - terraform/terraform.tfvars.example | 9 - terraform/variables.tf | 76 ----- 19 files changed, 1934 deletions(-) delete mode 100644 terraform/.terraform.lock.hcl delete mode 100644 terraform/Dockerfile delete mode 100644 terraform/FIREBASE_AUTH.md delete mode 100644 terraform/README.md delete mode 100644 terraform/app.yaml delete mode 100755 terraform/deploy.sh delete mode 100644 terraform/deployment.tf delete mode 100644 terraform/main.tf delete mode 100644 terraform/modules/app_engine/main.tf delete mode 100644 terraform/modules/app_engine/variables.tf delete mode 100644 terraform/modules/cloud_run/main.tf delete mode 100644 terraform/modules/cloud_run/variables.tf delete mode 100644 terraform/templates/email_verification.html delete mode 100644 terraform/templates/email_verification.txt delete mode 100644 terraform/templates/reset_password.html delete mode 100644 terraform/templates/reset_password.txt delete mode 100644 terraform/terraform.staging.tfvars delete mode 100644 terraform/terraform.tfvars.example delete mode 100644 terraform/variables.tf diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl deleted file mode 100644 index 65e526e..0000000 --- a/terraform/.terraform.lock.hcl +++ /dev/null @@ -1,41 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/hashicorp/google" { - version = "7.9.0" - hashes = [ - "h1:xhzErMeJSU7hzQs7Z5MvnGG+cwZA3gxW1tGwRbGjsL8=", - "zh:09d6c241edc669a2d5a0ec20ebdc8489995e690ed7b94bb64048f23db589801b", - "zh:0aa72a11265db9201464829a31a3d834149cd0aad5bb184a46f08bef4cd56d83", - "zh:1bd349373d11ba77bcd6ba389ec94e5116ac6b1c83ea2db85e847af7948d553f", - "zh:3ca032646e2d332e48aa46be19b7c30cdadd09e066e2f7c9e0f2022fbc0e0e7a", - "zh:481a20133ad3de9ed8a5de5ade5a46fe8f9f9c9f740ad7ebb9c4d7ef914140db", - "zh:56f3b7b521fa09dacc94abca7451b075d39793a569b53ef7ebed83fb088f5035", - "zh:bde46790fb4e6bf106df0c404aa2f8361651ad9ac70f30faf4bcb55d65e7d38e", - "zh:cc8d931e1d45376a421cff84d1223571296724e263ae4ebc021e3bd76bc74b9a", - "zh:d6604e6bb61f695e631d8862490389d65895f34d0133c066a81601e5539f0fa7", - "zh:d999cf33e1dd8cb3b02a75d079e542d9f3d73bc5756b870e78dfe3bf89535bd9", - "zh:e4f38256d1f190f7e04d393ba3e247da7e12f4bcf22c2c3ce1f57b465b4ad8a3", - "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", - ] -} - -provider "registry.terraform.io/hashicorp/google-beta" { - version = "6.50.0" - constraints = "~> 6.0" - hashes = [ - "h1:uxh4ME3hhSzVjmiWgA1IQqYqg25MV6FMVArHyA6Ki5o=", - "zh:18b442bd0a05321d39dda1e9e3f1bdede4e61bc2ac62cc7a67037a3864f75101", - "zh:2e387c51455862828bec923a3ec81abf63a4d998da470cf00e09003bda53d668", - "zh:3942e708fa84ebe54996086f4b1398cb747fe19cbcd0be07ace528291fb35dee", - "zh:496287dd48b34ae6197cb1f887abeafd07c33f389dbe431bb01e24846754cfdd", - "zh:6eca885419969ce5c2a706f34dce1f10bde9774757675f2d8a92d12e5a1be390", - "zh:710dbef826c3fe7f76f844dae47937e8e4c1279dd9205ec4610be04cf3327244", - "zh:777ebf44b24bfc7bdbf770dc089f1a72f143b4718fdedb8c6bd75983115a1ec2", - "zh:9c8703bba37b8c7ad857efc3513392c5a096c519397c1cb822d7612f38e4262f", - "zh:c4f1d3a73de2702277c99d5348ad6d374705bcfdd367ad964ff4cfd2cf06c281", - "zh:eca8df11af3f5a948492d5b8b5d01b4ec705aad10bc30ec1524205508ae28393", - "zh:f41e7fd5f2628e8fd6b8ea136366923858f54428d1729898925469b862c275c2", - "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", - ] -} diff --git a/terraform/Dockerfile b/terraform/Dockerfile deleted file mode 100644 index 09e40bd..0000000 --- a/terraform/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -# Use Python 3.11 slim image -FROM python:3.11-slim - -# Set working directory -WORKDIR /app - -# Copy requirements first for better layer caching -COPY requirements.txt . - -# Install dependencies -RUN pip install --no-cache-dir -r requirements.txt - -# Copy application code -COPY . . - -# Create non-root user (security best practice) -RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app -USER appuser - -# Expose port -EXPOSE 5000 - -# Health check -HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ - CMD curl -f http://localhost:5000/ || exit 1 - -# Run the application -CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "2", "--timeout", "120", "app:app"] \ No newline at end of file diff --git a/terraform/FIREBASE_AUTH.md b/terraform/FIREBASE_AUTH.md deleted file mode 100644 index 183f8fc..0000000 --- a/terraform/FIREBASE_AUTH.md +++ /dev/null @@ -1,262 +0,0 @@ -# Firebase Authentication Automation with Terraform - -This guide explains how Firebase Authentication settings are automated in the Rothbard Law Group deployment. - -## 🚀 What's Automated - -### 1. Authentication Providers -- **Email/Password**: Enabled by default -- **Google Sign-In**: Optional (controlled by `enable_google_signin` variable) -- **Phone, Facebook, Apple**: Disabled for security - -### 2. Email Templates -- **Password Reset**: Professional HTML and text templates -- **Email Verification**: Welcome templates with branding -- **Customizable**: From address, name, and reply-to settings - -### 3. Security Rules -- **Firestore Rules**: Users can only access their own data -- **Authentication Required**: All database operations require auth -- **Profile Access**: Users can read/write their own profile only - -### 4. Firebase Hosting -- **Static Asset Hosting**: Optional for CSS, JS, images -- **Caching Headers**: Optimized performance -- **URL Rewrites**: Proper routing for SPA - -## 📋 Configuration Variables - -Add these to your `terraform.tfvars`: - -```hcl -# Authentication Settings -enable_google_signin = false # Set to true to enable Google Sign-In - -# Email Configuration -auth_from_email = "noreply@rothbardlaw.com" -auth_from_name = "Rothbard Law Group" -auth_reply_to = "support@rothbardlaw.com" -``` - -## 🔧 Authentication Provider Setup - -### Email/Password (Default) -```hcl -sign_in_options { - email { - enabled = true - password_required = true - } -} -``` - -### Google Sign-In (Optional) -To enable Google Sign-In: - -1. **Set variable**: - ```hcl - enable_google_signin = true - ``` - -2. **Configure OAuth in Google Cloud**: - ```bash - # Enable Google+ API - gcloud services enable plus.googleapis.com - - # Create OAuth consent screen - gcloud alpha iap oauth-clients create \ - --display-name="Rothbard Portal" \ - --brand="Rothbard Law Group" - ``` - -3. **Update Firebase Console**: - - Go to Firebase Console → Authentication → Sign-in method - - Enable Google provider - - Add your OAuth client ID and secret - -## 📧 Email Template Customization - -### Template Files -- `templates/reset_password.html` - Password reset HTML -- `templates/reset_password.txt` - Password reset text -- `templates/email_verification.html` - Email verification HTML -- `templates/email_verification.txt` - Email verification text - -### Customization Options -- **Branding**: Update colors, logos in HTML templates -- **Contact Info**: Change address, phone numbers -- **Content**: Modify welcome messages and instructions - -### Email Variables Available -- `{{ resetLink }}` - Password reset URL -- `{{ verificationLink }}` - Email verification URL -- `{{ userEmail }}` - User's email address - -## 🔒 Security Rules Explained - -### Firestore Rules -```javascript -// Users can only access their own profile -match /users/{userId} { - allow read, write: if request.auth.uid == userId; -} - -// All other collections require authentication -match /{collection=**} { - allow read, write: if request.auth != null; -} -``` - -### Security Features -- **User Isolation**: Users can't access other users' data -- **Authentication Required**: No anonymous access -- **Self-Service**: Users can only modify their own profiles - -## 🛠️ Advanced Configuration - -### Multi-Factor Authentication -Currently disabled for simplicity. To enable: - -```hcl -multi_factor_auth { - enabled = true - provider_configs { - phone { - enabled = true - } - } -} -``` - -### Custom Email Templates -For more advanced templates, you can use Firebase Admin SDK: - -```python -# In your Flask app -from firebase_admin import auth - -def send_custom_email(user_email, template_name): - # Custom email sending logic - pass -``` - -### Domain Restrictions -To restrict authentication to specific domains: - -```javascript -// In Firebase Auth security rules -rules_version = '2'; -service cloud.firestore { - match /users/{userId} { - allow read, write: if - request.auth != null && - request.auth.token.email.matches('.*@rothbardlaw\\.com$'); - } -} -``` - -## 📊 Monitoring and Analytics - -### Authentication Events -Track these events in your application: - -```python -# Log authentication events -def log_auth_event(event_type, user_id, details=None): - db.collection('auth_logs').add({ - 'event_type': event_type, - 'user_id': user_id, - 'timestamp': firestore.SERVER_TIMESTAMP, - 'details': details or {} - }) -``` - -### Key Events to Monitor -- User registrations -- Password resets -- Failed login attempts -- Email verifications - -## 🔄 Updates and Maintenance - -### Updating Email Templates -1. Edit template files in `terraform/templates/` -2. Run `terraform apply` to update -3. Changes apply to new emails immediately - -### Adding New Providers -1. Update `google_identitytoolkit_config` in `main.tf` -2. Add provider-specific variables -3. Configure OAuth credentials in Google Cloud -4. Apply Terraform changes - -### Security Rule Updates -1. Modify `google_firestore_security_policy` in `main.tf` -2. Test rules in Firebase Console first -3. Apply with Terraform - -## 🚨 Troubleshooting - -### Common Issues - -1. **Email Templates Not Working** - - Check template file paths - - Verify template syntax - - Check email provider settings - -2. **Authentication Provider Not Working** - - Verify API credentials - - Check provider configuration - - Review Firebase Console settings - -3. **Security Rules Blocking Access** - - Test rules in Firebase Console - - Check user authentication status - - Verify collection/document paths - -### Debug Commands - -```bash -# Check Firebase Auth configuration -gcloud auth troubleshoot - -# Test authentication flow -curl -X POST "https://identitytoolkit.googleapis.com/v1/accounts:signIn?key=YOUR_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{"email":"user@example.com","password":"password","returnSecureToken":true}' - -# Check Firestore rules -gcloud firestore databases rules describe \ - --project=your-project-id -``` - -## 📚 Additional Resources - -- [Firebase Authentication Documentation](https://firebase.google.com/docs/auth) -- [Terraform Google Provider](https://registry.terraform.io/providers/hashicorp/google/latest/docs) -- [Firestore Security Rules](https://firebase.google.com/docs/firestore/security/get-started) -- [Firebase Email Templates](https://firebase.google.com/docs/auth/custom-email-templates) - -## 🎯 Best Practices - -1. **Security First** - - Use HTTPS everywhere - - Implement proper session management - - Regular security audits - -2. **User Experience** - - Clear error messages - - Professional email templates - - Mobile-responsive design - -3. **Maintenance** - - Regular backups - - Monitoring and alerts - - Documentation updates - -4. **Compliance** - - GDPR compliance for EU users - - Data retention policies - - Privacy policy alignment - -This automation ensures your Firebase Authentication is secure, professional, and maintainable while following industry best practices for legal client portals. \ No newline at end of file diff --git a/terraform/README.md b/terraform/README.md deleted file mode 100644 index d2cd4f9..0000000 --- a/terraform/README.md +++ /dev/null @@ -1,297 +0,0 @@ -# Rothbard Law Group - Terraform Deployment - -This Terraform configuration deploys the Rothbard Law Group client portal to Google Cloud Platform with Firebase backend. - -## Architecture Overview - -``` -┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ -│ Firebase App │ │ Firestore │ │ Cloud Run │ -│ (Client Auth) │◄──►│ (User Data) │◄──►│ (Flask App) │ -└─────────────────┘ └─────────────────┘ └─────────────────┘ - │ - ▼ - ┌─────────────────┐ - │ Filevine API │ - │ (Case Data) │ - └─────────────────┘ -``` - -## Hosting Options - -### 1. Cloud Run (Recommended) -- **Best for production use** -- Container-based deployment -- Scales from 0 to N instances -- Cost-effective (pay-per-use) -- Full control over environment - -### 2. App Engine -- Platform-as-a-service -- Built-in scaling -- Slightly more restrictive -- Good for simpler deployments - -## Prerequisites - -1. **Google Cloud SDK** - ```bash - curl https://sdk.cloud.google.com | bash - gcloud init - ``` - -2. **Terraform** - ```bash - # macOS - brew install terraform - - # Linux - sudo apt-get install terraform - ``` - -3. **Docker** (for Cloud Run) - ```bash - # macOS - brew install docker - - # Linux - sudo apt-get install docker.io - ``` - -## Setup Instructions - -### 1. Configure Terraform Variables - -Copy the example variables file: -```bash -cp terraform.tfvars.example terraform.tfvars -``` - -Edit `terraform.tfvars` with your values: -```hcl -gcp_project_id = "your-gcp-project-id" -domain_name = "rothbard.yourdomain.com" -hosting_option = "cloud_run" # or "app_engine" -``` - -### 2. Set Environment Variables - -Create a `.env` file for sensitive data: -```bash -# Flask Configuration -FLASK_SECRET_KEY=your-super-secret-key - -# Firebase Configuration -FIREBASE_API_KEY=your-firebase-api-key -FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com -FIREBASE_PROJECT_ID=your-gcp-project-id -FIREBASE_APP_ID=your-firebase-app-id - -# Service Account (optional - can use gcloud auth) -FIREBASE_SERVICE_ACCOUNT_JSON='{"type":"service_account",...}' - -# Filevine API Configuration -FILEVINE_CLIENT_ID=your-filevine-client-id -FILEVINE_CLIENT_SECRET=your-filevine-client-secret -FILEVINE_PERSONAL_ACCESS_TOKEN=your-filevine-pat -FILEVINE_ORG_ID=your-filevine-org-id -FILEVINE_USER_ID=your-filevine-user-id -``` - -### 3. Deploy with Cloud Run (Recommended) - -#### Step 1: Build and Push Docker Image -```bash -# Set your project ID -export PROJECT_ID=your-gcp-project-id - -# Build the Docker image -docker build -t gcr.io/$PROJECT_ID/rothbard-portal:latest . - -# Push to Google Container Registry -docker push gcr.io/$PROJECT_ID/rothbard-portal:latest -``` - -#### Step 2: Deploy Infrastructure -```bash -cd terraform - -# Initialize Terraform -terraform init - -# Plan the deployment -terraform plan - -# Apply the changes -terraform apply -``` - -#### Step 3: Update Container Image Variable -After the first deployment, update your `terraform.tfvars`: -```hcl -container_image = "gcr.io/your-gcp-project-id/rothbard-portal:latest" -``` - -Then run `terraform apply` again. - -### 4. Deploy with App Engine - -#### Step 1: Create Source Package -```bash -# Copy app files and create zip -cp app.py requirements.txt templates/ app-engine/ -cd app-engine -zip -r ../app-source.zip . -cd .. -``` - -#### Step 2: Deploy Infrastructure -```bash -cd terraform - -# Set hosting option to app_engine -# Edit terraform.tfvars: hosting_option = "app_engine" - -# Initialize and apply -terraform init -terraform plan -terraform apply -``` - -## Post-Deployment Setup - -### 1. Firebase Configuration - -After deployment, you'll need to: - -1. **Configure Firebase Authentication**: - - Go to Firebase Console → Authentication - - Enable Email/Password provider - - Add your domain to authorized domains - -2. **Set up Firestore Rules**: - ```javascript - rules_version = '2'; - service cloud.firestore { - match /databases/{database}/documents { - match /users/{userId} { - allow read, write: if request.auth != null && request.auth.uid == userId; - } - } - } - ``` - -### 2. Enable Users - -Users need to be manually enabled in Firestore: - -```javascript -// In Firebase Console → Firestore Database -// Create document in collection 'users' with document ID = Firebase UID -{ - enabled: true, - caseEmail: "user@example.com", // This filters Filevine projects - name: "Client Name" -} -``` - -### 3. Custom Domain (Optional) - -For Cloud Run with custom domain: - -```bash -# Map your domain to the Cloud Run service -gcloud run services add-iam-policy-binding rothbard-portal-service \ - --member="allUsers" \ - --role="roles/run.invoker" - -# Set up domain mapping -gcloud run domain-mappings create \ - --domain=rothbard.yourdomain.com \ - --service=rothbard-portal-service -``` - -## Monitoring and Maintenance - -### View Logs -```bash -# Cloud Run logs -gcloud logs read "resource.type=cloud_run_revision" --limit 50 - -# App Engine logs -gcloud app logs tail -s default -``` - -### Scale Configuration - -For Cloud Run, you can adjust scaling in `terraform/modules/cloud_run/main.tf`: -```hcl -metadata { - annotations = { - "autoscaling.knative.dev/maxScale" = "10" # Max instances - "autoscaling.knative.dev/minScale" = "1" # Min instances - } -} -``` - -### Updates - -To update the application: - -1. **Cloud Run**: Build and push new Docker image, then update the `container_image` variable -2. **App Engine**: Update source code, create new zip, and redeploy - -## Costs - -### Cloud Run (Recommended) -- **Free tier**: 180,000 vCPU-seconds, 360,000 GiB-seconds memory per month -- **Beyond free tier**: ~$0.000024 per vCPU-second, $0.0000025 per GiB-second -- **Typical cost**: $5-20/month for low traffic client portal - -### App Engine -- **Free tier**: 28 instance-hours per day -- **Beyond free tier**: ~$0.05 per instance-hour -- **Typical cost**: $10-50/month depending on traffic - -### Firebase -- **Spark plan**: Free for most use cases -- **Blaze plan**: Pay-as-you-go for high usage -- **Typical cost**: $0-25/month depending on authentication usage - -## Security Considerations - -1. **Service Account**: Minimal permissions granted (Firestore and Firebase Admin) -2. **Secret Management**: Sensitive data stored in Secret Manager -3. **HTTPS**: All traffic encrypted with TLS -4. **Authentication**: Firebase ID tokens verified server-side -5. **Access Control**: User access controlled through Firestore profiles - -## Troubleshooting - -### Common Issues - -1. **Build failures**: Check Dockerfile and requirements.txt -2. **Permission errors**: Verify service account has correct IAM roles -3. **Firebase connection**: Ensure service account key is properly formatted -4. **CORS errors**: Configure Firebase Auth domain correctly - -### Debug Commands - -```bash -# Check Cloud Run service status -gcloud run services describe rothbard-portal-service - -# Test service locally -docker run -p 5000:5000 gcr.io/$PROJECT_ID/rothbard-portal:latest - -# Check Terraform state -terraform show -``` - -## Support - -For issues with: -- **Terraform deployment**: Check Terraform logs and state -- **Cloud Run**: View Cloud Run logs in Google Console -- **Firebase**: Check Firebase Console for configuration issues -- **Application**: Review Flask application logs \ No newline at end of file diff --git a/terraform/app.yaml b/terraform/app.yaml deleted file mode 100644 index 7cf3513..0000000 --- a/terraform/app.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# App Engine configuration file -runtime: python311 - -instance_class: F1 -automatic_scaling: - min_idle_instances: automatic - max_idle_instances: 1 - min_pending_latency: automatic - max_pending_latency: automatic - -# Environment variables -env_variables: - FLASK_ENV: production - PORT: 8080 - -# Handlers -handlers: -- url: /.* - script: auto - secure: always - -# Health check -health_check: - enable_health_check: true - check_path: "/" - -# Runtime configuration -runtime_config: - python_version: 3 \ No newline at end of file diff --git a/terraform/deploy.sh b/terraform/deploy.sh deleted file mode 100755 index 3686313..0000000 --- a/terraform/deploy.sh +++ /dev/null @@ -1,229 +0,0 @@ -#!/bin/bash - -# Rothbard Law Group Deployment Script -# This script automates the deployment process for Cloud Run - -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -# Configuration -PROJECT_ID="" -DOMAIN_NAME="" -HOSTING_OPTION="cloud_run" - -# Helper functions -log_info() { - echo -e "${GREEN}[INFO]${NC} $1" -} - -log_warn() { - echo -e "${YELLOW}[WARN]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# Check prerequisites -check_prerequisites() { - log_info "Checking prerequisites..." - - # Check gcloud - if ! command -v gcloud &> /dev/null; then - log_error "gcloud is not installed. Please install Google Cloud SDK." - exit 1 - fi - - # Check terraform - if ! command -v terraform &> /dev/null; then - log_error "terraform is not installed. Please install Terraform." - exit 1 - fi - - # Check docker (for Cloud Run) - if [ "$HOSTING_OPTION" = "cloud_run" ] && ! command -v docker &> /dev/null; then - log_error "docker is not installed. Please install Docker for Cloud Run deployment." - exit 1 - fi - - log_info "Prerequisites check passed!" -} - -# Setup project -setup_project() { - log_info "Setting up Google Cloud project..." - - if [ -z "$PROJECT_ID" ]; then - read -p "Enter your GCP Project ID: " PROJECT_ID - fi - - # Set the project - gcloud config set project "$PROJECT_ID" - - # Enable required APIs - log_info "Enabling required APIs..." - gcloud services enable run.googleapis.com - gcloud services enable cloudbuild.googleapis.com - gcloud services enable firestore.googleapis.com - gcloud services enable firebase.googleapis.com - gcloud services enable secretmanager.googleapis.com - - log_info "Project setup completed!" -} - -# Build and push Docker image (Cloud Run) -build_and_push_image() { - if [ "$HOSTING_OPTION" != "cloud_run" ]; then - return - fi - - log_info "Building Docker image..." - - # Build the image - docker build -t gcr.io/$PROJECT_ID/rothbard-portal:latest . - - log_info "Pushing Docker image to Google Container Registry..." - - # Configure Docker to use gcloud as a credential helper - gcloud auth configure-docker - - # Push the image - docker push gcr.io/$PROJECT_ID/rothbard-portal:latest - - log_info "Docker image pushed successfully!" -} - -# Deploy infrastructure with Terraform -deploy_infrastructure() { - log_info "Deploying infrastructure with Terraform..." - - cd terraform - - # Create terraform.tfvars if it doesn't exist - if [ ! -f "terraform.tfvars" ]; then - log_warn "terraform.tfvars not found. Creating from example..." - cp terraform.tfvars.example terraform.tfvars - - # Update with project ID - sed -i "s/your-gcp-project-id/$PROJECT_ID/g" terraform.tfvars - - if [ -n "$DOMAIN_NAME" ]; then - sed -i "s/rothbard-portal.example.com/$DOMAIN_NAME/g" terraform.tfvars - fi - - log_warn "Please edit terraform/terraform.tfvars with your specific configuration before continuing." - read -p "Press Enter to continue after editing..." - fi - - # Initialize Terraform - terraform init - - # Plan deployment - log_info "Planning Terraform deployment..." - terraform plan - - # Apply deployment - log_info "Applying Terraform configuration..." - terraform apply -auto-approve - - # Get the output URL - APP_URL=$(terraform output -raw application_url) - - cd .. - - log_info "Infrastructure deployed successfully!" - log_info "Application URL: $APP_URL" -} - -# Create service account key for local development -create_service_account_key() { - log_info "Creating service account key for development..." - - SA_NAME="rothbard-flask-app" - SA_EMAIL="$SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" - - # Create service account if it doesn't exist - if ! gcloud iam service-accounts describe "$SA_EMAIL" &> /dev/null; then - gcloud iam service-accounts create "$SA_NAME" \ - --display-name="Rothbard Flask App Service Account" - fi - - # Grant necessary roles - gcloud projects add-iam-policy-binding "$PROJECT_ID" \ - --member="serviceAccount:$SA_EMAIL" \ - --role="roles/datastore.user" - - gcloud projects add-iam-policy-binding "$PROJECT_ID" \ - --member="serviceAccount:$SA_EMAIL" \ - --role="roles/firebase.admin" - - # Create key - gcloud iam service-accounts keys create ~/rothbard-service-account.json \ - --iam-account="$SA_EMAIL" - - log_info "Service account key created at ~/rothbard-service-account.json" - log_warn "Add this to your environment: export GOOGLE_APPLICATION_CREDENTIALS=~/rothbard-service-account.json" -} - -# Main deployment function -main() { - log_info "Starting Rothbard Law Group deployment..." - - # Parse command line arguments - while [[ $# -gt 0 ]]; do - case $1 in - -p|--project) - PROJECT_ID="$2" - shift 2 - ;; - -d|--domain) - DOMAIN_NAME="$2" - shift 2 - ;; - -o|--option) - HOSTING_OPTION="$2" - shift 2 - ;; - -h|--help) - echo "Usage: $0 [OPTIONS]" - echo "Options:" - echo " -p, --project PROJECT_ID GCP Project ID" - echo " -d, --domain DOMAIN_NAME Domain name (optional)" - echo " -o, --option HOSTING_OPTION Hosting option (cloud_run or app_engine)" - echo " -h, --help Show this help message" - exit 0 - ;; - *) - log_error "Unknown option: $1" - exit 1 - ;; - esac - done - - # Validate hosting option - if [[ ! "$HOSTING_OPTION" =~ ^(cloud_run|app_engine)$ ]]; then - log_error "Invalid hosting option. Use 'cloud_run' or 'app_engine'." - exit 1 - fi - - check_prerequisites - setup_project - build_and_push_image - deploy_infrastructure - create_service_account_key - - log_info "Deployment completed successfully!" - log_info "Next steps:" - log_info "1. Configure Firebase Authentication in the Firebase Console" - log_info "2. Set up Firestore security rules" - log_info "3. Enable user accounts in Firestore" - log_info "4. Configure your custom domain (if applicable)" -} - -# Run main function -main "$@" \ No newline at end of file diff --git a/terraform/deployment.tf b/terraform/deployment.tf deleted file mode 100644 index f25ba71..0000000 --- a/terraform/deployment.tf +++ /dev/null @@ -1,87 +0,0 @@ - -# Select hosting option based on variable -module "hosting" { - source = "./modules/cloud_run" - - # Common variables - app_name = "rothbard-portal" - gcp_project_id = var.gcp_project_id - gcp_region = var.gcp_region - firebase_project_id = google_firebase_project.default.project - flask_secret_key = var.flask_secret_key - service_account_email = google_service_account.flask_app.email - service_account_key_data = var.service_account_key_data - - # Filevine credentials - filevine_client_id = var.filevine_client_id - filevine_client_secret = var.filevine_client_secret - filevine_pat = var.filevine_pat - filevine_org_id = var.filevine_org_id - filevine_user_id = var.filevine_user_id - - # Module-specific variables - container_image = var.container_image -} - -# Additional variables for hosting options -variable "flask_secret_key" { - description = "Flask secret key" - type = string - sensitive = true -} - -variable "service_account_key_data" { - description = "Service account key JSON data" - type = string - sensitive = true -} - -variable "container_image" { - description = "Docker image for Cloud Run deployment" - type = string - default = "gcr.io/your-project/rothbard-portal:latest" -} - -variable "app_source_zip_path" { - description = "Path to App Engine source zip" - type = string - default = "./app-source.zip" -} - - -# Filevine credentials -variable "filevine_client_id" { - description = "Filevine client ID" - type = string - sensitive = true -} - -variable "filevine_client_secret" { - description = "Filevine client secret" - type = string - sensitive = true -} - -variable "filevine_pat" { - description = "Filevine personal access token" - type = string - sensitive = true -} - -variable "filevine_org_id" { - description = "Filevine organization ID" - type = string - sensitive = true -} - -variable "filevine_user_id" { - description = "Filevine user ID" - type = string - sensitive = true -} - -# Output hosting-specific URLs -output "application_url" { - description = "URL of the deployed application" - value = module.hosting.service_url - } diff --git a/terraform/main.tf b/terraform/main.tf deleted file mode 100644 index 3f0cf92..0000000 --- a/terraform/main.tf +++ /dev/null @@ -1,232 +0,0 @@ -terraform { - required_providers { - google-beta = { - source = "hashicorp/google-beta" - version = "~> 6.0" - } - } -} - -provider "google" { - project = var.gcp_project_id - region = var.gcp_region -} - - -# Firebase Project Setup -resource "google_firebase_project" "default" { - provider = google-beta - project = var.gcp_project_id -} - -# Firebase Web App -resource "google_firebase_web_app" "rothbard_portal" { - provider = google-beta - project = google_firebase_project.default.project - display_name = "Rothbard Client Portal" - - app_url = "https://${var.domain_name}" - - # Handle OAuth redirect - oauth_config { - client_id = var.oauth_client_id - client_secret = var.oauth_client_secret - } -} - -# Firestore Database -resource "google_firestore_database" "default" { - provider = google-beta - project = var.gcp_project_id - name = "(default)" - location_id = var.firestore_location - type = "FIRESTORE_NATIVE" - - delete_protection_state = "DISABLED" -} - -# Firebase Authentication - Complete Configuration -resource "google_identitytoolkit_config" "default" { - provider = google-beta - project = var.gcp_project_id - - sign_in_options { - email { - enabled = true - password_required = true - } - - # Disable other providers for security - phone { - enabled = false - } - - google { - enabled = var.enable_google_signin - } - - facebook { - enabled = false - } - - apple { - enabled = false - } - } - - # Email configuration - email { - reset_password_template { - from_email_address = var.auth_from_email - from_display_name = var.auth_from_name - reply_to = var.auth_reply_to - subject = "Reset your Rothbard Law Group password" - html = file("${path.module}/templates/reset_password.html") - text = file("${path.module}/templates/reset_password.txt") - } - - email_verification_template { - from_email_address = var.auth_from_email - from_display_name = var.auth_from_name - reply_to = var.auth_reply_to - subject = "Verify your Rothbard Law Group account" - html = file("${path.module}/templates/email_verification.html") - text = file("${path.module}/templates/email_verification.txt") - } - } - - # Security settings - sign_in { - allow_duplicate_emails = false - } - - # Multi-factor authentication (disabled for simplicity) - multi_factor_auth { - enabled = false - } - - # Anonymous user access (disabled) - anonymous { - enabled = false - } -} - -# Service Account for the Flask App -resource "google_service_account" "flask_app" { - account_id = "rothbard-flask-app" - display_name = "Rothbard Flask App Service Account" -} - -# IAM permissions for the Flask App -resource "google_project_iam_member" "firestore_access" { - project = var.gcp_project_id - role = "roles/datastore.user" - member = "serviceAccount:${google_service_account.flask_app.email}" -} - -resource "google_project_iam_member" "firebase_admin" { - project = var.gcp_project_id - role = "roles/firebase.admin" - member = "serviceAccount:${google_service_account.flask_app.email}" -} - -# Firestore Security Rules -resource "google_firestore_security_policy" "default" { - project = var.gcp_project_id - policy = { - rules = [ - { - description = "Allow users to read/write their own profile" - match = { - collection = "users" - document = "{userId}" - } - allow = [ - { - resource = "read" - condition = { - name = "request.auth.uid == userId" - } - }, - { - resource = "write" - condition = { - name = "request.auth.uid == userId" - } - } - ] - }, - { - description = "Only authenticated users can access the database" - match = { - collection = "{collection=**}" - } - allow = [ - { - resource = "read" - condition = { - name = "request.auth != null" - } - }, - { - resource = "write" - condition = { - name = "request.auth != null" - } - } - ] - } - ] - } -} - -# Firebase Hosting (optional - for static assets) -resource "google_firebase_hosting_site" "default" { - provider = google-beta - project = var.gcp_project_id - site_id = "rothbard-portal" - - # Default configuration for hosting - config { - public_root_dir = "public" - headers = [ - { - headers = ["Cache-Control: public, max-age=31536000"] - glob = "**/*.@(jpg|jpeg|gif|png|svg|webp)" - }, - { - headers = ["Cache-Control: public, max-age=86400"] - glob = "**/*.@(css|js)" - } - ] - redirects = [ - { - status_code = 302 - path = "/login" - location = "/login.html" - } - ] - rewrites = [ - { - glob = "**" - path = "/index.html" - } - ] - } -} - -# Output important values -output "firebase_web_app_id" { - description = "Firebase Web App ID" - value = google_firebase_web_app.rothbard_portal.app_id -} - -output "firebase_project_id" { - description = "Firebase Project ID" - value = google_firebase_project.default.project -} - -output "service_account_email" { - description = "Service account email for Flask app" - value = google_service_account.flask_app.email -} diff --git a/terraform/modules/app_engine/main.tf b/terraform/modules/app_engine/main.tf deleted file mode 100644 index a86a907..0000000 --- a/terraform/modules/app_engine/main.tf +++ /dev/null @@ -1,118 +0,0 @@ -# Enable App Engine Admin API -resource "google_project_service" "appengine" { - project = var.gcp_project_id - service = "appengine.googleapis.com" -} - -# App Engine Application -resource "google_app_engine_application" "app" { - project = var.gcp_project_id - location_id = var.gcp_region - depends_on = [google_project_service.appengine] -} - -# App Engine Service for Flask app -resource "google_app_engine_standard_app_version" "flask_app" { - project = var.gcp_project_id - service = "default" - version_id = "${var.app_name}-v1" - - runtime = "python311" - - entrypoint { - command = "gunicorn -b :$PORT app:app" - } - - deployment { - zip { - source_url = google_storage_bucket_object.app_source_zip.output_uri - } - } - - env_variables = { - FLASK_SECRET_KEY = var.flask_secret_key - FIREBASE_PROJECT_ID = var.firebase_project_id - GOOGLE_APPLICATION_CREDENTIALS = "/etc/secrets/service-account.json" - FILEVINE_CLIENT_ID = var.filevine_client_id - FILEVINE_CLIENT_SECRET = var.filevine_client_secret - FILEVINE_PERSONAL_ACCESS_TOKEN = var.filevine_pat - FILEVINE_ORG_ID = var.filevine_org_id - FILEVINE_USER_ID = var.filevine_user_id - } - - # Service account - service_account = var.service_account_email - - # Resources - resources { - cpu = 1 - memory_gb = 0.5 - disk_gb = 0.5 - } - - # Automatic scaling - automatic_scaling { - min_idle_instances = 0 - max_idle_instances = 1 - min_pending_latency = "automatic" - max_pending_latency = "automatic" - max_concurrent_requests = 80 - } - - # Health check - health_check { - enable_health_check = true - check_path = "/" - } - - depends_on = [ - google_storage_bucket_object.app_source_zip, - google_secret_manager_secret_version.service_account_key - ] -} - -# Make App Engine service publicly accessible -resource "google_app_engine_firewall_rule" "allow_all" { - project = var.gcp_project_id - action = "ALLOW" - priority = "1" - - source_range = "*" -} - -# Cloud Storage bucket for app source code -resource "google_storage_bucket" "app_source" { - name = "${var.app_name}-source-${var.gcp_project_id}" - location = var.gcp_region - force_destroy = true - - uniform_bucket_level_access = true -} - -# Upload app source code -resource "google_storage_bucket_object" "app_source_zip" { - name = "app-source.zip" - bucket = google_storage_bucket.app_source.name - source = var.app_source_zip_path -} - -# Store service account key in Secret Manager -resource "google_secret_manager_secret" "service_account_key" { - project = var.gcp_project_id - secret_id = "${var.app_name}-service-account-key" - - replication { - automatic = true - } -} - -resource "google_secret_manager_secret_version" "service_account_key" { - secret = google_secret_manager_secret.service_account_key.id - secret_data = var.service_account_key_data -} - -# Output the app URL -output "app_url" { - description = "App Engine application URL" - value = "https://${google_app_engine_application.app.default_hostname}" -} \ No newline at end of file diff --git a/terraform/modules/app_engine/variables.tf b/terraform/modules/app_engine/variables.tf deleted file mode 100644 index 9c758de..0000000 --- a/terraform/modules/app_engine/variables.tf +++ /dev/null @@ -1,71 +0,0 @@ -variable "app_name" { - description = "Name of the application" - type = string -} - -variable "gcp_project_id" { - description = "GCP Project ID" - type = string -} - -variable "gcp_region" { - description = "GCP region" - type = string -} - -variable "app_source_zip_path" { - description = "Path to the app source code zip file" - type = string -} - -variable "firebase_project_id" { - description = "Firebase project ID" - type = string -} - -variable "flask_secret_key" { - description = "Flask secret key" - type = string - sensitive = true -} - -variable "service_account_email" { - description = "Service account email for the App Engine service" - type = string -} - -variable "service_account_key_data" { - description = "Service account key JSON data" - type = string - sensitive = true -} - -variable "filevine_client_id" { - description = "Filevine client ID" - type = string - sensitive = true -} - -variable "filevine_client_secret" { - description = "Filevine client secret" - type = string - sensitive = true -} - -variable "filevine_pat" { - description = "Filevine personal access token" - type = string - sensitive = true -} - -variable "filevine_org_id" { - description = "Filevine organization ID" - type = string - sensitive = true -} - -variable "filevine_user_id" { - description = "Filevine user ID" - type = string - sensitive = true -} \ No newline at end of file diff --git a/terraform/modules/cloud_run/main.tf b/terraform/modules/cloud_run/main.tf deleted file mode 100644 index 0cefd56..0000000 --- a/terraform/modules/cloud_run/main.tf +++ /dev/null @@ -1,144 +0,0 @@ -# Cloud Run Service for Flask App -resource "google_cloud_run_service" "flask_app" { - name = "${var.app_name}-service" - location = var.gcp_region - - template { - spec { - containers { - image = var.container_image - - # Environment variables for the Flask app - env { - name = "FLASK_SECRET_KEY" - value = var.flask_secret_key - } - - env { - name = "FIREBASE_PROJECT_ID" - value = var.firebase_project_id - } - - env { - name = "GOOGLE_APPLICATION_CREDENTIALS" - value = "/etc/secrets/service-account.json" - } - - # Filevine API credentials - env { - name = "FILEVINE_CLIENT_ID" - value = var.filevine_client_id - } - - env { - name = "FILEVINE_CLIENT_SECRET" - value = var.filevine_client_secret - } - - env { - name = "FILEVINE_PERSONAL_ACCESS_TOKEN" - value = var.filevine_pat - } - - env { - name = "FILEVINE_ORG_ID" - value = var.filevine_org_id - } - - env { - name = "FILEVINE_USER_ID" - value = var.filevine_user_id - } - - # Memory and CPU limits - resources { - limits = { - cpu = "1000m" - memory = "512Mi" - } - } - - # Mount service account key - volume_mount { - name = "service-account-key" - mount_path = "/etc/secrets" - read_only = true - } - } - - # Service account for the container - service_account_name = var.service_account_email - - # Volumes - volumes { - name = "service-account-key" - secret { - secret_name = google_secret_manager_secret.service_account_key.secret_id - items { - key = "latest" - path = "service-account.json" - } - } - } - - # Allow unauthenticated access - container_concurrency = 100 - timeout_seconds = 300 - } - - # Traffic settings - metadata { - annotations = { - "autoscaling.knative.dev/maxScale" = "10" - "autoscaling.knative.dev/minScale" = "1" - "run.googleapis.com/ingress" = "all" - } - } - } - - traffic { - percent = 100 - latest_revision = true - } - - depends_on = [google_secret_manager_secret_version.service_account_key] -} - -# Make Cloud Run service publicly accessible -resource "google_cloud_run_service_iam_member" "public" { - location = google_cloud_run_service.flask_app.location - project = google_cloud_run_service.flask_app.project - service = google_cloud_run_service.flask_app.name - role = "roles/run.invoker" - member = "allUsers" -} - -# Store service account key in Secret Manager -resource "google_secret_manager_secret" "service_account_key" { - project = var.gcp_project_id - secret_id = "${var.app_name}-service-account-key" - - replication { - automatic = true - } -} - -resource "google_secret_manager_secret_version" "service_account_key" { - secret = google_secret_manager_secret.service_account_key.id - secret_data = var.service_account_key_data -} - -# Cloud Storage bucket for container storage (if needed) -resource "google_storage_bucket" "app_storage" { - name = "${var.app_name}-storage-${var.gcp_project_id}" - location = var.gcp_region - force_destroy = true - - uniform_bucket_level_access = true -} - -# Output the service URL -output "service_url" { - description = "Cloud Run service URL" - value = google_cloud_run_service.flask_app.status[0].url -} \ No newline at end of file diff --git a/terraform/modules/cloud_run/variables.tf b/terraform/modules/cloud_run/variables.tf deleted file mode 100644 index e202369..0000000 --- a/terraform/modules/cloud_run/variables.tf +++ /dev/null @@ -1,71 +0,0 @@ -variable "app_name" { - description = "Name of the application" - type = string -} - -variable "gcp_project_id" { - description = "GCP Project ID" - type = string -} - -variable "gcp_region" { - description = "GCP region" - type = string -} - -variable "container_image" { - description = "Docker image for the Flask app" - type = string -} - -variable "firebase_project_id" { - description = "Firebase project ID" - type = string -} - -variable "flask_secret_key" { - description = "Flask secret key" - type = string - sensitive = true -} - -variable "service_account_email" { - description = "Service account email for the Cloud Run service" - type = string -} - -variable "service_account_key_data" { - description = "Service account key JSON data" - type = string - sensitive = true -} - -variable "filevine_client_id" { - description = "Filevine client ID" - type = string - sensitive = true -} - -variable "filevine_client_secret" { - description = "Filevine client secret" - type = string - sensitive = true -} - -variable "filevine_pat" { - description = "Filevine personal access token" - type = string - sensitive = true -} - -variable "filevine_org_id" { - description = "Filevine organization ID" - type = string - sensitive = true -} - -variable "filevine_user_id" { - description = "Filevine user ID" - type = string - sensitive = true -} \ No newline at end of file diff --git a/terraform/templates/email_verification.html b/terraform/templates/email_verification.html deleted file mode 100644 index 00a628b..0000000 --- a/terraform/templates/email_verification.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - Verify Your Email - Rothbard Law Group - - - -
-

Rothbard Law Group

-

Client Portal

-
- -
-

Welcome to the Rothbard Law Group Client Portal

- -
-

Thank you for signing up!

-

You're just one step away from accessing your case information securely.

-
- -

Please verify your email address to complete your registration:

- -

Verify Email Address

- -

Or copy and paste this link into your browser:

-

{{ verificationLink }}

- -

What happens next?

- - -

Important:

- - -

If you have any questions or need assistance, please contact our support team.

-
- - - - \ No newline at end of file diff --git a/terraform/templates/email_verification.txt b/terraform/templates/email_verification.txt deleted file mode 100644 index ada70c7..0000000 --- a/terraform/templates/email_verification.txt +++ /dev/null @@ -1,31 +0,0 @@ -Rothbard Law Group - Email Verification - -Welcome to Rothbard Law Group Client Portal! - -Thank you for signing up for our client portal. You're just one step away from accessing your case information securely. - -Please verify your email address to complete your registration: -{{ verificationLink }} - -If the button doesn't work, you can copy and paste this link into your browser. - -What happens next? -- Once verified, you'll have full access to the client portal -- You can view your case information and documents -- Communicate securely with our legal team - -Important Information: -- This verification link will expire in 24 hours -- If you didn't create an account, please ignore this email -- Your account information is kept secure and confidential - -If you have any questions or need assistance, please contact our support team. - -Thank you for choosing Rothbard Law Group. - ---- -Rothbard Law Group -123 Legal Street -City, State 12345 -(555) 123-4567 -support@rothbardlaw.com \ No newline at end of file diff --git a/terraform/templates/reset_password.html b/terraform/templates/reset_password.html deleted file mode 100644 index b362e9d..0000000 --- a/terraform/templates/reset_password.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - Reset Your Password - Rothbard Law Group - - - -
-

Rothbard Law Group

-

Client Portal

-
- -
-

Reset Your Password

- -

Hello,

- -

We received a request to reset the password for your Rothbard Law Group client portal account. Click the button below to reset your password:

- -

Reset Password

- -

Or copy and paste this link into your browser:

-

{{ resetLink }}

- -

Important:

- - -

If you have any questions or need assistance, please contact our support team.

-
- - - - \ No newline at end of file diff --git a/terraform/templates/reset_password.txt b/terraform/templates/reset_password.txt deleted file mode 100644 index 54c362f..0000000 --- a/terraform/templates/reset_password.txt +++ /dev/null @@ -1,27 +0,0 @@ -Rothbard Law Group - Password Reset - -Hello, - -We received a request to reset your password for your Rothbard Law Group client portal account. - -To reset your password, please visit this link: -{{ resetLink }} - -If the button doesn't work, you can copy and paste the link into your browser. - -Important Information: -- This link will expire in 24 hours -- If you didn't request a password reset, please ignore this email -- For security reasons, never share this link with anyone - -If you have any questions or need assistance, please contact our support team. - -Thank you, -Rothbard Law Group - ---- -Rothbard Law Group -123 Legal Street -City, State 12345 -(555) 123-4567 -support@rothbardlaw.com \ No newline at end of file diff --git a/terraform/terraform.staging.tfvars b/terraform/terraform.staging.tfvars deleted file mode 100644 index 35f8e7f..0000000 --- a/terraform/terraform.staging.tfvars +++ /dev/null @@ -1,9 +0,0 @@ -# Copy this file to terraform.tfvars and fill in your values -gcp_project_id = "811764775573" -domain_name = "rothbard.yourdomain.com" - -# Optional: Override defaults -gcp_region = "us-central1" -firestore_location = "us-central1" -hosting_option = "cloud_run" # Options: cloud_run, app_engine, gcs -environment = "staging" diff --git a/terraform/terraform.tfvars.example b/terraform/terraform.tfvars.example deleted file mode 100644 index 5dce2d0..0000000 --- a/terraform/terraform.tfvars.example +++ /dev/null @@ -1,9 +0,0 @@ -# Copy this file to terraform.tfvars and fill in your values -gcp_project_id = "your-gcp-project-id" -domain_name = "rothbard.yourdomain.com" - -# Optional: Override defaults -# gcp_region = "us-central1" -# firestore_location = "us-central1" -# hosting_option = "cloud_run" # Options: cloud_run, app_engine, gcs -# environment = "production" \ No newline at end of file diff --git a/terraform/variables.tf b/terraform/variables.tf deleted file mode 100644 index fc13bb3..0000000 --- a/terraform/variables.tf +++ /dev/null @@ -1,76 +0,0 @@ -variable "gcp_project_id" { - description = "GCP Project ID for the deployment" - type = string -} - -variable "gcp_region" { - description = "GCP region for resources" - type = string - default = "us-central1" -} - -variable "firestore_location" { - description = "Location for Firestore database" - type = string - default = "us-central1" -} - -variable "domain_name" { - description = "Domain name for the application" - type = string - default = "rothbard-portal.example.com" -} - -variable "oauth_client_id" { - description = "OAuth client ID for Firebase" - type = string - default = "" -} - -variable "oauth_client_secret" { - description = "OAuth client secret for Firebase" - type = string - default = "" - sensitive = true -} - -variable "hosting_option" { - description = "Hosting option for the Flask app" - type = string - default = "cloud_run" - validation { - condition = contains(["cloud_run", "app_engine"], var.hosting_option) - error_message = "The hosting_option must be one of: cloud_run, app_engine." - } -} - -variable "environment" { - description = "Environment tag" - type = string - default = "production" -} - -# Firebase Authentication Configuration -variable "enable_google_signin" { - description = "Enable Google Sign-In authentication provider" - type = bool - default = false -} - -variable "auth_from_email" { - description = "From email address for authentication emails" - type = string - default = "noreply@rothbardlaw.com" -} - -variable "auth_from_name" { - description = "From display name for authentication emails" - type = string - default = "Rothbard Law Group" -} - -variable "auth_reply_to" { - description = "Reply-to email address for authentication emails" - type = string - default = "support@rothbardlaw.com" -} \ No newline at end of file