diff --git a/Dockerfile b/Dockerfile index acf746a5..2f485df9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,7 @@ WORKDIR /app/backend RUN apk add --no-cache gcc musl-dev sqlite-dev # Install Delve so we can attach during debugging -RUN go install github.com/go-delve/delve/cmd/dlv@v1.22.0 +RUN go install github.com/go-delve/delve/cmd/dlv@latest # Copy Go module files COPY backend/go.mod backend/go.sum ./ @@ -50,7 +50,9 @@ ARG VCS_REF=unknown ARG BUILD_DATE=unknown # Build the Go binary with version information injected via ldflags +# -gcflags "all=-N -l" disables optimizations and inlining for better debugging RUN CGO_ENABLED=1 GOOS=linux go build \ + -gcflags "all=-N -l" \ -a -installsuffix cgo \ -ldflags "-X github.com/Wikid82/CaddyProxyManagerPlus/backend/internal/version.SemVer=${VERSION} \ -X github.com/Wikid82/CaddyProxyManagerPlus/backend/internal/version.GitCommit=${VCS_REF} \ diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index ce8ee4d2..7f582eb9 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -4,7 +4,7 @@ version: '3.9' services: app: - image: ghcr.io/wikid82/caddyproxymanagerplus:dev + image: ghcr.io/wikid82/cpmp:dev # Development: expose Caddy admin API externally for debugging ports: - "80:80" diff --git a/docker-compose.local.yml b/docker-compose.local.yml index 3b60453c..02b1de54 100644 --- a/docker-compose.local.yml +++ b/docker-compose.local.yml @@ -3,7 +3,7 @@ version: '3.9' services: app: image: cpmp:local - container_name: caddyproxymanagerplus-local + container_name: cpmp-debug restart: unless-stopped ports: - "80:80" # HTTP (Caddy proxy) diff --git a/docker-compose.yml b/docker-compose.yml index 559c1ec7..8e7a70f5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,8 +2,8 @@ version: '3.9' services: app: - image: ghcr.io/wikid82/caddyproxymanagerplus:latest - container_name: caddyproxymanagerplus + image: ghcr.io/wikid82/cpmp:latest + container_name: cpmp restart: unless-stopped ports: - "80:80" # HTTP (Caddy proxy) diff --git a/frontend/src/index.css b/frontend/src/index.css index 24c02a53..d8255eac 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -1,6 +1,5 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; +@import "tailwindcss"; +@config "../tailwind.config.js"; @layer utilities { @keyframes slide-in { diff --git a/frontend/src/pages/Login.tsx b/frontend/src/pages/Login.tsx index 4bb99c2b..a1ef5e08 100644 --- a/frontend/src/pages/Login.tsx +++ b/frontend/src/pages/Login.tsx @@ -1,20 +1,35 @@ -import { useState } from 'react' +import { useState, useEffect } from 'react' import { useNavigate } from 'react-router-dom' +import { useQuery, useQueryClient } from '@tanstack/react-query' import { Card } from '../components/ui/Card' import { Input } from '../components/ui/Input' import { Button } from '../components/ui/Button' import { toast } from '../components/Toast' import client from '../api/client' import { useAuth } from '../context/AuthContext' +import { getSetupStatus } from '../api/setup' export default function Login() { const navigate = useNavigate() + const queryClient = useQueryClient() const [email, setEmail] = useState('') const [password, setPassword] = useState('') const [loading, setLoading] = useState(false) const [showResetInfo, setShowResetInfo] = useState(false) const { login } = useAuth() + const { data: setupStatus, isLoading: isCheckingSetup } = useQuery({ + queryKey: ['setupStatus'], + queryFn: getSetupStatus, + retry: false, + }) + + useEffect(() => { + if (setupStatus?.setupRequired) { + navigate('/setup') + } + }, [setupStatus, navigate]) + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() setLoading(true) @@ -22,6 +37,7 @@ export default function Login() { try { await client.post('/auth/login', { email, password }) await login() + await queryClient.invalidateQueries({ queryKey: ['setupStatus'] }) toast.success('Logged in successfully') navigate('/') } catch (err: any) { @@ -31,6 +47,14 @@ export default function Login() { } } + if (isCheckingSetup) { + return ( +
+
Checking setup status...
+
+ ) + } + return (
diff --git a/frontend/src/pages/Setup.tsx b/frontend/src/pages/Setup.tsx index f16bde8c..d5a0c3b0 100644 --- a/frontend/src/pages/Setup.tsx +++ b/frontend/src/pages/Setup.tsx @@ -1,12 +1,16 @@ import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; -import { useMutation, useQuery } from '@tanstack/react-query'; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { getSetupStatus, performSetup, SetupRequest } from '../api/setup'; +import client from '../api/client'; +import { useAuth } from '../context/AuthContext'; import { Input } from '../components/ui/Input'; import { Button } from '../components/ui/Button'; const Setup: React.FC = () => { const navigate = useNavigate(); + const queryClient = useQueryClient(); + const { login, isAuthenticated } = useAuth(); const [formData, setFormData] = useState({ name: '', email: '', @@ -21,15 +25,27 @@ const Setup: React.FC = () => { }); useEffect(() => { + if (isAuthenticated) { + navigate('/'); + return; + } if (status && !status.setupRequired) { navigate('/login'); } - }, [status, navigate]); + }, [status, isAuthenticated, navigate]); const mutation = useMutation({ - mutationFn: performSetup, - onSuccess: () => { - navigate('/login'); + mutationFn: async (data: SetupRequest) => { + // 1. Perform Setup + await performSetup(data); + // 2. Auto Login + await client.post('/auth/login', { email: data.email, password: data.password }); + // 3. Update Auth Context + await login(); + }, + onSuccess: async () => { + await queryClient.invalidateQueries({ queryKey: ['setupStatus'] }); + navigate('/'); }, onError: (err: any) => { setError(err.response?.data?.error || 'Setup failed');