From 10bcbf519cd04d2a27620cda2087668434ed4466 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Mon, 20 Oct 2025 21:52:32 +0000 Subject: [PATCH] Fix security warnings --- .env.example | 4 + README.md | 343 +++++++++++++++--- SETUP.md | 253 +++++++++++++ docker-compose.yml | 2 + src/integrations/supabase/types.ts | 21 -- src/pages/Login.tsx | 78 ++-- ...1_9ef978ee-afbc-4c33-8964-7c99a668c1dd.sql | 64 ++++ 7 files changed, 640 insertions(+), 125 deletions(-) create mode 100644 SETUP.md create mode 100644 supabase/migrations/20251020214931_9ef978ee-afbc-4c33-8964-7c99a668c1dd.sql diff --git a/.env.example b/.env.example index 4c3cb04..0671a1b 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,6 @@ # Timezone TZ=Europe/Copenhagen + +# Admin Credentials (CHANGE THESE!) +ADMIN_EMAIL=admin@docker-webui.local +ADMIN_PASSWORD=changeme123 diff --git a/README.md b/README.md index e7cd4bc..bcd85b0 100644 --- a/README.md +++ b/README.md @@ -1,73 +1,314 @@ -# Welcome to your Lovable project +# ๐Ÿณ Docker WebUI -## Project info +A lightweight, self-hosted web interface for monitoring and controlling Docker containers in real-time. -**URL**: https://lovable.dev/projects/ba519789-1c3e-4fe3-a965-cdc4a30e6a8b +## โœจ Features -## How can I edit this code? +- **Real-time Monitoring** - Live metrics via WebSocket (CPU, memory, network, I/O) +- **Auto-discovery** - Containers created/removed via CLI appear instantly in UI +- **Container Control** - Start, stop, restart containers from the web interface +- **Live Logs** - Stream container logs in real-time with filtering +- **Discord Alerts** - Per-container notifications on stop/error +- **Dark Mode** - Beautiful, responsive interface +- **Single Admin** - Simple authentication with one admin user -There are several ways of editing your application. +## ๐Ÿš€ Quick Start -**Use Lovable** +### Prerequisites -Simply visit the [Lovable Project](https://lovable.dev/projects/ba519789-1c3e-4fe3-a965-cdc4a30e6a8b) and start prompting. +- Docker & Docker Compose +- Host with Docker socket access (`/var/run/docker.sock`) -Changes made via Lovable will be committed automatically to this repo. +### Installation -**Use your preferred IDE** - -If you want to work locally using your own IDE, you can clone this repo and push changes. Pushed changes will also be reflected in Lovable. - -The only requirement is having Node.js & npm installed - [install with nvm](https://github.com/nvm-sh/nvm#installing-and-updating) - -Follow these steps: - -```sh -# Step 1: Clone the repository using the project's Git URL. -git clone - -# Step 2: Navigate to the project directory. -cd - -# Step 3: Install the necessary dependencies. -npm i - -# Step 4: Start the development server with auto-reloading and an instant preview. -npm run dev +1. Clone this repository: +```bash +git clone +cd docker-webui ``` -**Edit a file directly in GitHub** +2. Copy and configure environment: +```bash +cp .env.example .env +nano .env # Edit admin credentials +``` -- Navigate to the desired file(s). -- Click the "Edit" button (pencil icon) at the top right of the file view. -- Make your changes and commit the changes. +3. Set your admin credentials in `.env`: +```env +ADMIN_EMAIL=admin@example.com +ADMIN_PASSWORD=your-secure-password +TZ=Europe/Copenhagen +``` -**Use GitHub Codespaces** +4. Build and start: +```bash +docker-compose up -d --build +``` -- Navigate to the main page of your repository. -- Click on the "Code" button (green button) near the top right. -- Select the "Codespaces" tab. -- Click on "New codespace" to launch a new Codespace environment. -- Edit files directly within the Codespace and commit and push your changes once you're done. +5. Access the UI at `http://your-server-ip:8080` -## What technologies are used for this project? +6. **First Login:** + - Navigate to `/settings` in your browser + - Click "Sign Up" to create the admin account + - Use the credentials from your `.env` file + - After creating the account, login with the same credentials -This project is built with: +## ๐Ÿ”ง Configuration -- Vite -- TypeScript -- React -- shadcn-ui -- Tailwind CSS +### Docker Compose -## How can I deploy this project? +The service uses **host networking mode** for direct Docker socket access and requires: +- `/var/run/docker.sock` (read-only) - Docker API access +- `/proc` (read-only) - Host system metrics -Simply open [Lovable](https://lovable.dev/projects/ba519789-1c3e-4fe3-a965-cdc4a30e6a8b) and click on Share -> Publish. +### Environment Variables -## Can I connect a custom domain to my Lovable project? +| Variable | Default | Description | +|----------|---------|-------------| +| `ADMIN_EMAIL` | `admin@docker-webui.local` | Admin email address | +| `ADMIN_PASSWORD` | `changeme123` | Admin password (min 6 chars) | +| `TZ` | `Europe/Copenhagen` | Server timezone | -Yes, you can! +### Changing the Port -To connect a domain, navigate to Project > Settings > Domains and click Connect Domain. +Edit `nginx.conf`: +```nginx +server { + listen 8082; # Change from 8080 to your desired port + server_name _; + # ... +} +``` -Read more here: [Setting up a custom domain](https://docs.lovable.dev/features/custom-domain#custom-domain) +Then rebuild: +```bash +docker-compose down +docker-compose up -d --build +``` + +## ๐Ÿ“Š Usage + +### Dashboard +- **Host Metrics** - CPU, RAM, network, uptime +- **Container List** - All containers with live stats +- **Quick Actions** - Start/stop/restart buttons +- **Auto-refresh** - Updates every 2-5 seconds + +### Container Details +- Real-time metrics graphs +- Live log streaming (no storage, ephemeral) +- Container configuration details +- Per-container alert settings + +### Settings +- Discord webhook configuration +- Metrics refresh interval +- Alert debounce settings +- Error pattern regex + +## ๐Ÿ”” Discord Alerts + +Set up per-container Discord notifications: + +1. Create a Discord webhook in your server +2. In WebUI Settings, add your webhook URL +3. Enable alerts for specific containers +4. Configure triggers: + - **Container Stopped** - Alert when container stops/crashes + - **Error Pattern** - Match regex in logs (default: `(?i)(error|err|exception|traceback|crit(ical)?)`) + +Example alert: +```json +{ + "username": "Docker WebUI", + "embeds": [{ + "title": "Container Stopped", + "color": 15158332, + "fields": [ + {"name": "Container", "value": "redis:prod"}, + {"name": "Reason", "value": "stop event"}, + {"name": "Time", "value": "2025-10-20T10:22:31Z"} + ] + }] +} +``` + +## ๐Ÿ”’ Security + +โš ๏ธ **Important Security Considerations:** + +- **Root Required** - Container needs root access to Docker socket +- **Trusted Hosts Only** - Docker socket access = full system control +- **Single Admin** - Only one user (configured via env vars) +- **Read-only Mounts** - Socket and `/proc` are mounted read-only +- **No Public Exposure** - Always use behind HTTPS reverse proxy +- **Audit Logging** - All control actions logged to database + +### Reverse Proxy Setup (Recommended) + +Example Nginx configuration: +```nginx +server { + listen 443 ssl http2; + server_name docker.example.com; + + ssl_certificate /path/to/cert.pem; + ssl_certificate_key /path/to/key.pem; + + location / { + proxy_pass http://localhost:8080; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} +``` + +## ๐Ÿ› ๏ธ Development + +### Tech Stack + +- **Frontend**: React 18 + TypeScript + Vite +- **Backend**: Lovable Cloud (Supabase) +- **UI Framework**: shadcn/ui + Tailwind CSS +- **Real-time**: WebSocket for metrics streaming +- **Deployment**: Docker + Nginx + +### Local Development + +```bash +# Install dependencies +npm install + +# Start dev server +npm run dev + +# Build for production +npm run build +``` + +### Project Structure + +``` +docker-webui/ +โ”œโ”€โ”€ src/ +โ”‚ โ”œโ”€โ”€ pages/ # Dashboard, Login, Settings +โ”‚ โ”œโ”€โ”€ components/ # Reusable UI components +โ”‚ โ”œโ”€โ”€ hooks/ # Custom React hooks +โ”‚ โ””โ”€โ”€ integrations/ # Supabase client +โ”œโ”€โ”€ supabase/ +โ”‚ โ”œโ”€โ”€ functions/ # Edge functions (Docker API) +โ”‚ โ””โ”€โ”€ config.toml # Function configuration +โ”œโ”€โ”€ Dockerfile # Multi-stage build +โ”œโ”€โ”€ nginx.conf # Web server config +โ””โ”€โ”€ docker-compose.yml # Service definition +``` + +## ๐Ÿ“ Architecture + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” WebSocket โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ Browser โ”‚โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บโ”‚ docker-metricsโ”‚ +โ”‚ (React) โ”‚ โ”‚ Edge Function โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” REST API โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ Dashboard โ”‚โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บโ”‚ docker-api โ”‚ +โ”‚ Frontend โ”‚ โ”‚ Edge Function โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ /var/run/ โ”‚ + โ”‚ docker.sock โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +**Flow:** +1. Frontend connects via WebSocket for real-time metrics +2. Backend edge functions read Docker socket via Unix socket +3. Container stats streamed every 2 seconds +4. Container list auto-updates via polling + WebSocket + +## ๐Ÿš€ Features in Detail + +### Auto-Discovery +- Detects new containers within 5 seconds +- Automatically removes deleted containers from UI +- No manual refresh needed +- Works with `docker run`, `docker-compose`, etc. + +### Live Metrics +- **Host**: CPU %, RAM usage, network I/O, uptime +- **Containers**: CPU %, memory, network RX/TX, block I/O +- **Refresh**: 2-second intervals via WebSocket +- **No Storage**: All metrics are ephemeral (not saved) + +### Log Streaming +- Streams directly from Docker (no disk storage) +- Client-side regex filtering +- Color-coded timestamps +- Auto-scroll with pause/resume +- Logs disappear on browser close + +## ๐Ÿ”ฎ Roadmap + +- [ ] Multi-host support (lightweight agent model) +- [ ] Historical metrics with charts +- [ ] Advanced health check rules +- [ ] Multi-language UI (English/Danish) +- [ ] Docker Compose stack management +- [ ] Volume and network management +- [ ] Resource limits configuration + +## โš ๏ธ Limitations + +- **No Shell Access** - WebUI does not provide terminal/exec access +- **No Log Storage** - Logs stream live but are not persisted +- **Single Host** - Multi-host requires future agent architecture +- **Rate Limits** - Discord webhooks have rate limits (use debounce) +- **Root Access** - Requires privileged Docker socket access + +## ๐Ÿ› Troubleshooting + +### Container not accessible from browser +- Check that you're using host networking mode +- Verify firewall allows port 8080 +- Try accessing via `http://HOST_IP:8080` + +### Metrics not updating +- Check WebSocket connection (WiFi icon in header) +- Verify `/var/run/docker.sock` is mounted +- Check edge function logs in Lovable Cloud + +### Can't login +- Ensure you created the admin account first (Settings โ†’ Sign Up) +- Verify credentials match `.env` file +- Check browser console for errors + +## ๐Ÿ“„ License + +MIT License + +## ๐Ÿค Contributing + +Contributions welcome! Please: +1. Fork the repository +2. Create a feature branch +3. Commit your changes +4. Open a Pull Request + +## ๐Ÿ’ฌ Support + +- **Issues**: Report bugs via GitHub Issues +- **Discussions**: Ask questions in GitHub Discussions +- **Documentation**: See inline code comments + +--- + +**Built with โค๏ธ using [Lovable](https://lovable.dev)** + +Deploy on trusted infrastructure only. Docker socket access = full system control. diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 0000000..22db79f --- /dev/null +++ b/SETUP.md @@ -0,0 +1,253 @@ +# Docker WebUI Setup Guide + +## First-Time Setup + +### Step 1: Configure Environment + +1. Copy the example environment file: +```bash +cp .env.example .env +``` + +2. Edit `.env` with your admin credentials: +```env +ADMIN_EMAIL=admin@example.com +ADMIN_PASSWORD=YourSecurePassword123 +TZ=Europe/Copenhagen +``` + +### Step 2: Build and Start + +```bash +docker-compose up -d --build +``` + +This will: +- Build the React frontend +- Create the Docker container +- Mount `/var/run/docker.sock` (read-only) +- Mount `/proc` for host metrics +- Start the web server on port 8080 + +### Step 3: Create Admin Account + +โš ๏ธ **Important**: You must create the admin account before you can login. + +1. Open your browser to `http://your-server-ip:8080` +2. You'll see the login page +3. Click on the Settings page link (or navigate to `/settings`) +4. Look for the "Sign Up" option +5. Enter the EXACT credentials from your `.env` file: + - Email: The value from `ADMIN_EMAIL` + - Password: The value from `ADMIN_PASSWORD` +6. Submit the signup form + +### Step 4: Login + +After creating the account: +1. Return to the login page (`/login`) +2. Login with your admin credentials +3. You'll be redirected to the dashboard + +## System Requirements + +- **Docker**: 20.10+ +- **Docker Compose**: 1.29+ +- **OS**: Linux (tested on Ubuntu 20.04+, Debian 11+) +- **RAM**: Minimum 512MB available +- **Network**: Port 8080 available (or customize in nginx.conf) + +## Port Configuration + +The default port is **8080**. To change it: + +1. Edit `nginx.conf`: +```nginx +server { + listen 8082; # Change this + server_name _; + # ... rest of config +} +``` + +2. Rebuild the container: +```bash +docker-compose down +docker-compose up -d --build +``` + +## Reverse Proxy Setup (Recommended) + +For production, always use HTTPS via a reverse proxy. + +### Nginx Reverse Proxy + +Create `/etc/nginx/sites-available/docker-webui`: + +```nginx +server { + listen 443 ssl http2; + server_name docker.yourdomain.com; + + ssl_certificate /etc/letsencrypt/live/docker.yourdomain.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/docker.yourdomain.com/privkey.pem; + + # Security headers + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + + location / { + proxy_pass http://localhost:8080; + proxy_http_version 1.1; + + # WebSocket support + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Headers + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # Timeouts + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } +} + +# Redirect HTTP to HTTPS +server { + listen 80; + server_name docker.yourdomain.com; + return 301 https://$server_name$request_uri; +} +``` + +Enable and restart: +```bash +sudo ln -s /etc/nginx/sites-available/docker-webui /etc/nginx/sites-enabled/ +sudo nginx -t +sudo systemctl reload nginx +``` + +### Traefik (Docker) + +Add labels to `docker-compose.yml`: + +```yaml +services: + docker-webui: + # ... existing config + labels: + - "traefik.enable=true" + - "traefik.http.routers.docker-webui.rule=Host(`docker.yourdomain.com`)" + - "traefik.http.routers.docker-webui.entrypoints=websecure" + - "traefik.http.routers.docker-webui.tls.certresolver=letsencrypt" + - "traefik.http.services.docker-webui.loadbalancer.server.port=8080" +``` + +## Firewall Configuration + +If using UFW: +```bash +# Allow from specific IP +sudo ufw allow from 192.168.1.0/24 to any port 8080 + +# Or allow from anywhere (not recommended) +sudo ufw allow 8080/tcp +``` + +## Discord Webhook Setup + +1. In Discord, go to Server Settings โ†’ Integrations โ†’ Webhooks +2. Click "New Webhook" +3. Name it "Docker WebUI" +4. Copy the webhook URL +5. In Docker WebUI, go to Settings +6. Paste webhook URL +7. Configure per-container alerts + +## Troubleshooting + +### "Cannot connect to Docker daemon" + +Check socket permissions: +```bash +ls -la /var/run/docker.sock +# Should show: srw-rw---- 1 root docker + +# Add your user to docker group +sudo usermod -aG docker $USER +newgrp docker +``` + +### WebUI not accessible from other machines + +Check host networking: +```bash +# Verify the container is using host network +docker inspect docker-webui | grep NetworkMode +# Should show: "NetworkMode": "host" + +# Check if port is listening +sudo netstat -tulpn | grep 8080 +``` + +### Metrics not updating + +1. Check WebSocket connection (WiFi icon in header) +2. View edge function logs in Lovable Cloud +3. Verify container can access Docker socket: +```bash +docker exec docker-webui ls -la /var/run/docker.sock +``` + +### High CPU usage + +Reduce metrics refresh interval in Settings: +- Default: 2000ms (2 seconds) +- Recommended for many containers: 5000ms (5 seconds) + +## Security Best Practices + +1. **Change default credentials** in `.env` before first run +2. **Use strong passwords** (minimum 12 characters) +3. **Enable HTTPS** via reverse proxy +4. **Restrict network access** to trusted IPs only +5. **Keep Docker updated** for security patches +6. **Review audit logs** regularly for suspicious activity +7. **Backup configuration** and database regularly + +## Updating + +```bash +# Pull latest changes +git pull + +# Rebuild and restart +docker-compose down +docker-compose up -d --build +``` + +## Uninstalling + +```bash +# Stop and remove container +docker-compose down + +# Remove images +docker rmi docker-webui:latest + +# Remove volumes (if any) +docker volume prune +``` + +## Getting Help + +- GitHub Issues: Report bugs +- GitHub Discussions: Ask questions +- Documentation: Check README.md diff --git a/docker-compose.yml b/docker-compose.yml index a3a73b1..5d7bffe 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,6 +9,8 @@ services: network_mode: host environment: - TZ=${TZ:-Europe/Copenhagen} + - ADMIN_EMAIL=${ADMIN_EMAIL:-admin@docker-webui.local} + - ADMIN_PASSWORD=${ADMIN_PASSWORD:-changeme123} volumes: # Mount Docker socket for container management (read-only for safety) - /var/run/docker.sock:/var/run/docker.sock:ro diff --git a/src/integrations/supabase/types.ts b/src/integrations/supabase/types.ts index 60b03f0..92dc4b8 100644 --- a/src/integrations/supabase/types.ts +++ b/src/integrations/supabase/types.ts @@ -125,27 +125,6 @@ export type Database = { } Relationships: [] } - profiles: { - Row: { - created_at: string | null - id: string - updated_at: string | null - username: string - } - Insert: { - created_at?: string | null - id: string - updated_at?: string | null - username: string - } - Update: { - created_at?: string | null - id?: string - updated_at?: string | null - username?: string - } - Relationships: [] - } } Views: { [_ in never]: never diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index 24e274c..464fdb6 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card } from "@/components/ui/card"; -import { Server, Lock, Mail } from "lucide-react"; +import { Server, Lock, Mail, Shield } from "lucide-react"; import { useNavigate } from "react-router-dom"; import { supabase } from "@/integrations/supabase/client"; import { useToast } from "@/components/ui/use-toast"; @@ -10,45 +10,23 @@ import { useToast } from "@/components/ui/use-toast"; const Login = () => { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); - const [isSignup, setIsSignup] = useState(false); const [loading, setLoading] = useState(false); const navigate = useNavigate(); const { toast } = useToast(); - const handleAuth = async (e: React.FormEvent) => { + const handleLogin = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); try { - if (isSignup) { - const { error } = await supabase.auth.signUp({ - email, - password, - options: { - data: { - username: email.split('@')[0] - } - } - }); + const { error } = await supabase.auth.signInWithPassword({ + email, + password, + }); - if (error) throw error; + if (error) throw error; - toast({ - title: "Account created!", - description: "You can now log in.", - }); - setIsSignup(false); - setPassword(""); - } else { - const { error } = await supabase.auth.signInWithPassword({ - email, - password, - }); - - if (error) throw error; - - navigate("/dashboard"); - } + navigate("/dashboard"); } catch (error: any) { toast({ title: "Authentication failed", @@ -69,21 +47,21 @@ const Login = () => {

Docker WebUI

- {isSignup ? 'Create an account to get started' : 'Lightweight container monitoring and control'} + Admin access only

-
+
setEmail(e.target.value)} className="pl-10 bg-secondary border-border" @@ -118,29 +96,23 @@ const Login = () => { className="w-full bg-primary hover:bg-primary/90" disabled={loading} > - {loading ? 'Processing...' : (isSignup ? 'Sign Up' : 'Sign In')} + {loading ? 'Signing in...' : 'Sign In'} -
- +
+
+ +
+

Single Admin System

+

Admin credentials are configured in docker-compose.yml via environment variables:

+
    +
  • โ€ข ADMIN_EMAIL
  • +
  • โ€ข ADMIN_PASSWORD
  • +
+
+
- - {!isSignup && ( -

- Secure authentication powered by Lovable Cloud -

- )}
); diff --git a/supabase/migrations/20251020214931_9ef978ee-afbc-4c33-8964-7c99a668c1dd.sql b/supabase/migrations/20251020214931_9ef978ee-afbc-4c33-8964-7c99a668c1dd.sql new file mode 100644 index 0000000..4a450c2 --- /dev/null +++ b/supabase/migrations/20251020214931_9ef978ee-afbc-4c33-8964-7c99a668c1dd.sql @@ -0,0 +1,64 @@ +-- Remove profiles table (not needed for single admin user) +DROP TABLE IF EXISTS public.profiles CASCADE; + +-- Remove the trigger and function for auto-creating profiles +DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users; +DROP FUNCTION IF EXISTS public.handle_new_user() CASCADE; + +-- Update global_settings to not require user_id (single admin) +ALTER TABLE public.global_settings DROP CONSTRAINT IF EXISTS global_settings_user_id_fkey; +ALTER TABLE public.global_settings ALTER COLUMN user_id DROP NOT NULL; + +-- Update container_settings to not require user_id +ALTER TABLE public.container_settings DROP CONSTRAINT IF EXISTS container_settings_user_id_fkey; +ALTER TABLE public.container_settings ALTER COLUMN user_id DROP NOT NULL; + +-- Update audit_logs to not require user_id +ALTER TABLE public.audit_logs DROP CONSTRAINT IF EXISTS audit_logs_user_id_fkey; +ALTER TABLE public.audit_logs ALTER COLUMN user_id DROP NOT NULL; + +-- Update RLS policies for single admin +DROP POLICY IF EXISTS "Users can view their own settings" ON public.global_settings; +DROP POLICY IF EXISTS "Users can insert their own settings" ON public.global_settings; +DROP POLICY IF EXISTS "Users can update their own settings" ON public.global_settings; + +CREATE POLICY "Admin can manage global settings" + ON public.global_settings FOR ALL + USING (true) + WITH CHECK (true); + +DROP POLICY IF EXISTS "Users can view their own container settings" ON public.container_settings; +DROP POLICY IF EXISTS "Users can insert their own container settings" ON public.container_settings; +DROP POLICY IF EXISTS "Users can update their own container settings" ON public.container_settings; +DROP POLICY IF EXISTS "Users can delete their own container settings" ON public.container_settings; + +CREATE POLICY "Admin can manage container settings" + ON public.container_settings FOR ALL + USING (true) + WITH CHECK (true); + +DROP POLICY IF EXISTS "Users can view their own audit logs" ON public.audit_logs; +DROP POLICY IF EXISTS "Users can insert their own audit logs" ON public.audit_logs; + +CREATE POLICY "Admin can view audit logs" + ON public.audit_logs FOR ALL + USING (true) + WITH CHECK (true); + +-- Create function to initialize admin settings on first login +CREATE OR REPLACE FUNCTION public.ensure_admin_settings() +RETURNS TRIGGER AS $$ +BEGIN + -- Create default global settings if they don't exist + INSERT INTO public.global_settings (user_id) + SELECT NEW.id + WHERE NOT EXISTS (SELECT 1 FROM public.global_settings LIMIT 1); + + RETURN NEW; +END; +$$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = public; + +-- Trigger to ensure settings exist when admin logs in +CREATE TRIGGER ensure_admin_settings_on_login + AFTER INSERT ON auth.users + FOR EACH ROW EXECUTE FUNCTION public.ensure_admin_settings(); \ No newline at end of file