refactor: improve layout and backend monitoring functionality - Streamlined the layout component in Svelte for better readability and consistency. - Enhanced the backend monitoring functions by updating argument structures and improving code clarity. - A #10
@@ -1,179 +0,0 @@
|
|||||||
# Análise: Migração para Better Auth
|
|
||||||
|
|
||||||
## 📊 Situação Atual
|
|
||||||
|
|
||||||
### Sistema Customizado (Atual)
|
|
||||||
- ✅ **Funciona**: Sistema próprio com tokens na tabela `sessoes`
|
|
||||||
- ✅ **Características**:
|
|
||||||
- Login via `api.autenticacao.login` (mutation customizada)
|
|
||||||
- Tokens gerados manualmente
|
|
||||||
- Armazenamento em `localStorage` no frontend
|
|
||||||
- Uso de `ConvexHttpClient.setAuth(token)` para autenticar requisições
|
|
||||||
- ⚠️ **Problema encontrado**: Vulnerabilidade onde mensagens eram enviadas em nome errado
|
|
||||||
- ❌ **Estado após correção**: Agora falha porque `ctx.auth.getUserIdentity()` retorna `null` (Better Auth não configurado)
|
|
||||||
|
|
||||||
### Better Auth (Parcialmente Configurado)
|
|
||||||
- ✅ **Frontend**: Cliente criado em `lib/auth.ts`
|
|
||||||
- ✅ **API Route**: Handler em `/api/auth/[...all]/+server.ts`
|
|
||||||
- ❌ **Backend Convex**: **NÃO CONFIGURADO** - `convex.config.ts` não tem integração
|
|
||||||
- ❌ **Integração**: Código comentado no `+layout.svelte`
|
|
||||||
|
|
||||||
## 🔍 Por que está falhando agora?
|
|
||||||
|
|
||||||
Após remover o fallback inseguro:
|
|
||||||
```typescript
|
|
||||||
// Antes (inseguro, mas funcionava):
|
|
||||||
if (!usuarioAtual) {
|
|
||||||
sessaoAtiva = sessaoMaisRecente(); // ❌ Pegava qualquer usuário
|
|
||||||
}
|
|
||||||
|
|
||||||
// Agora (seguro, mas não funciona):
|
|
||||||
// Só usa Better Auth, que não está configurado
|
|
||||||
// Resultado: ctx.auth.getUserIdentity() retorna null
|
|
||||||
```
|
|
||||||
|
|
||||||
O código está tentando usar `ctx.auth.getUserIdentity()` do Convex, mas isso **só funciona** se Better Auth estiver integrado ao Convex via `convex.config.ts`.
|
|
||||||
|
|
||||||
## 📈 Comparação: Sistema Customizado vs Better Auth
|
|
||||||
|
|
||||||
| Aspecto | Sistema Customizado | Better Auth |
|
|
||||||
|---------|-------------------|-------------|
|
|
||||||
| **Segurança** | ⚠️ Média (token manual, vulnerável a problemas) | ✅ Alta (padrão da indústria) |
|
|
||||||
| **Manutenção** | ⚠️ Alta (manter código próprio) | ✅ Baixa (biblioteca mantida) |
|
|
||||||
| **Funcionalidades** | ⚠️ Básicas | ✅ Completas (OAuth, 2FA, etc) |
|
|
||||||
| **Confiabilidade** | ⚠️ Dependente da implementação | ✅ Testado e confiável |
|
|
||||||
| **Migração** | - | ⚠️ Trabalhosa (mas única vez) |
|
|
||||||
| **Tempo** | ✅ Já funciona | ⚠️ Requer configuração |
|
|
||||||
|
|
||||||
## 🎯 Impacto da Migração para Better Auth
|
|
||||||
|
|
||||||
### ✅ Vantagens
|
|
||||||
1. **Segurança**: Elimina vulnerabilidades de identificação incorreta
|
|
||||||
2. **Confiabilidade**: Biblioteca testada e mantida pela comunidade
|
|
||||||
3. **Features**: OAuth, 2FA, recuperação de senha, etc
|
|
||||||
4. **Padrão**: Usa `ctx.auth.getUserIdentity()` nativo do Convex
|
|
||||||
5. **Futuro**: Mais fácil adicionar novos métodos de auth
|
|
||||||
|
|
||||||
### ⚠️ Desvantagens/Custos
|
|
||||||
1. **Trabalho inicial**: Configurar Better Auth no Convex
|
|
||||||
2. **Migração de dados**: Migrar sessões ativas
|
|
||||||
3. **Mudanças no frontend**: Alterar fluxo de login
|
|
||||||
4. **Breaking changes**: Usuários precisarão fazer login novamente
|
|
||||||
5. **Tempo**: 2-4 horas de trabalho
|
|
||||||
|
|
||||||
### 📝 Arquivos que precisam mudar
|
|
||||||
|
|
||||||
**Backend:**
|
|
||||||
- `packages/backend/convex/convex.config.ts` - Adicionar Better Auth provider
|
|
||||||
- `packages/backend/convex/autenticacao.ts` - Manter para features específicas (logs, etc)
|
|
||||||
- `packages/backend/convex/chat.ts` - Já usa Better Auth (precisa configurar)
|
|
||||||
- `packages/backend/convex/usuarios.ts` - Já usa Better Auth (precisa configurar)
|
|
||||||
|
|
||||||
**Frontend:**
|
|
||||||
- `apps/web/src/routes/+layout.svelte` - Descomentar integração Better Auth
|
|
||||||
- `apps/web/src/lib/components/Sidebar.svelte` - Migrar login para Better Auth
|
|
||||||
- `apps/web/src/lib/stores/auth.svelte.ts` - Adaptar para Better Auth
|
|
||||||
- Qualquer lugar que use `convex.setAuth(token)`
|
|
||||||
|
|
||||||
## 🚀 Recomendação
|
|
||||||
|
|
||||||
**SIM, migrar para Better Auth é melhor**, porque:
|
|
||||||
1. ✅ Mais seguro (resolve o problema atual)
|
|
||||||
2. ✅ Padrão da indústria
|
|
||||||
3. ✅ Menos código para manter
|
|
||||||
4. ✅ Melhor integração com Convex
|
|
||||||
5. ⚠️ Custo inicial é aceitável (única vez)
|
|
||||||
|
|
||||||
## 📋 Plano de Migração (se aprovar)
|
|
||||||
|
|
||||||
### Fase 1: Configurar Better Auth no Convex
|
|
||||||
- Configurar provider no `convex.config.ts`
|
|
||||||
- Testar `ctx.auth.getUserIdentity()` funcionando
|
|
||||||
|
|
||||||
### Fase 2: Migrar Login no Frontend
|
|
||||||
- Usar Better Auth para login/logout
|
|
||||||
- Manter sistema customizado como fallback temporário
|
|
||||||
|
|
||||||
### Fase 3: Migrar Todas as Queries/Mutations
|
|
||||||
- Garantir que todas usam Better Auth
|
|
||||||
- Remover dependências de tokens customizados
|
|
||||||
|
|
||||||
### Fase 4: Limpeza
|
|
||||||
- Remover código de sessões customizadas (ou manter apenas para logs)
|
|
||||||
- Atualizar documentação
|
|
||||||
|
|
||||||
## ⚠️ Alternativa: Corrigir Sistema Customizado
|
|
||||||
|
|
||||||
Se preferir manter o sistema customizado, precisamos:
|
|
||||||
1. Configurar Custom Auth Provider no `convex.config.ts` para ler token do header
|
|
||||||
2. Modificar `getUsuarioAutenticado` para buscar sessão pelo token específico
|
|
||||||
3. Garantir que tokens customizados sejam validados corretamente
|
|
||||||
|
|
||||||
**Desvantagem**: Continua mantendo código customizado que pode ter bugs futuros.
|
|
||||||
|
|
||||||
## 🔧 Solução Imediata: Configurar Custom Auth Provider
|
|
||||||
|
|
||||||
Para fazer o sistema customizado funcionar AGORA, precisamos configurar um auth provider no Convex:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// convex.config.ts
|
|
||||||
import { defineApp } from "convex/server";
|
|
||||||
import { createCustomAuth } from "convex/server";
|
|
||||||
|
|
||||||
const app = defineApp({
|
|
||||||
auth: createCustomAuth({
|
|
||||||
// Função que extrai o token do header da requisição
|
|
||||||
getToken: async (request) => {
|
|
||||||
const authHeader = request.headers.get("authorization");
|
|
||||||
if (authHeader?.startsWith("Bearer ")) {
|
|
||||||
return authHeader.substring(7);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
// Função que valida o token e retorna identity
|
|
||||||
getIdentity: async (token, ctx) => {
|
|
||||||
// Buscar sessão pelo token
|
|
||||||
const sessao = await ctx.db
|
|
||||||
.query("sessoes")
|
|
||||||
.withIndex("by_token", (q) => q.eq("token", token))
|
|
||||||
.filter((q) => q.eq(q.field("ativo"), true))
|
|
||||||
.first();
|
|
||||||
|
|
||||||
if (!sessao || sessao.expiraEm < Date.now()) {
|
|
||||||
return null; // Token inválido ou expirado
|
|
||||||
}
|
|
||||||
|
|
||||||
const usuario = await ctx.db.get(sessao.usuarioId);
|
|
||||||
if (!usuario || !usuario.ativo) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retornar identity compatível com Better Auth
|
|
||||||
return {
|
|
||||||
subject: usuario._id,
|
|
||||||
email: usuario.email,
|
|
||||||
emailVerified: true,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default app;
|
|
||||||
```
|
|
||||||
|
|
||||||
Depois disso, `ctx.auth.getUserIdentity()` funcionará com tokens customizados!
|
|
||||||
|
|
||||||
## 💡 Minha Recomendação Final
|
|
||||||
|
|
||||||
**Opção A - Migrar para Better Auth (RECOMENDADO)**:
|
|
||||||
- ✅ Mais seguro e confiável
|
|
||||||
- ✅ Padrão da indústria
|
|
||||||
- ⚠️ 2-4 horas de trabalho
|
|
||||||
- ✅ Solução definitiva
|
|
||||||
|
|
||||||
**Opção B - Configurar Custom Auth Provider (RÁPIDO)**:
|
|
||||||
- ✅ Funciona imediatamente
|
|
||||||
- ✅ Mantém sistema atual
|
|
||||||
- ⚠️ Continua código customizado
|
|
||||||
- ⚠️ Mais manutenção futura
|
|
||||||
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
# 🔔 Configuração de Push Notifications
|
|
||||||
|
|
||||||
## Passo 1: Configurar VAPID Keys
|
|
||||||
|
|
||||||
### 1.1 Gerar VAPID Keys (se ainda não tiver)
|
|
||||||
|
|
||||||
Execute no diretório do backend:
|
|
||||||
```bash
|
|
||||||
cd packages/backend
|
|
||||||
bunx web-push generate-vapid-keys
|
|
||||||
```
|
|
||||||
|
|
||||||
Isso gerará duas chaves:
|
|
||||||
- **Public Key**: Segura para expor no frontend
|
|
||||||
- **Private Key**: Deve ser mantida em segredo, apenas no backend
|
|
||||||
|
|
||||||
### 1.2 Configurar no Convex (Backend)
|
|
||||||
|
|
||||||
As variáveis de ambiente no Convex são configuradas via dashboard ou CLI:
|
|
||||||
|
|
||||||
#### Opção A: Via Dashboard Convex
|
|
||||||
1. Acesse https://dashboard.convex.dev
|
|
||||||
2. Selecione seu projeto
|
|
||||||
3. Vá em **Settings** > **Environment Variables**
|
|
||||||
4. Adicione as seguintes variáveis:
|
|
||||||
|
|
||||||
```
|
|
||||||
VAPID_PUBLIC_KEY=BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks
|
|
||||||
VAPID_PRIVATE_KEY=KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4
|
|
||||||
FRONTEND_URL=http://localhost:5173
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Opção B: Via CLI Convex
|
|
||||||
```bash
|
|
||||||
cd packages/backend
|
|
||||||
npx convex env set VAPID_PUBLIC_KEY "BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks"
|
|
||||||
npx convex env set VAPID_PRIVATE_KEY "KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4"
|
|
||||||
npx convex env set FRONTEND_URL "http://localhost:5173"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.3 Configurar no Frontend
|
|
||||||
|
|
||||||
Crie um arquivo `.env` no diretório `apps/web/` com:
|
|
||||||
|
|
||||||
```env
|
|
||||||
VITE_VAPID_PUBLIC_KEY=BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks
|
|
||||||
```
|
|
||||||
|
|
||||||
**Importante**: Reinicie o servidor de desenvolvimento após criar/modificar o `.env`.
|
|
||||||
|
|
||||||
## Passo 2: Configurar FRONTEND_URL
|
|
||||||
|
|
||||||
A variável `FRONTEND_URL` é usada nos templates de email para gerar links de volta ao sistema.
|
|
||||||
|
|
||||||
### Para Desenvolvimento:
|
|
||||||
```
|
|
||||||
FRONTEND_URL=http://localhost:5173
|
|
||||||
```
|
|
||||||
|
|
||||||
### Para Produção:
|
|
||||||
```
|
|
||||||
FRONTEND_URL=https://seu-dominio.com
|
|
||||||
```
|
|
||||||
|
|
||||||
## Passo 3: Testar Push Notifications
|
|
||||||
|
|
||||||
### 3.1 Registrar Subscription no Frontend
|
|
||||||
|
|
||||||
O sistema automaticamente solicita permissão e registra a subscription quando:
|
|
||||||
1. O usuário faz login
|
|
||||||
2. Acessa o chat pela primeira vez
|
|
||||||
3. O Service Worker é instalado
|
|
||||||
|
|
||||||
### 3.2 Verificar se está funcionando
|
|
||||||
|
|
||||||
1. Abra o DevTools do navegador (F12)
|
|
||||||
2. Vá na aba **Application** > **Service Workers**
|
|
||||||
3. Verifique se o Service Worker está registrado
|
|
||||||
4. Vá em **Application** > **Notifications**
|
|
||||||
5. Verifique se a permissão está concedida
|
|
||||||
|
|
||||||
### 3.3 Testar envio de push
|
|
||||||
|
|
||||||
1. Abra o chat em duas abas/janelas diferentes
|
|
||||||
2. Faça login com usuários diferentes
|
|
||||||
3. Envie uma mensagem de um usuário para o outro
|
|
||||||
4. A mensagem deve aparecer como notificação push na outra aba
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Push notifications não funcionam
|
|
||||||
|
|
||||||
1. **Verificar VAPID keys**: Certifique-se de que as keys estão configuradas corretamente
|
|
||||||
2. **Verificar Service Worker**: O arquivo `sw.js` deve estar em `/static/sw.js`
|
|
||||||
3. **Verificar permissões**: O navegador deve ter permissão para notificações
|
|
||||||
4. **Verificar console**: Procure por erros no console do navegador e do Convex
|
|
||||||
|
|
||||||
### Erro "VAPID keys não configuradas"
|
|
||||||
|
|
||||||
- Verifique se as variáveis de ambiente estão configuradas no Convex
|
|
||||||
- Reinicie o servidor Convex após configurar as variáveis
|
|
||||||
- Verifique se os nomes das variáveis estão corretos (case-sensitive)
|
|
||||||
|
|
||||||
### Service Worker não registra
|
|
||||||
|
|
||||||
- Verifique se o arquivo `sw.js` existe em `apps/web/static/sw.js`
|
|
||||||
- Verifique se o servidor está servindo arquivos estáticos corretamente
|
|
||||||
- Limpe o cache do navegador e tente novamente
|
|
||||||
|
|
||||||
## Segurança
|
|
||||||
|
|
||||||
⚠️ **IMPORTANTE**:
|
|
||||||
- A **Private Key** nunca deve ser exposta no frontend
|
|
||||||
- Use variáveis de ambiente diferentes para desenvolvimento e produção
|
|
||||||
- Regenere as keys se suspeitar de comprometimento
|
|
||||||
- Mantenha as keys em segredo (não commite no Git)
|
|
||||||
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
# 🔧 Correção Crítica: Autenticação no Chat
|
|
||||||
|
|
||||||
## 🐛 Problema Identificado
|
|
||||||
|
|
||||||
Erros no console:
|
|
||||||
- `[getUsuarioAutenticado] Usuário não autenticado - Better Auth não configurado ou token inválido`
|
|
||||||
- `Uncaught Error: Não autenticado at handler (../convex/chat.ts:757:14)`
|
|
||||||
- Chat não abre conversas (tela branca)
|
|
||||||
|
|
||||||
**Causa Raiz**: Token não está sendo passado nas requisições Convex do `convex-svelte`
|
|
||||||
|
|
||||||
## ✅ Correções Aplicadas
|
|
||||||
|
|
||||||
### 1. `apps/web/src/routes/+layout.svelte`
|
|
||||||
- ✅ Monkey patch no `ConvexHttpClient.prototype` para adicionar token automaticamente
|
|
||||||
- ✅ Token é injetado em todas chamadas `mutation()` e `query()`
|
|
||||||
|
|
||||||
### 2. `apps/web/src/lib/components/chat/PresenceManager.svelte`
|
|
||||||
- ✅ Configuração manual do token no `onMount`
|
|
||||||
- ✅ Garante que `atualizarStatusPresenca` tenha token
|
|
||||||
|
|
||||||
### 3. `apps/web/src/lib/components/chat/ChatWindow.svelte`
|
|
||||||
- ✅ Configuração manual do token no cliente
|
|
||||||
- ✅ Garante que queries de conversas funcionem
|
|
||||||
|
|
||||||
### 4. Backend (`packages/backend/convex/convex.config.ts`)
|
|
||||||
- ✅ Custom Auth Provider já configurado com logs extensivos
|
|
||||||
- ✅ Busca sessão por token específico (seguro)
|
|
||||||
|
|
||||||
## 🧪 Como Testar
|
|
||||||
|
|
||||||
1. **Limpar cache do navegador** (importante!)
|
|
||||||
2. **Fazer login novamente**
|
|
||||||
3. **Abrir console do navegador** e verificar:
|
|
||||||
- Não deve aparecer mais "Não autenticado"
|
|
||||||
- Deve aparecer logs do Custom Auth Provider no backend
|
|
||||||
4. **Testar chat**:
|
|
||||||
- Abrir conversa
|
|
||||||
- Verificar se mensagens carregam
|
|
||||||
- Enviar mensagem
|
|
||||||
|
|
||||||
## 🔍 Verificar Logs do Backend
|
|
||||||
|
|
||||||
No terminal do Convex, deve aparecer:
|
|
||||||
- `🔍 [Custom Auth] Headers recebidos:` - Se token está chegando
|
|
||||||
- `✅ [Custom Auth] Token extraído:` - Se token foi encontrado
|
|
||||||
- `✅ [Custom Auth] Identity criada:` - Se usuário foi identificado
|
|
||||||
|
|
||||||
## ⚠️ Se Ainda Não Funcionar
|
|
||||||
|
|
||||||
1. Verificar se token está no `authStore`: `console.log(authStore.token)`
|
|
||||||
2. Verificar logs do backend Convex para ver qual etapa está falhando
|
|
||||||
3. Verificar se sessão ainda está ativa no banco
|
|
||||||
|
|
||||||
## 📝 Arquivos Modificados
|
|
||||||
|
|
||||||
- `apps/web/src/routes/+layout.svelte`
|
|
||||||
- `apps/web/src/lib/components/chat/PresenceManager.svelte`
|
|
||||||
- `apps/web/src/lib/components/chat/ChatWindow.svelte`
|
|
||||||
- Backend já estava correto desde Fase 1
|
|
||||||
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
# ✅ FASE 1 COMPLETA: Configurar Auth Provider no Convex
|
|
||||||
|
|
||||||
## 🎯 Objetivo
|
|
||||||
Configurar Custom Auth Provider no Convex que funciona com o sistema atual (tokens customizados) e prepara para Better Auth.
|
|
||||||
|
|
||||||
## ✅ O que foi implementado:
|
|
||||||
|
|
||||||
### 1. `packages/backend/convex/convex.config.ts`
|
|
||||||
- ✅ Adicionado Custom Auth Provider
|
|
||||||
- ✅ `getToken()` - Extrai token do header `Authorization: Bearer <token>`
|
|
||||||
- ✅ `getIdentity()` - Valida token buscando sessão na tabela `sessoes`
|
|
||||||
- ✅ Retorna identity formatada compatível com Better Auth
|
|
||||||
- ✅ Valida expiração e status ativo
|
|
||||||
|
|
||||||
### 2. `packages/backend/convex/chat.ts`
|
|
||||||
- ✅ Atualizado `getUsuarioAutenticado()` para usar Custom Auth Provider
|
|
||||||
- ✅ Adicionado logs de debug em desenvolvimento
|
|
||||||
- ✅ Mantida compatibilidade com sistema atual
|
|
||||||
|
|
||||||
### 3. `packages/backend/convex/usuarios.ts`
|
|
||||||
- ✅ Atualizado `getUsuarioAutenticado()` para usar Custom Auth Provider
|
|
||||||
- ✅ Mantida compatibilidade
|
|
||||||
|
|
||||||
## 🔍 Como funciona agora:
|
|
||||||
|
|
||||||
1. **Frontend envia token**: `ConvexHttpClient.setAuth(token)` → header `Authorization: Bearer <token>`
|
|
||||||
|
|
||||||
2. **Convex recebe**: O Custom Auth Provider extrai o token do header
|
|
||||||
|
|
||||||
3. **Provider valida**:
|
|
||||||
- Busca sessão na tabela `sessoes` por token
|
|
||||||
- Verifica se está ativa e não expirada
|
|
||||||
- Busca usuário e retorna identity
|
|
||||||
|
|
||||||
4. **Backend usa**: `ctx.auth.getUserIdentity()` agora retorna identity válida!
|
|
||||||
|
|
||||||
## ✅ Garantias de segurança:
|
|
||||||
|
|
||||||
- ✅ Busca sessão por **token específico** (não mais recente)
|
|
||||||
- ✅ Valida expiração do token
|
|
||||||
- ✅ Verifica se usuário está ativo
|
|
||||||
- ✅ Retorna `null` se token inválido (não assume usuário errado)
|
|
||||||
|
|
||||||
## 🧪 Como testar:
|
|
||||||
|
|
||||||
1. **Iniciar backend**:
|
|
||||||
```bash
|
|
||||||
cd packages/backend
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Fazer login** no sistema (como sempre)
|
|
||||||
|
|
||||||
3. **Verificar logs**:
|
|
||||||
- Deve aparecer: `✅ [getUsuarioAutenticado] Usuário identificado via Custom Auth Provider`
|
|
||||||
- Enviar mensagem no chat deve funcionar
|
|
||||||
- Ver perfil deve funcionar
|
|
||||||
|
|
||||||
4. **Testar mutations críticas**:
|
|
||||||
- ✅ Enviar mensagem no chat
|
|
||||||
- ✅ Ver perfil do usuário
|
|
||||||
- ✅ Criar conversa
|
|
||||||
- ✅ Qualquer mutation que use `getUsuarioAutenticado()`
|
|
||||||
|
|
||||||
## ⚠️ Se algo der errado:
|
|
||||||
|
|
||||||
**Rollback rápido**: Comentar o bloco `auth: { ... }` no `convex.config.ts`:
|
|
||||||
```typescript
|
|
||||||
const app = defineApp();
|
|
||||||
// auth: { ... } // Comentado temporariamente
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📝 Próximos passos (Fase 2):
|
|
||||||
|
|
||||||
- Configurar Better Auth no frontend para funcionar junto
|
|
||||||
- Migrar login gradualmente
|
|
||||||
- Adicionar suporte a tokens Better Auth no provider
|
|
||||||
|
|
||||||
## ✨ Status: FASE 1 COMPLETA ✅
|
|
||||||
|
|
||||||
O sistema atual deve funcionar normalmente, mas agora com `ctx.auth.getUserIdentity()` funcionando corretamente!
|
|
||||||
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# ✅ FASE 2 COMPLETA: Migração Dual - Login
|
|
||||||
|
|
||||||
## 🎯 Objetivo
|
|
||||||
Preparar sistema de login para suportar tanto Better Auth quanto sistema customizado, mantendo ambos funcionando simultaneamente.
|
|
||||||
|
|
||||||
## ✅ O que foi implementado:
|
|
||||||
|
|
||||||
### 1. `apps/web/src/lib/stores/auth.svelte.ts`
|
|
||||||
- ✅ Método `login()` atualizado com logs e preparação para Better Auth
|
|
||||||
- ✅ Método `loginWithBetterAuth()` criado (estrutura pronta, aguardando configuração)
|
|
||||||
- ✅ Sistema customizado continua funcionando normalmente
|
|
||||||
|
|
||||||
### 2. `apps/web/src/lib/components/Sidebar.svelte`
|
|
||||||
- ✅ `handleLogin()` preparado com estrutura dual
|
|
||||||
- ✅ Comentários mostram onde Better Auth será integrado
|
|
||||||
- ✅ Fallback para sistema customizado mantido
|
|
||||||
|
|
||||||
### 3. `apps/web/src/routes/+layout.svelte`
|
|
||||||
- ✅ `setupConvex` configurado para passar token automaticamente
|
|
||||||
- ✅ Token do `authStore` é incluído em todas as requisições
|
|
||||||
|
|
||||||
## 🔄 Como funciona agora:
|
|
||||||
|
|
||||||
**Login atual (Sistema Customizado)**:
|
|
||||||
1. Usuário faz login via `api.autenticacao.login`
|
|
||||||
2. Recebe `token` e `usuario`
|
|
||||||
3. `authStore.login()` salva no localStorage
|
|
||||||
4. Token é passado automaticamente para todas requisições Convex
|
|
||||||
|
|
||||||
**Preparado para Better Auth**:
|
|
||||||
- Estrutura pronta em `loginWithBetterAuth()`
|
|
||||||
- Quando Better Auth estiver configurado, será descomentado o código em `handleLogin()`
|
|
||||||
- Sistema continuará funcionando com fallback automático
|
|
||||||
|
|
||||||
## ✨ Status: FASE 2 COMPLETA ✅
|
|
||||||
|
|
||||||
Sistema está preparado para Better Auth, mas ainda usa sistema customizado normalmente.
|
|
||||||
Próximo passo: Fase 3 (já parcialmente feito na Fase 1)
|
|
||||||
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
# ✅ FASE 4 COMPLETA: Integração Better Auth no Frontend
|
|
||||||
|
|
||||||
## 🎯 Objetivo
|
|
||||||
Preparar integração Better Auth no frontend, mantendo compatibilidade com sistema customizado.
|
|
||||||
|
|
||||||
## ✅ O que foi implementado:
|
|
||||||
|
|
||||||
### 1. `apps/web/src/lib/auth.ts`
|
|
||||||
- ✅ `authClient` atualizado com configuração dinâmica
|
|
||||||
- ✅ Plugin `convexClient` configurado corretamente
|
|
||||||
- ✅ Base URL ajustada para funcionar em produção/dev
|
|
||||||
|
|
||||||
### 2. `apps/web/src/routes/+layout.svelte`
|
|
||||||
- ✅ Comentários e estrutura preparada para Better Auth
|
|
||||||
- ✅ Sistema customizado continua funcionando
|
|
||||||
- ✅ Preparado para descomentar quando Better Auth estiver pronto
|
|
||||||
|
|
||||||
### 3. `apps/web/src/routes/api/auth/[...all]/+server.ts`
|
|
||||||
- ✅ Handler SvelteKit já existe e está funcionando
|
|
||||||
- ✅ Processa requisições Better Auth automaticamente
|
|
||||||
|
|
||||||
### 4. `packages/backend/convex/betterAuth.ts`
|
|
||||||
- ✅ Arquivo criado (estrutura preparada)
|
|
||||||
- ✅ Será configurado quando Better Auth estiver totalmente integrado
|
|
||||||
|
|
||||||
## 🔄 Como funciona agora:
|
|
||||||
|
|
||||||
**Sistema Atual (Funcionando)**:
|
|
||||||
- ✅ Login via sistema customizado
|
|
||||||
- ✅ Tokens passados automaticamente
|
|
||||||
- ✅ Custom Auth Provider valida tokens
|
|
||||||
|
|
||||||
**Preparado para Better Auth**:
|
|
||||||
- ✅ Cliente Better Auth configurado
|
|
||||||
- ✅ Handler SvelteKit pronto
|
|
||||||
- ⏳ Aguardando configuração completa do backend
|
|
||||||
|
|
||||||
## ⚠️ Status Atual:
|
|
||||||
|
|
||||||
Better Auth está **parcialmente configurado**:
|
|
||||||
- ✅ Frontend preparado
|
|
||||||
- ✅ Handler API pronto
|
|
||||||
- ⏳ Backend Convex precisa de configuração adicional
|
|
||||||
- ⏳ Tabelas Better Auth precisam ser geradas
|
|
||||||
|
|
||||||
**Próximos Passos**:
|
|
||||||
1. Configurar Better Auth no backend Convex (quando pacote suportar)
|
|
||||||
2. Gerar/migrar tabelas Better Auth
|
|
||||||
3. Descomentar integração no `+layout.svelte`
|
|
||||||
4. Testar login via Better Auth
|
|
||||||
|
|
||||||
## ✨ Status: FASE 4 COMPLETA (Estrutura) ✅
|
|
||||||
|
|
||||||
Estrutura está pronta. Sistema customizado continua funcionando normalmente.
|
|
||||||
Better Auth será ativado quando backend estiver completamente configurado.
|
|
||||||
|
|
||||||
@@ -1,214 +0,0 @@
|
|||||||
# 🧪 Guia de Teste - Push Notifications e Melhorias do Chat
|
|
||||||
|
|
||||||
## Pré-requisitos
|
|
||||||
|
|
||||||
1. ✅ Convex rodando (`cd packages/backend && bun run dev`)
|
|
||||||
2. ✅ Frontend rodando (`cd apps/web && bun run dev`)
|
|
||||||
3. ✅ Variáveis de ambiente configuradas (ver `configurar-variaveis-ambiente.md`)
|
|
||||||
4. ✅ Usuários criados no sistema
|
|
||||||
|
|
||||||
## Teste 1: Configuração de Push Notifications
|
|
||||||
|
|
||||||
### 1.1 Verificar Service Worker
|
|
||||||
|
|
||||||
1. Abra o navegador em `http://localhost:5173`
|
|
||||||
2. Faça login no sistema
|
|
||||||
3. Abra DevTools (F12)
|
|
||||||
4. Vá em **Application** > **Service Workers**
|
|
||||||
5. ✅ Verifique se `sw.js` está registrado e ativo
|
|
||||||
|
|
||||||
### 1.2 Solicitar Permissão de Notificações
|
|
||||||
|
|
||||||
1. Abra o chat no sistema
|
|
||||||
2. O sistema deve solicitar permissão para notificações automaticamente
|
|
||||||
3. Clique em **Permitir**
|
|
||||||
4. ✅ Verifique em **Application** > **Notifications** que a permissão está concedida
|
|
||||||
|
|
||||||
### 1.3 Verificar Subscription
|
|
||||||
|
|
||||||
1. Abra o Console do DevTools
|
|
||||||
2. Execute:
|
|
||||||
```javascript
|
|
||||||
navigator.serviceWorker.ready.then(reg => {
|
|
||||||
reg.pushManager.getSubscription().then(sub => {
|
|
||||||
console.log('Subscription:', sub);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
```
|
|
||||||
3. ✅ Deve retornar um objeto Subscription com endpoint e keys
|
|
||||||
|
|
||||||
## Teste 2: Envio e Recebimento de Push Notifications
|
|
||||||
|
|
||||||
### 2.1 Teste Básico
|
|
||||||
|
|
||||||
1. Abra o sistema em **duas abas diferentes** (ou dois navegadores)
|
|
||||||
2. Faça login com usuários diferentes em cada aba
|
|
||||||
3. Na aba 1, abra uma conversa com o usuário da aba 2
|
|
||||||
4. Envie uma mensagem da aba 1
|
|
||||||
5. ✅ A aba 2 deve receber uma notificação push (mesmo se estiver em background)
|
|
||||||
|
|
||||||
### 2.2 Teste de Menção
|
|
||||||
|
|
||||||
1. Na aba 1, envie uma mensagem mencionando o usuário da aba 2 (use @)
|
|
||||||
2. ✅ A aba 2 deve receber uma notificação push destacada
|
|
||||||
|
|
||||||
### 2.3 Teste Offline
|
|
||||||
|
|
||||||
1. Feche a aba 2 (ou coloque o navegador em modo offline)
|
|
||||||
2. Envie uma mensagem da aba 1
|
|
||||||
3. ✅ O sistema deve enviar um email para o usuário da aba 2 (se estiver offline)
|
|
||||||
|
|
||||||
## Teste 3: Edição de Mensagens
|
|
||||||
|
|
||||||
### 3.1 Editar Mensagem Própria
|
|
||||||
|
|
||||||
1. Envie uma mensagem no chat
|
|
||||||
2. Clique no ícone ✏️ ao lado da mensagem
|
|
||||||
3. Edite o conteúdo
|
|
||||||
4. Pressione **Ctrl+Enter** ou clique em **Salvar**
|
|
||||||
5. ✅ A mensagem deve ser atualizada com indicador "(editado)"
|
|
||||||
|
|
||||||
### 3.2 Tentar Editar Mensagem de Outro Usuário
|
|
||||||
|
|
||||||
1. Tente editar uma mensagem de outro usuário
|
|
||||||
2. ✅ Não deve aparecer o botão de editar (ou deve retornar erro)
|
|
||||||
|
|
||||||
## Teste 4: Soft Delete de Mensagens
|
|
||||||
|
|
||||||
### 4.1 Deletar Mensagem Própria
|
|
||||||
|
|
||||||
1. Envie uma mensagem
|
|
||||||
2. Clique no ícone 🗑️ ao lado da mensagem
|
|
||||||
3. Confirme a exclusão
|
|
||||||
4. ✅ A mensagem deve ser marcada como "Mensagem deletada"
|
|
||||||
|
|
||||||
### 4.2 Tentar Deletar Mensagem de Outro Usuário
|
|
||||||
|
|
||||||
1. Tente deletar uma mensagem de outro usuário
|
|
||||||
2. ✅ Não deve aparecer o botão de deletar (ou deve retornar erro)
|
|
||||||
|
|
||||||
## Teste 5: Respostas Encadeadas
|
|
||||||
|
|
||||||
### 5.1 Responder Mensagem
|
|
||||||
|
|
||||||
1. Clique no botão **↪️ Responder** em uma mensagem
|
|
||||||
2. ✅ Deve aparecer um preview da mensagem original no campo de input
|
|
||||||
3. Digite sua resposta e envie
|
|
||||||
4. ✅ A mensagem enviada deve mostrar o preview da mensagem original acima
|
|
||||||
|
|
||||||
### 5.2 Visualizar Thread
|
|
||||||
|
|
||||||
1. Envie várias respostas para diferentes mensagens
|
|
||||||
2. ✅ Cada resposta deve mostrar claramente qual mensagem está respondendo
|
|
||||||
|
|
||||||
## Teste 6: Preview de Links
|
|
||||||
|
|
||||||
### 6.1 Enviar Mensagem com URL
|
|
||||||
|
|
||||||
1. Envie uma mensagem contendo uma URL (ex: `https://www.google.com`)
|
|
||||||
2. Aguarde alguns segundos
|
|
||||||
3. ✅ Deve aparecer um preview do link abaixo da mensagem com:
|
|
||||||
- Imagem (se disponível)
|
|
||||||
- Título
|
|
||||||
- Descrição
|
|
||||||
- Site/nome do domínio
|
|
||||||
|
|
||||||
### 6.2 Testar Diferentes URLs
|
|
||||||
|
|
||||||
Teste com diferentes tipos de URLs:
|
|
||||||
- ✅ Google: `https://www.google.com`
|
|
||||||
- ✅ YouTube: `https://www.youtube.com`
|
|
||||||
- ✅ Artigo de notícia
|
|
||||||
- ✅ Site sem Open Graph (deve funcionar mesmo assim)
|
|
||||||
|
|
||||||
## Teste 7: Busca Full-Text
|
|
||||||
|
|
||||||
### 7.1 Busca Básica
|
|
||||||
|
|
||||||
1. Envie algumas mensagens com palavras específicas
|
|
||||||
2. Use a busca no chat (se implementada) ou a query de busca
|
|
||||||
3. ✅ Deve encontrar mensagens mesmo com acentos diferentes
|
|
||||||
|
|
||||||
### 7.2 Busca com Filtros
|
|
||||||
|
|
||||||
1. Busque mensagens por:
|
|
||||||
- ✅ Remetente específico
|
|
||||||
- ✅ Tipo (texto, arquivo, imagem)
|
|
||||||
- ✅ Período de data
|
|
||||||
2. ✅ Os filtros devem funcionar corretamente
|
|
||||||
|
|
||||||
## Teste 8: Rate Limiting de Emails
|
|
||||||
|
|
||||||
### 8.1 Enviar Múltiplos Emails
|
|
||||||
|
|
||||||
1. Configure o sistema para enviar emails
|
|
||||||
2. Tente enviar mais de 10 emails em 1 minuto
|
|
||||||
3. ✅ Deve retornar erro de rate limit após o limite
|
|
||||||
|
|
||||||
### 8.2 Verificar Delay Exponencial
|
|
||||||
|
|
||||||
1. Aguarde o rate limit ser aplicado
|
|
||||||
2. Tente enviar novamente
|
|
||||||
3. ✅ Deve haver um delay antes de permitir novo envio
|
|
||||||
|
|
||||||
## Checklist de Validação
|
|
||||||
|
|
||||||
- [ ] Service Worker registrado e funcionando
|
|
||||||
- [ ] Permissão de notificações concedida
|
|
||||||
- [ ] Push notifications sendo recebidas
|
|
||||||
- [ ] Emails sendo enviados quando usuário offline
|
|
||||||
- [ ] Edição de mensagens funcionando
|
|
||||||
- [ ] Soft delete funcionando
|
|
||||||
- [ ] Respostas encadeadas funcionando
|
|
||||||
- [ ] Preview de links aparecendo
|
|
||||||
- [ ] Busca full-text funcionando
|
|
||||||
- [ ] Rate limiting de emails funcionando
|
|
||||||
|
|
||||||
## Problemas Comuns e Soluções
|
|
||||||
|
|
||||||
### Push notifications não funcionam
|
|
||||||
|
|
||||||
**Problema**: Notificações não aparecem
|
|
||||||
|
|
||||||
**Soluções**:
|
|
||||||
1. Verifique se as VAPID keys estão configuradas no Convex
|
|
||||||
2. Verifique se `VITE_VAPID_PUBLIC_KEY` está no `.env` do frontend
|
|
||||||
3. Reinicie o servidor Convex e frontend
|
|
||||||
4. Limpe o cache do navegador
|
|
||||||
5. Verifique o console para erros
|
|
||||||
|
|
||||||
### Preview de links não aparece
|
|
||||||
|
|
||||||
**Problema**: Links não geram preview
|
|
||||||
|
|
||||||
**Soluções**:
|
|
||||||
1. Verifique se a URL é válida (começa com http:// ou https://)
|
|
||||||
2. Aguarde alguns segundos (processamento é assíncrono)
|
|
||||||
3. Verifique o console do Convex para erros na extração
|
|
||||||
4. Alguns sites bloqueiam scrapers - isso é normal
|
|
||||||
|
|
||||||
### Edição não funciona
|
|
||||||
|
|
||||||
**Problema**: Botão de editar não aparece ou não funciona
|
|
||||||
|
|
||||||
**Soluções**:
|
|
||||||
1. Verifique se a mensagem é sua (só pode editar próprias mensagens)
|
|
||||||
2. Verifique se a mensagem não foi deletada
|
|
||||||
3. Verifique o console para erros
|
|
||||||
4. Certifique-se de que a mutation `editarMensagem` está funcionando
|
|
||||||
|
|
||||||
## Relatório de Testes
|
|
||||||
|
|
||||||
Após completar os testes, preencha:
|
|
||||||
|
|
||||||
- **Data**: ___________
|
|
||||||
- **Testador**: ___________
|
|
||||||
- **Ambiente**: [ ] Desenvolvimento [ ] Produção
|
|
||||||
- **Navegador**: ___________
|
|
||||||
- **Resultados**: ___________
|
|
||||||
|
|
||||||
**Observações**:
|
|
||||||
_______________________________________
|
|
||||||
_______________________________________
|
|
||||||
_______________________________________
|
|
||||||
|
|
||||||
@@ -1,163 +0,0 @@
|
|||||||
# 📋 Passo a Passo - Configuração Completa
|
|
||||||
|
|
||||||
## ✅ Passo 1: Configurar VAPID Keys
|
|
||||||
|
|
||||||
### 1.1 Configurar no Convex (Backend)
|
|
||||||
|
|
||||||
**Opção A: Via Dashboard (Recomendado)**
|
|
||||||
|
|
||||||
1. Acesse https://dashboard.convex.dev
|
|
||||||
2. Selecione seu projeto
|
|
||||||
3. Vá em **Settings** > **Environment Variables**
|
|
||||||
4. Adicione as seguintes variáveis:
|
|
||||||
|
|
||||||
```
|
|
||||||
VAPID_PUBLIC_KEY=BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks
|
|
||||||
VAPID_PRIVATE_KEY=KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4
|
|
||||||
FRONTEND_URL=http://localhost:5173
|
|
||||||
```
|
|
||||||
|
|
||||||
**Opção B: Via CLI**
|
|
||||||
|
|
||||||
Execute do diretório raiz do projeto:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
cd packages/backend
|
|
||||||
npx convex env set VAPID_PUBLIC_KEY "BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks"
|
|
||||||
npx convex env set VAPID_PRIVATE_KEY "KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4"
|
|
||||||
npx convex env set FRONTEND_URL "http://localhost:5173"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Opção C: Usar Script Automático**
|
|
||||||
|
|
||||||
Execute na raiz do projeto:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
.\scripts\configurar-push-notifications.ps1
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.2 Configurar no Frontend
|
|
||||||
|
|
||||||
Crie o arquivo `apps/web/.env` com:
|
|
||||||
|
|
||||||
```env
|
|
||||||
VITE_VAPID_PUBLIC_KEY=BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks
|
|
||||||
```
|
|
||||||
|
|
||||||
**Importante**: Reinicie o servidor frontend após criar/modificar o `.env`
|
|
||||||
|
|
||||||
## ✅ Passo 2: Configurar FRONTEND_URL
|
|
||||||
|
|
||||||
A variável `FRONTEND_URL` já foi configurada no Passo 1.1. Ela é usada nos templates de email para gerar links de volta ao sistema.
|
|
||||||
|
|
||||||
**Para Desenvolvimento:**
|
|
||||||
```
|
|
||||||
FRONTEND_URL=http://localhost:5173
|
|
||||||
```
|
|
||||||
|
|
||||||
**Para Produção (quando fizer deploy):**
|
|
||||||
```
|
|
||||||
FRONTEND_URL=https://seu-dominio.com
|
|
||||||
```
|
|
||||||
|
|
||||||
## ✅ Passo 3: Testar Funcionalidades
|
|
||||||
|
|
||||||
### 3.1 Verificar Configuração Inicial
|
|
||||||
|
|
||||||
1. **Inicie o Convex** (se não estiver rodando):
|
|
||||||
```bash
|
|
||||||
cd packages/backend
|
|
||||||
bun run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Inicie o Frontend** (se não estiver rodando):
|
|
||||||
```bash
|
|
||||||
cd apps/web
|
|
||||||
bun run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Verifique as variáveis de ambiente**:
|
|
||||||
- No Convex Dashboard: Settings > Environment Variables
|
|
||||||
- No Frontend: Verifique se `apps/web/.env` existe
|
|
||||||
|
|
||||||
### 3.2 Testar Push Notifications
|
|
||||||
|
|
||||||
1. Abra `http://localhost:5173` no navegador
|
|
||||||
2. Faça login no sistema
|
|
||||||
3. Abra DevTools (F12) > **Application** > **Service Workers**
|
|
||||||
4. ✅ Verifique se `sw.js` está registrado
|
|
||||||
5. ✅ Verifique se a permissão de notificações foi solicitada
|
|
||||||
|
|
||||||
### 3.3 Testar Chat Completo
|
|
||||||
|
|
||||||
Siga o guia completo em `GUIA_TESTE_PUSH_NOTIFICATIONS.md` para testar:
|
|
||||||
- ✅ Push notifications
|
|
||||||
- ✅ Edição de mensagens
|
|
||||||
- ✅ Soft delete
|
|
||||||
- ✅ Respostas encadeadas
|
|
||||||
- ✅ Preview de links
|
|
||||||
- ✅ Busca full-text
|
|
||||||
|
|
||||||
## 🔍 Verificação Rápida
|
|
||||||
|
|
||||||
Execute estes comandos para verificar:
|
|
||||||
|
|
||||||
### Verificar Variáveis no Convex:
|
|
||||||
```bash
|
|
||||||
cd packages/backend
|
|
||||||
npx convex env list
|
|
||||||
```
|
|
||||||
|
|
||||||
Deve mostrar:
|
|
||||||
- `VAPID_PUBLIC_KEY`
|
|
||||||
- `VAPID_PRIVATE_KEY`
|
|
||||||
- `FRONTEND_URL`
|
|
||||||
|
|
||||||
### Verificar Frontend:
|
|
||||||
```bash
|
|
||||||
cd apps/web
|
|
||||||
# Verifique se o arquivo .env existe
|
|
||||||
cat .env
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🐛 Troubleshooting
|
|
||||||
|
|
||||||
### Problema: Variáveis não aparecem no Convex
|
|
||||||
|
|
||||||
**Solução**:
|
|
||||||
- Certifique-se de estar no projeto correto no dashboard
|
|
||||||
- Reinicie o servidor Convex após configurar
|
|
||||||
- Use `npx convex env list` para verificar
|
|
||||||
|
|
||||||
### Problema: Frontend não encontra VAPID_PUBLIC_KEY
|
|
||||||
|
|
||||||
**Solução**:
|
|
||||||
- Verifique se o arquivo `.env` está em `apps/web/.env`
|
|
||||||
- Verifique se a variável começa com `VITE_`
|
|
||||||
- Reinicie o servidor frontend
|
|
||||||
- Limpe o cache do navegador
|
|
||||||
|
|
||||||
### Problema: Service Worker não registra
|
|
||||||
|
|
||||||
**Solução**:
|
|
||||||
- Verifique se `apps/web/static/sw.js` existe
|
|
||||||
- Abra DevTools > Application > Service Workers
|
|
||||||
- Clique em "Unregister" e recarregue a página
|
|
||||||
- Verifique o console para erros
|
|
||||||
|
|
||||||
## 📝 Checklist Final
|
|
||||||
|
|
||||||
- [ ] VAPID keys configuradas no Convex
|
|
||||||
- [ ] FRONTEND_URL configurada no Convex
|
|
||||||
- [ ] VITE_VAPID_PUBLIC_KEY no `.env` do frontend
|
|
||||||
- [ ] Convex rodando
|
|
||||||
- [ ] Frontend rodando
|
|
||||||
- [ ] Service Worker registrado
|
|
||||||
- [ ] Permissão de notificações concedida
|
|
||||||
- [ ] Push notifications funcionando
|
|
||||||
- [ ] Todas as funcionalidades testadas
|
|
||||||
|
|
||||||
## 🎉 Pronto!
|
|
||||||
|
|
||||||
Após completar os 3 passos, o sistema estará totalmente configurado e pronto para uso!
|
|
||||||
|
|
||||||
@@ -1,226 +0,0 @@
|
|||||||
# Plano de Migração para Better Auth - Garantia de Funcionamento
|
|
||||||
|
|
||||||
## 🎯 Estratégia: Migração Dual (Zero Downtime)
|
|
||||||
|
|
||||||
**Garantia**: Sistema atual continua funcionando durante toda a migração. Se algo falhar, simplesmente revertemos uma linha de código.
|
|
||||||
|
|
||||||
## 📋 Análise Completa de Dependências
|
|
||||||
|
|
||||||
### Backend (7 arquivos usando `getUsuarioAutenticado`):
|
|
||||||
1. ✅ `chat.ts` - Crítico (mensagens)
|
|
||||||
2. ✅ `usuarios.ts` - Crítico (perfil)
|
|
||||||
3. ✅ `pushNotifications.ts` - Importante
|
|
||||||
4. ✅ `preferenciasNotificacao.ts` - Importante
|
|
||||||
5. ✅ `atestadosLicencas.ts` - Médio
|
|
||||||
6. ✅ `permissoesAcoes.ts` - Médio
|
|
||||||
7. ✅ `monitoramento.ts` - Baixo
|
|
||||||
|
|
||||||
### Frontend (24 arquivos usando `authStore`):
|
|
||||||
- ✅ Todos usam `useConvexClient()` que pega auth automaticamente
|
|
||||||
- ✅ Não há `setAuth()` manual nos componentes (exceto refresh)
|
|
||||||
- ✅ `Sidebar.svelte` é o único lugar que faz login customizado
|
|
||||||
|
|
||||||
## 🔄 Fases de Migração (Cada fase é testável e reversível)
|
|
||||||
|
|
||||||
### ✅ FASE 0: Preparação (Sem Risco)
|
|
||||||
- [x] Documentação completa
|
|
||||||
- [x] Análise de dependências
|
|
||||||
- [ ] Backups de configuração atual
|
|
||||||
|
|
||||||
### ✅ FASE 1: Configurar Better Auth no Convex (Baixo Risco)
|
|
||||||
**Status**: Configuração apenas, sistema atual continua funcionando
|
|
||||||
|
|
||||||
**Arquivo**: `packages/backend/convex/convex.config.ts`
|
|
||||||
- Adicionar Better Auth provider
|
|
||||||
- Testar `ctx.auth.getUserIdentity()` retornando dados
|
|
||||||
|
|
||||||
**Rollback**: Simplesmente comentar a configuração
|
|
||||||
|
|
||||||
**Tempo**: 30 minutos
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ✅ FASE 2: Migração Dual - Login (Médio Risco)
|
|
||||||
**Status**: Ambos sistemas funcionam simultaneamente
|
|
||||||
|
|
||||||
**Estratégia**:
|
|
||||||
- Better Auth como primário
|
|
||||||
- Sistema customizado como fallback
|
|
||||||
- Logs para comparar resultados
|
|
||||||
|
|
||||||
**Arquivos**:
|
|
||||||
- `apps/web/src/lib/components/Sidebar.svelte` - Suportar ambos logins
|
|
||||||
- `apps/web/src/lib/stores/auth.svelte.ts` - Detectar qual método usar
|
|
||||||
|
|
||||||
**Teste**: Login com Better Auth e verificar que tudo funciona
|
|
||||||
**Rollback**: Remover código Better Auth, manter apenas customizado
|
|
||||||
|
|
||||||
**Tempo**: 1 hora
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ✅ FASE 3: Migração Dual - Backend Helpers (Baixo Risco)
|
|
||||||
**Status**: Helper tenta Better Auth primeiro, fallback para customizado
|
|
||||||
|
|
||||||
**Arquivos** (7 arquivos):
|
|
||||||
- `packages/backend/convex/chat.ts`
|
|
||||||
- `packages/backend/convex/usuarios.ts`
|
|
||||||
- `packages/backend/convex/pushNotifications.ts`
|
|
||||||
- `packages/backend/convex/preferenciasNotificacao.ts`
|
|
||||||
- `packages/backend/convex/atestadosLicencas.ts`
|
|
||||||
- `packages/backend/convex/permissoesAcoes.ts`
|
|
||||||
- `packages/backend/convex/monitoramento.ts`
|
|
||||||
|
|
||||||
**Estratégia**:
|
|
||||||
```typescript
|
|
||||||
async function getUsuarioAutenticado(ctx) {
|
|
||||||
// 1. Tentar Better Auth primeiro
|
|
||||||
const identity = await ctx.auth.getUserIdentity();
|
|
||||||
if (identity?.email) {
|
|
||||||
// Buscar usuário do Better Auth
|
|
||||||
const usuario = await buscarPorEmail(identity.email);
|
|
||||||
if (usuario) return usuario;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Fallback para sistema customizado (se Better Auth não funcionar)
|
|
||||||
// ... código atual ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Teste**: Cada mutation/query deve funcionar com ambos sistemas
|
|
||||||
**Rollback**: Remover código Better Auth, manter apenas fallback
|
|
||||||
|
|
||||||
**Tempo**: 1 hora
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ✅ FASE 4: Integrar Convex com Better Auth (Médio Risco)
|
|
||||||
**Status**: Convex passa a usar Better Auth automaticamente
|
|
||||||
|
|
||||||
**Arquivo**: `apps/web/src/routes/+layout.svelte`
|
|
||||||
- Descomentar `createSvelteAuthClient`
|
|
||||||
- Configurar Convex para usar Better Auth automaticamente
|
|
||||||
|
|
||||||
**Teste**: Todas requisições devem funcionar sem `setAuth()` manual
|
|
||||||
**Rollback**: Comentar novamente
|
|
||||||
|
|
||||||
**Tempo**: 30 minutos
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ✅ FASE 5: Migração Completa - Frontend (Médio Risco)
|
|
||||||
**Status**: Remover sistema customizado do frontend
|
|
||||||
|
|
||||||
**Arquivos**:
|
|
||||||
- `apps/web/src/lib/components/Sidebar.svelte` - Usar apenas Better Auth
|
|
||||||
- `apps/web/src/lib/stores/auth.svelte.ts` - Adaptar para Better Auth
|
|
||||||
- Remover `auth_token` do localStorage
|
|
||||||
|
|
||||||
**Teste**: Login/logout completo
|
|
||||||
**Rollback**: Reverter para código anterior
|
|
||||||
|
|
||||||
**Tempo**: 1 hora
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ✅ FASE 6: Migração Completa - Backend (Baixo Risco)
|
|
||||||
**Status**: Remover fallback customizado dos helpers
|
|
||||||
|
|
||||||
**Arquivos**: Os mesmos 7 arquivos da Fase 3
|
|
||||||
- Remover código de fallback customizado
|
|
||||||
- Manter apenas Better Auth
|
|
||||||
|
|
||||||
**Teste**: Tudo deve funcionar apenas com Better Auth
|
|
||||||
**Rollback**: Restaurar código com fallback
|
|
||||||
|
|
||||||
**Tempo**: 30 minutos
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ✅ FASE 7: Limpeza (Sem Risco)
|
|
||||||
**Status**: Remover código não usado
|
|
||||||
|
|
||||||
**Arquivos**:
|
|
||||||
- `packages/backend/convex/autenticacao.ts` - Manter para logs históricos ou remover
|
|
||||||
- Limpar tokens antigos do localStorage (se houver)
|
|
||||||
|
|
||||||
**Tempo**: 30 minutos
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ Pontos de Atenção e Como Mitigar
|
|
||||||
|
|
||||||
### 1. **Sessões Ativas Existentes**
|
|
||||||
**Problema**: Usuários logados perderão sessão
|
|
||||||
**Mitigação**:
|
|
||||||
- Fazer migração fora do horário de pico
|
|
||||||
- Avisar usuários para fazer logout/login
|
|
||||||
- Manter ambos sistemas por alguns dias
|
|
||||||
|
|
||||||
### 2. **Tokens no localStorage**
|
|
||||||
**Problema**: Tokens antigos podem causar confusão
|
|
||||||
**Mitigação**:
|
|
||||||
- Criar script de migração que limpa tokens antigos
|
|
||||||
- Detectar e migrar automaticamente na primeira abertura
|
|
||||||
|
|
||||||
### 3. **Email como Identificador Único**
|
|
||||||
**Problema**: Better Auth usa email, sistema atual usa ID
|
|
||||||
**Mitigação**:
|
|
||||||
- Verificar que todos usuários têm email único
|
|
||||||
- Criar índices no banco se necessário
|
|
||||||
|
|
||||||
### 4. **Testes em Produção**
|
|
||||||
**Problema**: Diferenças entre dev e produção
|
|
||||||
**Mitigação**:
|
|
||||||
- Testar em ambiente de staging primeiro
|
|
||||||
- Migração gradual por módulo
|
|
||||||
- Monitorar logs de erro
|
|
||||||
|
|
||||||
## ✅ Checklist de Garantia
|
|
||||||
|
|
||||||
Antes de completar cada fase:
|
|
||||||
- [ ] Testar login/logout
|
|
||||||
- [ ] Testar queries críticas
|
|
||||||
- [ ] Testar mutations críticas
|
|
||||||
- [ ] Verificar logs de erro
|
|
||||||
- [ ] Testar com múltiplos usuários
|
|
||||||
- [ ] Verificar autenticação em componentes críticos (Chat, Perfil, etc)
|
|
||||||
|
|
||||||
## 🚨 Plano de Rollback
|
|
||||||
|
|
||||||
Se algo der errado em qualquer fase:
|
|
||||||
|
|
||||||
1. **Fase 1-3**: Comentar configuração Better Auth, manter sistema atual
|
|
||||||
2. **Fase 4**: Reverter layout.svelte para código anterior
|
|
||||||
3. **Fase 5**: Restaurar código de Sidebar e authStore
|
|
||||||
4. **Fase 6**: Restaurar helpers com fallback
|
|
||||||
|
|
||||||
**Tempo de rollback**: Máximo 5 minutos por fase
|
|
||||||
|
|
||||||
## 📊 Garantia Final
|
|
||||||
|
|
||||||
**Posso garantir**:
|
|
||||||
- ✅ Sistema atual continua funcionando durante migração
|
|
||||||
- ✅ Rollback rápido em caso de problemas
|
|
||||||
- ✅ Testes em cada fase antes de prosseguir
|
|
||||||
- ✅ Documentação completa de cada passo
|
|
||||||
|
|
||||||
**Não posso garantir**:
|
|
||||||
- ❌ Zero bugs (impossível sem testes reais)
|
|
||||||
- ❌ Compatibilidade 100% sem testar em ambiente real
|
|
||||||
- ❌ Que não haverá necessidade de ajustes finos
|
|
||||||
|
|
||||||
**Mas posso garantir**:
|
|
||||||
- ✅ Que se algo falhar, revertemos imediatamente
|
|
||||||
- ✅ Que testes serão feitos antes de cada avanço
|
|
||||||
- ✅ Que código estará documentado para debugging fácil
|
|
||||||
|
|
||||||
## 🎬 Decisão
|
|
||||||
|
|
||||||
**Opções**:
|
|
||||||
1. **Migração completa** (6 horas total, fases separadas)
|
|
||||||
2. **Solução rápida** (Configurar Custom Auth Provider - 1 hora)
|
|
||||||
3. **Manter como está** (Corrigir apenas o problema imediato)
|
|
||||||
|
|
||||||
**Minha recomendação**: Opção 1, mas fazer fase por fase, testando bem entre cada uma.
|
|
||||||
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
# ✅ Resumo da Configuração Completa
|
|
||||||
|
|
||||||
## 📋 Passo 1: VAPID Keys - CONCLUÍDO
|
|
||||||
|
|
||||||
### Keys Geradas:
|
|
||||||
- **Public Key**: `BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks`
|
|
||||||
- **Private Key**: `KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4`
|
|
||||||
|
|
||||||
### Configuração Necessária:
|
|
||||||
|
|
||||||
**1. No Convex (Backend):**
|
|
||||||
- Via Dashboard: Settings > Environment Variables
|
|
||||||
- Adicionar: `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY`, `FRONTEND_URL`
|
|
||||||
- OU executar: `.\scripts\configurar-push-notifications.ps1`
|
|
||||||
|
|
||||||
**2. No Frontend:**
|
|
||||||
- Criar arquivo `apps/web/.env`
|
|
||||||
- Adicionar: `VITE_VAPID_PUBLIC_KEY=BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks`
|
|
||||||
|
|
||||||
## 📋 Passo 2: FRONTEND_URL - CONCLUÍDO
|
|
||||||
|
|
||||||
- Valor padrão: `http://localhost:5173`
|
|
||||||
- Configurar no Convex junto com as VAPID keys
|
|
||||||
- Usado nos templates de email para links de retorno
|
|
||||||
|
|
||||||
## 📋 Passo 3: Testes - PRONTO PARA EXECUTAR
|
|
||||||
|
|
||||||
### Arquivos Criados:
|
|
||||||
- ✅ `PushNotificationManager.svelte` - Registra subscription automaticamente
|
|
||||||
- ✅ `GUIA_TESTE_PUSH_NOTIFICATIONS.md` - Guia completo de testes
|
|
||||||
- ✅ `PASSO_A_PASSO_CONFIGURACAO.md` - Instruções detalhadas
|
|
||||||
- ✅ `CONFIGURACAO_PUSH_NOTIFICATIONS.md` - Documentação técnica
|
|
||||||
- ✅ `scripts/configurar-push-notifications.ps1` - Script automático
|
|
||||||
|
|
||||||
### Para Testar:
|
|
||||||
|
|
||||||
1. **Configure as variáveis** (ver Passo 1)
|
|
||||||
2. **Reinicie os servidores** (Convex e Frontend)
|
|
||||||
3. **Faça login** no sistema
|
|
||||||
4. **Siga o guia**: `GUIA_TESTE_PUSH_NOTIFICATIONS.md`
|
|
||||||
|
|
||||||
## 🎯 Checklist de Configuração
|
|
||||||
|
|
||||||
- [ ] VAPID keys configuradas no Convex Dashboard
|
|
||||||
- [ ] FRONTEND_URL configurada no Convex
|
|
||||||
- [ ] Arquivo `apps/web/.env` criado com VITE_VAPID_PUBLIC_KEY
|
|
||||||
- [ ] Convex reiniciado após configurar variáveis
|
|
||||||
- [ ] Frontend reiniciado após criar .env
|
|
||||||
- [ ] Service Worker registrado (verificar DevTools)
|
|
||||||
- [ ] Permissão de notificações concedida
|
|
||||||
- [ ] Testes executados conforme guia
|
|
||||||
|
|
||||||
## 📚 Documentação Disponível
|
|
||||||
|
|
||||||
1. **CONFIGURACAO_PUSH_NOTIFICATIONS.md** - Configuração técnica detalhada
|
|
||||||
2. **PASSO_A_PASSO_CONFIGURACAO.md** - Instruções passo a passo
|
|
||||||
3. **GUIA_TESTE_PUSH_NOTIFICATIONS.md** - Guia completo de testes
|
|
||||||
4. **configurar-variaveis-ambiente.md** - Referência rápida
|
|
||||||
|
|
||||||
## 🚀 Próximos Passos
|
|
||||||
|
|
||||||
1. Execute o script de configuração OU configure manualmente
|
|
||||||
2. Reinicie os servidores
|
|
||||||
3. Teste todas as funcionalidades
|
|
||||||
4. Reporte qualquer problema encontrado
|
|
||||||
|
|
||||||
**Tudo pronto para configuração e testes!** 🎉
|
|
||||||
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
# 📋 Resumo da Migração para Better Auth
|
|
||||||
|
|
||||||
## ✅ STATUS GERAL: FASES 1-4 COMPLETAS
|
|
||||||
|
|
||||||
Migração gradual implementada com sucesso. Sistema atual funcionando + estrutura Better Auth preparada.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 O QUE FOI FEITO
|
|
||||||
|
|
||||||
### ✅ FASE 1: Custom Auth Provider no Convex
|
|
||||||
**Arquivos modificados:**
|
|
||||||
- `packages/backend/convex/convex.config.ts` - Custom Auth Provider configurado
|
|
||||||
- `packages/backend/convex/chat.ts` - Helper atualizado
|
|
||||||
- `packages/backend/convex/usuarios.ts` - Helper atualizado
|
|
||||||
|
|
||||||
**Resultado:**
|
|
||||||
- ✅ `ctx.auth.getUserIdentity()` agora funciona com tokens customizados
|
|
||||||
- ✅ Busca sessão por token específico (seguro, não mais "mais recente")
|
|
||||||
- ✅ Logs de debug extensivos adicionados
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ✅ FASE 2: Migração Dual - Login
|
|
||||||
**Arquivos modificados:**
|
|
||||||
- `apps/web/src/lib/stores/auth.svelte.ts` - Estrutura dual preparada
|
|
||||||
- `apps/web/src/lib/components/Sidebar.svelte` - Login com fallback preparado
|
|
||||||
- `apps/web/src/routes/+layout.svelte` - Token passado automaticamente
|
|
||||||
|
|
||||||
**Resultado:**
|
|
||||||
- ✅ Sistema customizado continua funcionando normalmente
|
|
||||||
- ✅ Estrutura pronta para Better Auth
|
|
||||||
- ✅ Token passado automaticamente em todas requisições
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ✅ FASE 3: Backend Helpers (Já feito na Fase 1)
|
|
||||||
**Arquivos modificados:**
|
|
||||||
- Mesmos arquivos da Fase 1
|
|
||||||
|
|
||||||
**Resultado:**
|
|
||||||
- ✅ Todos helpers usam Custom Auth Provider
|
|
||||||
- ✅ Fallback seguro implementado
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ✅ FASE 4: Integração Better Auth Frontend
|
|
||||||
**Arquivos modificados:**
|
|
||||||
- `apps/web/src/lib/auth.ts` - Cliente Better Auth configurado
|
|
||||||
- `apps/web/src/routes/+layout.svelte` - Integração preparada
|
|
||||||
- `apps/web/src/routes/api/auth/[...all]/+server.ts` - Handler já existia
|
|
||||||
- `packages/backend/convex/betterAuth.ts` - Estrutura criada
|
|
||||||
|
|
||||||
**Resultado:**
|
|
||||||
- ✅ Cliente Better Auth configurado corretamente
|
|
||||||
- ✅ Handler SvelteKit pronto
|
|
||||||
- ⏳ Aguardando configuração completa do backend
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔒 SEGURANÇA
|
|
||||||
|
|
||||||
### Problemas corrigidos:
|
|
||||||
1. ✅ **Bug crítico**: Removido fallback inseguro que buscava "sessão mais recente"
|
|
||||||
2. ✅ **Identificação correta**: Agora busca sessão por token específico
|
|
||||||
3. ✅ **Validação**: Verifica expiração e status ativo
|
|
||||||
4. ✅ **Logs**: Debug extensivo para troubleshooting
|
|
||||||
|
|
||||||
### Garantias:
|
|
||||||
- ✅ Nenhum usuário será identificado incorretamente
|
|
||||||
- ✅ Tokens são validados antes de usar
|
|
||||||
- ✅ Sessões expiradas são rejeitadas
|
|
||||||
- ✅ Usuários inativos são bloqueados
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 TESTES NECESSÁRIOS
|
|
||||||
|
|
||||||
### Testes Imediatos:
|
|
||||||
1. ✅ **Login**: Fazer login e verificar que funciona
|
|
||||||
2. ✅ **Enviar Mensagem**: Testar chat funcionando
|
|
||||||
3. ✅ **Ver Perfil**: Verificar que perfil carrega
|
|
||||||
4. ✅ **Logs**: Verificar logs do Convex para debug
|
|
||||||
|
|
||||||
### Testes Futuros (quando Better Auth ativo):
|
|
||||||
1. ⏳ Login via Better Auth
|
|
||||||
2. ⏳ Comparar tokens Better Auth vs customizado
|
|
||||||
3. ⏳ Validar que ambos funcionam simultaneamente
|
|
||||||
4. ⏳ Migração de usuários existentes
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 ESTADO ATUAL DO SISTEMA
|
|
||||||
|
|
||||||
### ✅ Funcionando:
|
|
||||||
- Login via sistema customizado
|
|
||||||
- Autenticação em todas mutations/queries
|
|
||||||
- Token passado automaticamente
|
|
||||||
- Custom Auth Provider validando tokens
|
|
||||||
|
|
||||||
### ⏳ Preparado mas não ativo:
|
|
||||||
- Cliente Better Auth configurado
|
|
||||||
- Handler SvelteKit pronto
|
|
||||||
- Estrutura dual no login
|
|
||||||
- Integração no layout
|
|
||||||
|
|
||||||
### ❌ Pendente:
|
|
||||||
- Configuração completa Better Auth backend
|
|
||||||
- Migração de sessões existentes
|
|
||||||
- Ativação Better Auth (descomentar código)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 PRÓXIMOS PASSOS
|
|
||||||
|
|
||||||
### Curto Prazo (Para resolver erros):
|
|
||||||
1. **Verificar logs do Convex** para entender por que tokens não estão chegando
|
|
||||||
2. **Ajustar `setupConvex`** se necessário para passar token corretamente
|
|
||||||
3. **Testar em ambiente real** e ajustar conforme necessário
|
|
||||||
|
|
||||||
### Médio Prazo (Completar Better Auth):
|
|
||||||
1. Configurar Better Auth backend completamente
|
|
||||||
2. Gerar tabelas Better Auth no Convex
|
|
||||||
3. Descomentar integração no `+layout.svelte`
|
|
||||||
4. Testar login via Better Auth
|
|
||||||
5. Validar que ambos sistemas funcionam
|
|
||||||
|
|
||||||
### Longo Prazo (Migração completa):
|
|
||||||
1. Migrar todos usuários para Better Auth
|
|
||||||
2. Remover sistema customizado (ou manter como fallback)
|
|
||||||
3. Atualizar documentação
|
|
||||||
4. Remover código comentado
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ ROLLBACK PLAN
|
|
||||||
|
|
||||||
Se algo der errado, reverta em ordem:
|
|
||||||
|
|
||||||
1. **Comentar Custom Auth Provider**: Remover `auth: { ... }` de `convex.config.ts`
|
|
||||||
2. **Reverter helpers**: Voltar para busca de sessão (mas não "mais recente"!)
|
|
||||||
3. **Reverter layout**: Remover configuração `auth` de `setupConvex`
|
|
||||||
|
|
||||||
**Tempo estimado de rollback**: 5-10 minutos
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 ARQUIVOS CRIADOS/MODIFICADOS
|
|
||||||
|
|
||||||
### Criados:
|
|
||||||
- `FASE1_COMPLETA.md`
|
|
||||||
- `FASE2_COMPLETA.md`
|
|
||||||
- `FASE4_COMPLETA.md`
|
|
||||||
- `RESUMO_MIGRACAO.md`
|
|
||||||
- `packages/backend/convex/betterAuth.ts`
|
|
||||||
|
|
||||||
### Modificados:
|
|
||||||
- `packages/backend/convex/convex.config.ts`
|
|
||||||
- `packages/backend/convex/chat.ts`
|
|
||||||
- `packages/backend/convex/usuarios.ts`
|
|
||||||
- `apps/web/src/routes/+layout.svelte`
|
|
||||||
- `apps/web/src/lib/auth.ts`
|
|
||||||
- `apps/web/src/lib/stores/auth.svelte.ts`
|
|
||||||
- `apps/web/src/lib/components/Sidebar.svelte`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✨ CONCLUSÃO
|
|
||||||
|
|
||||||
**Migração gradual implementada com sucesso!**
|
|
||||||
|
|
||||||
- ✅ Sistema atual funcionando com Custom Auth Provider seguro
|
|
||||||
- ✅ Estrutura Better Auth preparada e pronta
|
|
||||||
- ✅ Migração reversível e testável
|
|
||||||
- ✅ Documentação completa
|
|
||||||
|
|
||||||
**Próximo passo**: Testar sistema atual e verificar logs para ajustar se necessário.
|
|
||||||
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
# ⚙️ Configuração de Variáveis de Ambiente
|
|
||||||
|
|
||||||
## Passo 1: Configurar VAPID Keys no Convex
|
|
||||||
|
|
||||||
### Opção A: Via Dashboard Convex (Recomendado)
|
|
||||||
|
|
||||||
1. Acesse https://dashboard.convex.dev
|
|
||||||
2. Selecione seu projeto SGSE
|
|
||||||
3. Vá em **Settings** > **Environment Variables**
|
|
||||||
4. Clique em **Add Variable** e adicione uma por vez:
|
|
||||||
|
|
||||||
**Variável 1:**
|
|
||||||
- **Name**: `VAPID_PUBLIC_KEY`
|
|
||||||
- **Value**: `BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks`
|
|
||||||
|
|
||||||
**Variável 2:**
|
|
||||||
- **Name**: `VAPID_PRIVATE_KEY`
|
|
||||||
- **Value**: `KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4`
|
|
||||||
|
|
||||||
**Variável 3:**
|
|
||||||
- **Name**: `FRONTEND_URL`
|
|
||||||
- **Value**: `http://localhost:5173` (ou sua URL de produção)
|
|
||||||
|
|
||||||
### Opção B: Via CLI Convex
|
|
||||||
|
|
||||||
Execute os seguintes comandos no diretório `packages/backend`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd packages/backend
|
|
||||||
|
|
||||||
# Configurar VAPID Public Key
|
|
||||||
npx convex env set VAPID_PUBLIC_KEY "BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks"
|
|
||||||
|
|
||||||
# Configurar VAPID Private Key
|
|
||||||
npx convex env set VAPID_PRIVATE_KEY "KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4"
|
|
||||||
|
|
||||||
# Configurar URL do Frontend
|
|
||||||
npx convex env set FRONTEND_URL "http://localhost:5173"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Passo 2: Configurar VAPID Public Key no Frontend
|
|
||||||
|
|
||||||
Crie um arquivo `.env` no diretório `apps/web/` com o seguinte conteúdo:
|
|
||||||
|
|
||||||
```env
|
|
||||||
VITE_VAPID_PUBLIC_KEY=BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks
|
|
||||||
```
|
|
||||||
|
|
||||||
**Importante**:
|
|
||||||
- Após criar/modificar o `.env`, reinicie o servidor de desenvolvimento do frontend
|
|
||||||
- O arquivo `.env` já está no `.gitignore`, então não será commitado
|
|
||||||
|
|
||||||
## Passo 3: Verificar Configuração
|
|
||||||
|
|
||||||
### Verificar no Convex Dashboard:
|
|
||||||
1. Acesse https://dashboard.convex.dev
|
|
||||||
2. Vá em **Settings** > **Environment Variables**
|
|
||||||
3. Verifique se as 3 variáveis estão listadas
|
|
||||||
|
|
||||||
### Verificar no Frontend:
|
|
||||||
1. Execute o frontend: `cd apps/web && bun run dev`
|
|
||||||
2. Abra o DevTools (F12)
|
|
||||||
3. Vá em **Console** e execute: `console.log(import.meta.env.VITE_VAPID_PUBLIC_KEY)`
|
|
||||||
4. Deve exibir a chave pública (ou `undefined` se não estiver configurado)
|
|
||||||
|
|
||||||
## Chaves Geradas
|
|
||||||
|
|
||||||
As seguintes VAPID keys foram geradas para este projeto:
|
|
||||||
|
|
||||||
- **Public Key**: `BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks`
|
|
||||||
- **Private Key**: `KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4`
|
|
||||||
|
|
||||||
⚠️ **IMPORTANTE**:
|
|
||||||
- A Private Key deve ser mantida em segredo
|
|
||||||
- Nunca exponha a Private Key no frontend ou em código público
|
|
||||||
- Se suspeitar de comprometimento, regenere as keys com `bunx web-push generate-vapid-keys`
|
|
||||||
|
|
||||||
400
fix-editar.js
400
fix-editar.js
@@ -1,400 +0,0 @@
|
|||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const baseDir = 'apps/web/src/routes/(dashboard)/recursos-humanos/funcionarios';
|
|
||||||
const cadastroPath = path.join(baseDir, 'cadastro/+page.svelte');
|
|
||||||
const editarPath = path.join(baseDir, '[funcionarioId]/editar/+page.svelte');
|
|
||||||
|
|
||||||
console.log('Reading files...');
|
|
||||||
const cadastro = fs.readFileSync(cadastroPath, 'utf8');
|
|
||||||
|
|
||||||
// Create the edit file from scratch
|
|
||||||
const editContent = `<script lang="ts">
|
|
||||||
import { useConvexClient } from "convex-svelte";
|
|
||||||
import { api } from "@sgse-app/backend/convex/_generated/api";
|
|
||||||
import { goto } from "$app/navigation";
|
|
||||||
import { page } from "$app/stores";
|
|
||||||
import type { SimboloTipo } from "@sgse-app/backend/convex/schema";
|
|
||||||
import FileUpload from "$lib/components/FileUpload.svelte";
|
|
||||||
import {
|
|
||||||
maskCPF, maskCEP, maskPhone, maskDate, onlyDigits,
|
|
||||||
validateCPF, validateDate
|
|
||||||
} from "$lib/utils/masks";
|
|
||||||
import {
|
|
||||||
SEXO_OPTIONS, ESTADO_CIVIL_OPTIONS, GRAU_INSTRUCAO_OPTIONS,
|
|
||||||
GRUPO_SANGUINEO_OPTIONS, FATOR_RH_OPTIONS, APOSENTADO_OPTIONS, UFS_BRASIL
|
|
||||||
} from "$lib/utils/constants";
|
|
||||||
import { documentos, categoriasDocumentos, getDocumentosByCategoria } from "$lib/utils/documentos";
|
|
||||||
import ModelosDeclaracoes from "$lib/components/ModelosDeclaracoes.svelte";
|
|
||||||
|
|
||||||
const client = useConvexClient();
|
|
||||||
|
|
||||||
let funcionarioId = $derived($page.params.funcionarioId as string);
|
|
||||||
|
|
||||||
let simbolos: Array<{
|
|
||||||
_id: string;
|
|
||||||
nome: string;
|
|
||||||
tipo: SimboloTipo;
|
|
||||||
descricao: string;
|
|
||||||
}> = [];
|
|
||||||
|
|
||||||
let tipo: SimboloTipo = "cargo_comissionado";
|
|
||||||
let loading = $state(false);
|
|
||||||
let loadingData = $state(true);
|
|
||||||
let notice = $state<{ kind: "success" | "error"; text: string } | null>(null);
|
|
||||||
|
|
||||||
// Campos obrigatórios
|
|
||||||
let nome = $state("");
|
|
||||||
let matricula = $state("");
|
|
||||||
let cpf = $state("");
|
|
||||||
let rg = $state("");
|
|
||||||
let nascimento = $state("");
|
|
||||||
let email = $state("");
|
|
||||||
let telefone = $state("");
|
|
||||||
let endereco = $state("");
|
|
||||||
let cep = $state("");
|
|
||||||
let cidade = $state("");
|
|
||||||
let uf = $state("");
|
|
||||||
let simboloId = $state("");
|
|
||||||
let admissaoData = $state("");
|
|
||||||
|
|
||||||
// Dados Pessoais Adicionais
|
|
||||||
let nomePai = $state("");
|
|
||||||
let nomeMae = $state("");
|
|
||||||
let naturalidade = $state("");
|
|
||||||
let naturalidadeUF = $state("");
|
|
||||||
let sexo = $state("");
|
|
||||||
let estadoCivil = $state("");
|
|
||||||
let nacionalidade = $state("Brasileira");
|
|
||||||
|
|
||||||
// Documentos Pessoais
|
|
||||||
let rgOrgaoExpedidor = $state("");
|
|
||||||
let rgDataEmissao = $state("");
|
|
||||||
let carteiraProfissionalNumero = $state("");
|
|
||||||
let carteiraProfissionalSerie = $state("");
|
|
||||||
let carteiraProfissionalDataEmissao = $state("");
|
|
||||||
let reservistaNumero = $state("");
|
|
||||||
let reservistaSerie = $state("");
|
|
||||||
let tituloEleitorNumero = $state("");
|
|
||||||
let tituloEleitorZona = $state("");
|
|
||||||
let tituloEleitorSecao = $state("");
|
|
||||||
let pisNumero = $state("");
|
|
||||||
|
|
||||||
// Formação e Saúde
|
|
||||||
let grauInstrucao = $state("");
|
|
||||||
let formacao = $state("");
|
|
||||||
let formacaoRegistro = $state("");
|
|
||||||
let grupoSanguineo = $state("");
|
|
||||||
let fatorRH = $state("");
|
|
||||||
|
|
||||||
// Cargo e Vínculo
|
|
||||||
let descricaoCargo = $state("");
|
|
||||||
let nomeacaoPortaria = $state("");
|
|
||||||
let nomeacaoData = $state("");
|
|
||||||
let nomeacaoDOE = $state("");
|
|
||||||
let pertenceOrgaoPublico = $state(false);
|
|
||||||
let orgaoOrigem = $state("");
|
|
||||||
let aposentado = $state("nao");
|
|
||||||
|
|
||||||
// Dados Bancários
|
|
||||||
let contaBradescoNumero = $state("");
|
|
||||||
let contaBradescoDV = $state("");
|
|
||||||
let contaBradescoAgencia = $state("");
|
|
||||||
|
|
||||||
// Documentos (Storage IDs)
|
|
||||||
let documentosStorage: Record<string, string | undefined> = $state({});
|
|
||||||
|
|
||||||
async function loadSimbolos() {
|
|
||||||
const list = await client.query(api.simbolos.getAll, {} as any);
|
|
||||||
simbolos = list.map((s: any) => ({
|
|
||||||
_id: s._id,
|
|
||||||
nome: s.nome,
|
|
||||||
tipo: s.tipo,
|
|
||||||
descricao: s.descricao
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadFuncionario() {
|
|
||||||
try {
|
|
||||||
const func = await client.query(api.funcionarios.getById, { id: funcionarioId as any });
|
|
||||||
|
|
||||||
// Preencher campos
|
|
||||||
nome = func.nome;
|
|
||||||
matricula = func.matricula;
|
|
||||||
cpf = maskCPF(func.cpf);
|
|
||||||
rg = func.rg;
|
|
||||||
nascimento = func.nascimento;
|
|
||||||
email = func.email;
|
|
||||||
telefone = maskPhone(func.telefone);
|
|
||||||
endereco = func.endereco;
|
|
||||||
cep = maskCEP(func.cep);
|
|
||||||
cidade = func.cidade;
|
|
||||||
uf = func.uf;
|
|
||||||
simboloId = func.simboloId;
|
|
||||||
tipo = func.simboloTipo;
|
|
||||||
admissaoData = func.admissaoData || "";
|
|
||||||
|
|
||||||
// Dados adicionais
|
|
||||||
nomePai = func.nomePai || "";
|
|
||||||
nomeMae = func.nomeMae || "";
|
|
||||||
naturalidade = func.naturalidade || "";
|
|
||||||
naturalidadeUF = func.naturalidadeUF || "";
|
|
||||||
sexo = func.sexo || "";
|
|
||||||
estadoCivil = func.estadoCivil || "";
|
|
||||||
nacionalidade = func.nacionalidade || "Brasileira";
|
|
||||||
|
|
||||||
rgOrgaoExpedidor = func.rgOrgaoExpedidor || "";
|
|
||||||
rgDataEmissao = func.rgDataEmissao || "";
|
|
||||||
carteiraProfissionalNumero = func.carteiraProfissionalNumero || "";
|
|
||||||
carteiraProfissionalSerie = func.carteiraProfissionalSerie || "";
|
|
||||||
carteiraProfissionalDataEmissao = func.carteiraProfissionalDataEmissao || "";
|
|
||||||
reservistaNumero = func.reservistaNumero || "";
|
|
||||||
reservistaSerie = func.reservistaSerie || "";
|
|
||||||
tituloEleitorNumero = func.tituloEleitorNumero || "";
|
|
||||||
tituloEleitorZona = func.tituloEleitorZona || "";
|
|
||||||
tituloEleitorSecao = func.tituloEleitorSecao || "";
|
|
||||||
pisNumero = func.pisNumero || "";
|
|
||||||
|
|
||||||
grauInstrucao = func.grauInstrucao || "";
|
|
||||||
formacao = func.formacao || "";
|
|
||||||
formacaoRegistro = func.formacaoRegistro || "";
|
|
||||||
grupoSanguineo = func.grupoSanguineo || "";
|
|
||||||
fatorRH = func.fatorRH || "";
|
|
||||||
|
|
||||||
descricaoCargo = func.descricaoCargo || "";
|
|
||||||
nomeacaoPortaria = func.nomeacaoPortaria || "";
|
|
||||||
nomeacaoData = func.nomeacaoData || "";
|
|
||||||
nomeacaoDOE = func.nomeacaoDOE || "";
|
|
||||||
pertenceOrgaoPublico = func.pertenceOrgaoPublico || false;
|
|
||||||
orgaoOrigem = func.orgaoOrigem || "";
|
|
||||||
aposentado = func.aposentado || "nao";
|
|
||||||
|
|
||||||
contaBradescoNumero = func.contaBradescoNumero || "";
|
|
||||||
contaBradescoDV = func.contaBradescoDV || "";
|
|
||||||
contaBradescoAgencia = func.contaBradescoAgencia || "";
|
|
||||||
|
|
||||||
// Documentos
|
|
||||||
documentosStorage = {};
|
|
||||||
documentos.forEach(doc => {
|
|
||||||
const storageId = (func as any)[doc.campo];
|
|
||||||
if (storageId) {
|
|
||||||
documentosStorage[doc.campo] = storageId;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Erro ao carregar funcionário:", error);
|
|
||||||
notice = { kind: "error", text: "Erro ao carregar dados do funcionário" };
|
|
||||||
} finally {
|
|
||||||
loadingData = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fillFromCEP(cepValue: string) {
|
|
||||||
const cepDigits = onlyDigits(cepValue);
|
|
||||||
if (cepDigits.length !== 8) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const res = await fetch(\`https://viacep.com.br/ws/\${cepDigits}/json/\`);
|
|
||||||
const data = await res.json();
|
|
||||||
if (!data || data.erro) return;
|
|
||||||
|
|
||||||
const enderecoFull = [data.logradouro, data.bairro].filter(Boolean).join(", ");
|
|
||||||
endereco = enderecoFull;
|
|
||||||
cidade = data.localidade || "";
|
|
||||||
uf = data.uf || "";
|
|
||||||
} catch {}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleDocumentoUpload(campo: string, file: File) {
|
|
||||||
try {
|
|
||||||
const uploadUrl = await client.mutation(api.documentos.generateUploadUrl, {});
|
|
||||||
|
|
||||||
const result = await fetch(uploadUrl, {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "Content-Type": file.type },
|
|
||||||
body: file,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { storageId } = await result.json();
|
|
||||||
documentosStorage[campo] = storageId;
|
|
||||||
} catch (err: any) {
|
|
||||||
throw new Error(err?.message || "Erro ao fazer upload");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleDocumentoRemove(campo: string) {
|
|
||||||
documentosStorage[campo] = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleSubmit() {
|
|
||||||
if (!nome || !matricula || !cpf || !rg || !nascimento || !email || !telefone) {
|
|
||||||
notice = { kind: "error", text: "Preencha todos os campos obrigatórios" };
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!validateCPF(cpf)) {
|
|
||||||
notice = { kind: "error", text: "CPF inválido" };
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!validateDate(nascimento)) {
|
|
||||||
notice = { kind: "error", text: "Data de nascimento inválida" };
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!simboloId) {
|
|
||||||
notice = { kind: "error", text: "Selecione um símbolo" };
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
loading = true;
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
nome,
|
|
||||||
matricula,
|
|
||||||
cpf: onlyDigits(cpf),
|
|
||||||
rg: onlyDigits(rg),
|
|
||||||
nascimento,
|
|
||||||
email,
|
|
||||||
telefone: onlyDigits(telefone),
|
|
||||||
endereco,
|
|
||||||
cep: onlyDigits(cep),
|
|
||||||
cidade,
|
|
||||||
uf: uf.toUpperCase(),
|
|
||||||
simboloId: simboloId as any,
|
|
||||||
simboloTipo: tipo,
|
|
||||||
admissaoData: admissaoData || undefined,
|
|
||||||
|
|
||||||
nomePai: nomePai || undefined,
|
|
||||||
nomeMae: nomeMae || undefined,
|
|
||||||
naturalidade: naturalidade || undefined,
|
|
||||||
naturalidadeUF: naturalidadeUF ? naturalidadeUF.toUpperCase() : undefined,
|
|
||||||
sexo: sexo || undefined,
|
|
||||||
estadoCivil: estadoCivil || undefined,
|
|
||||||
nacionalidade: nacionalidade || undefined,
|
|
||||||
|
|
||||||
rgOrgaoExpedidor: rgOrgaoExpedidor || undefined,
|
|
||||||
rgDataEmissao: rgDataEmissao || undefined,
|
|
||||||
carteiraProfissionalNumero: carteiraProfissionalNumero || undefined,
|
|
||||||
carteiraProfissionalSerie: carteiraProfissionalSerie || undefined,
|
|
||||||
carteiraProfissionalDataEmissao: carteiraProfissionalDataEmissao || undefined,
|
|
||||||
reservistaNumero: reservistaNumero || undefined,
|
|
||||||
reservistaSerie: reservistaSerie || undefined,
|
|
||||||
tituloEleitorNumero: tituloEleitorNumero || undefined,
|
|
||||||
tituloEleitorZona: tituloEleitorZona || undefined,
|
|
||||||
tituloEleitorSecao: tituloEleitorSecao || undefined,
|
|
||||||
pisNumero: pisNumero || undefined,
|
|
||||||
|
|
||||||
grauInstrucao: grauInstrucao || undefined,
|
|
||||||
formacao: formacao || undefined,
|
|
||||||
formacaoRegistro: formacaoRegistro || undefined,
|
|
||||||
grupoSanguineo: grupoSanguineo || undefined,
|
|
||||||
fatorRH: fatorRH || undefined,
|
|
||||||
|
|
||||||
descricaoCargo: descricaoCargo || undefined,
|
|
||||||
nomeacaoPortaria: nomeacaoPortaria || undefined,
|
|
||||||
nomeacaoData: nomeacaoData || undefined,
|
|
||||||
nomeacaoDOE: nomeacaoDOE || undefined,
|
|
||||||
pertenceOrgaoPublico: pertenceOrgaoPublico || undefined,
|
|
||||||
orgaoOrigem: orgaoOrigem || undefined,
|
|
||||||
aposentado: aposentado || undefined,
|
|
||||||
|
|
||||||
contaBradescoNumero: contaBradescoNumero || undefined,
|
|
||||||
contaBradescoDV: contaBradescoDV || undefined,
|
|
||||||
contaBradescoAgencia: contaBradescoAgencia || undefined,
|
|
||||||
|
|
||||||
...Object.fromEntries(
|
|
||||||
Object.entries(documentosStorage).map(([key, value]) => [key, value as any])
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
await client.mutation(api.funcionarios.update, { id: funcionarioId as any, ...payload as any });
|
|
||||||
notice = { kind: "success", text: "Funcionário atualizado com sucesso!" };
|
|
||||||
setTimeout(() => goto("/recursos-humanos/funcionarios"), 600);
|
|
||||||
} catch (e: any) {
|
|
||||||
notice = { kind: "error", text: "Erro ao atualizar funcionário." };
|
|
||||||
} finally {
|
|
||||||
loading = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function init() {
|
|
||||||
await loadSimbolos();
|
|
||||||
await loadFuncionario();
|
|
||||||
}
|
|
||||||
|
|
||||||
$effect(() => {
|
|
||||||
if (funcionarioId) {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if loadingData}
|
|
||||||
<div class="flex items-center justify-center min-h-screen">
|
|
||||||
<span class="loading loading-spinner loading-lg"></span>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<main class="container mx-auto px-4 py-4 max-w-7xl">
|
|
||||||
<!-- Breadcrumb -->
|
|
||||||
<div class="text-sm breadcrumbs mb-4">
|
|
||||||
<ul>
|
|
||||||
<li><a href="/recursos-humanos" class="text-primary hover:underline">Recursos Humanos</a></li>
|
|
||||||
<li><a href="/recursos-humanos/funcionarios" class="text-primary hover:underline">Funcionários</a></li>
|
|
||||||
<li>Editar</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Cabeçalho -->
|
|
||||||
<div class="mb-6">
|
|
||||||
<div class="flex items-center gap-4 mb-2">
|
|
||||||
<div class="p-3 bg-yellow-500/20 rounded-xl">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-yellow-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h1 class="text-3xl font-bold text-primary">Editar Funcionário</h1>
|
|
||||||
<p class="text-base-content/70">Atualize as informações do funcionário</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Alertas -->
|
|
||||||
{#if notice}
|
|
||||||
<div class="alert mb-6 shadow-lg" class:alert-success={notice.kind === "success"} class:alert-error={notice.kind === "error"}>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
|
|
||||||
{#if notice.kind === "success"}
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
||||||
{:else}
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
||||||
{/if}
|
|
||||||
</svg>
|
|
||||||
<span>{notice.text}</span>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- Formulário de Edição -->
|
|
||||||
<form class="space-y-6" onsubmit={(e) => { e.preventDefault(); handleSubmit(); }}>
|
|
||||||
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Extract form from cadastro (from line 294 to 1181)
|
|
||||||
const cadastroLines = cadastro.split('\n');
|
|
||||||
const formLines = cadastroLines.slice(293, 1181); // Get lines 294-1181 (0-indexed)
|
|
||||||
const formContent = formLines.join('\n');
|
|
||||||
|
|
||||||
// Replace "Cadastrar" with "Atualizar" in button
|
|
||||||
const fixedForm = formContent
|
|
||||||
.replace('Cadastrar Funcionário', 'Atualizar Funcionário')
|
|
||||||
.replace('Cadastrando...', 'Atualizando...');
|
|
||||||
|
|
||||||
const finalContent = editContent + fixedForm + '\n </form>\n </main>\n{/if}';
|
|
||||||
|
|
||||||
fs.writeFileSync(editarPath, finalContent, 'utf8');
|
|
||||||
|
|
||||||
console.log(`✓ File created successfully!`);
|
|
||||||
console.log(` Total lines: ${finalContent.split('\n').length}`);
|
|
||||||
console.log(` File saved to: ${editarPath}`);
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user