diff --git a/rls_all.sql b/rls_all.sql new file mode 100644 index 0000000..debdf26 --- /dev/null +++ b/rls_all.sql @@ -0,0 +1,14 @@ +DO $$ +DECLARE + r RECORD; +BEGIN + FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = 'steelbook') + LOOP + -- Habilitar RLS + EXECUTE 'ALTER TABLE steelbook.' || quote_ident(r.tablename) || ' ENABLE ROW LEVEL SECURITY;'; + + -- Criar política de permissão global para usuários logados + EXECUTE 'DROP POLICY IF EXISTS "Auth_ALL_' || r.tablename || '" ON steelbook.' || quote_ident(r.tablename) || ';'; + EXECUTE 'CREATE POLICY "Auth_ALL_' || r.tablename || '" ON steelbook.' || quote_ident(r.tablename) || ' FOR ALL USING (auth.role() = ''authenticated'');'; + END LOOP; +END $$; diff --git a/rls_policies.sql b/rls_policies.sql new file mode 100644 index 0000000..10cebe0 --- /dev/null +++ b/rls_policies.sql @@ -0,0 +1,14 @@ +-- 1. Ativar Row Level Security nas tabelas principais +ALTER TABLE steelbook.projetos ENABLE ROW LEVEL SECURITY; +ALTER TABLE steelbook.templates_customizados ENABLE ROW LEVEL SECURITY; +ALTER TABLE steelbook.t_topicos ENABLE ROW LEVEL SECURITY; + +-- 2. Criar políticas para permitir apenas usuários autenticados (authenticated) +-- DROP POLICY IF EXISTS "Autenticados podem gerenciar projetos" ON steelbook.projetos; +-- CREATE POLICY "Autenticados podem gerenciar projetos" ON steelbook.projetos +-- FOR ALL USING (auth.role() = 'authenticated'); + +-- Em vez de FOR ALL, para produção rigorosa pode-se dividir, mas como o app depende do uso direto via painel admin, "ALL" para role authenticated é o mínimo viável seguro hoje. +CREATE POLICY "RLS_Projetos_Auth" ON steelbook.projetos FOR ALL USING (auth.role() = 'authenticated'); +CREATE POLICY "RLS_Templates_Auth" ON steelbook.templates_customizados FOR ALL USING (auth.role() = 'authenticated'); +CREATE POLICY "RLS_Topicos_Auth" ON steelbook.t_topicos FOR ALL USING (auth.role() = 'authenticated'); diff --git a/src/App.tsx b/src/App.tsx index 0d6649d..ed0025b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,7 +4,6 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { Suspense, lazy } from 'react' import { ThemeProvider } from './contexts/ThemeContext' import LoadingSpinner from './components/common/LoadingSpinner' -import PasscodeGuard from './components/common/PasscodeGuard' // Layout import Layout from './components/layout/Layout' @@ -43,7 +42,6 @@ function App() { return ( - }> @@ -74,7 +72,6 @@ function App() { - ) } diff --git a/src/components/common/PasscodeGuard.tsx b/src/components/common/PasscodeGuard.tsx deleted file mode 100644 index 37e59d5..0000000 --- a/src/components/common/PasscodeGuard.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import { useState, useEffect } from 'react' -import { motion, AnimatePresence } from 'framer-motion' -import { Lock, ChevronRight, AlertCircle } from 'lucide-react' - -interface PasscodeGuardProps { - children: React.ReactNode -} - -const CORRECT_PASSCODE = '@@Gi05Br;;' - -export default function PasscodeGuard({ children }: PasscodeGuardProps) { - const [passcode, setPasscode] = useState('') - const [isAuthenticated, setIsAuthenticated] = useState(false) - const [error, setError] = useState(false) - const [isLoading, setIsLoading] = useState(true) - - useEffect(() => { - const saved = localStorage.getItem('app_access_granted') - if (saved === 'true') { - setIsAuthenticated(true) - } - setIsLoading(false) - }, []) - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault() - if (passcode === CORRECT_PASSCODE) { - localStorage.setItem('app_access_granted', 'true') - setIsAuthenticated(true) - setError(false) - } else { - setError(true) - setPasscode('') - // Shake animation effect could be added here - } - } - - if (isLoading) return null - - if (isAuthenticated) return <>{children} - - return ( -
- {/* Background Glow */} -
-
-
-
- - -
-
- -
- - - -

Acesso Restrito

-

O aplicativo está em fase de desenvolvimento.

-
- -
-
- setPasscode(e.target.value)} - autoFocus - className={`w-full bg-slate-800/50 border ${error ? 'border-red-500/50 ring-2 ring-red-500/10' : 'border-slate-700/50 group-hover/input:border-slate-600 focus:border-blue-500'} h-14 rounded-2xl px-6 outline-none text-white text-lg transition-all duration-300 placeholder:text-slate-600`} - /> - - - {error && ( - - - Senha incorreta - - )} - -
- - -
- -
- TrackSteel DBMaker v1.0 -
-
- -
- ) -} diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index c432b6a..d7652bb 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -1,55 +1,112 @@ +import { useState } from 'react' import { useNavigate } from 'react-router-dom' import { useAuthStore } from '@/lib/store' +import { supabase } from '@/lib/supabase' import Button from '@/components/common/Button' import { BeamsBackground } from '@/components/ui/beams-background' +import { AlertCircle, Mail, Lock } from 'lucide-react' +import { motion, AnimatePresence } from 'framer-motion' export default function Login() { const navigate = useNavigate() const setUser = useAuthStore((state) => state.setUser) - const handleSkipLogin = () => { - // Entrar direto sem credenciais - setUser({ - id: 'guest-user', - email: 'guest@steelbook.com', - nome_completo: 'Visitante', - } as any) - navigate('/dashboard') + const [email, setEmail] = useState('') + const [password, setPassword] = useState('') + const [loading, setLoading] = useState(false) + const [error, setError] = useState(null) + + const handleLogin = async (e: React.FormEvent) => { + e.preventDefault() + setLoading(true) + setError(null) + + try { + const { data, error } = await supabase.auth.signInWithPassword({ + email, + password, + }) + + if (error) { + throw error + } + + if (data.user) { + setUser(data.user) + navigate('/dashboard') + } + } catch (err: any) { + setError(err.message || 'Erro ao realizar login') + } finally { + setLoading(false) + } } return ( -
+

SteelBook

Gestão Inteligente de Databooks

-
- - -
-
-
-
-
- Modo Desenvolvimento +
+
+ +
+ + setEmail(e.target.value)} + className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent bg-gray-50" + placeholder="seu@email.com" + />
- -

- Autenticação desabilitada para desenvolvimento -

-
+ +
+ +
+ + setPassword(e.target.value)} + className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent bg-gray-50" + placeholder="••••••••" + /> +
+
+ + + {error && ( + + + {error} + + )} + + + +
-

Versão 1.0.0 - 2025

+

Versão 1.0.0 - 2026