create-fluxstack 1.5.0 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +1 -8
- package/app/client/src/App.tsx +1 -4
- package/app/server/index.ts +0 -4
- package/app/server/routes/index.ts +1 -5
- package/config/index.ts +1 -9
- package/core/cli/generators/plugin.ts +34 -324
- package/core/cli/generators/template-engine.ts +0 -5
- package/core/cli/plugin-discovery.ts +12 -33
- package/core/framework/server.ts +0 -10
- package/core/plugins/dependency-manager.ts +22 -89
- package/core/plugins/index.ts +0 -4
- package/core/plugins/manager.ts +2 -3
- package/core/plugins/registry.ts +1 -28
- package/core/utils/logger/index.ts +0 -4
- package/core/utils/version.ts +1 -1
- package/fluxstack.config.ts +114 -253
- package/package.json +117 -117
- package/CRYPTO-AUTH-MIDDLEWARE-GUIDE.md +0 -475
- package/CRYPTO-AUTH-MIDDLEWARES.md +0 -473
- package/CRYPTO-AUTH-USAGE.md +0 -491
- package/EXEMPLO-ROTA-PROTEGIDA.md +0 -347
- package/QUICK-START-CRYPTO-AUTH.md +0 -221
- package/app/client/src/pages/CryptoAuthPage.tsx +0 -394
- package/app/server/routes/crypto-auth-demo.routes.ts +0 -167
- package/app/server/routes/example-with-crypto-auth.routes.ts +0 -235
- package/app/server/routes/exemplo-posts.routes.ts +0 -161
- package/core/plugins/module-resolver.ts +0 -216
- package/plugins/crypto-auth/README.md +0 -788
- package/plugins/crypto-auth/ai-context.md +0 -1282
- package/plugins/crypto-auth/cli/make-protected-route.command.ts +0 -383
- package/plugins/crypto-auth/client/CryptoAuthClient.ts +0 -302
- package/plugins/crypto-auth/client/components/AuthProvider.tsx +0 -131
- package/plugins/crypto-auth/client/components/LoginButton.tsx +0 -138
- package/plugins/crypto-auth/client/components/ProtectedRoute.tsx +0 -89
- package/plugins/crypto-auth/client/components/index.ts +0 -12
- package/plugins/crypto-auth/client/index.ts +0 -12
- package/plugins/crypto-auth/config/index.ts +0 -34
- package/plugins/crypto-auth/index.ts +0 -162
- package/plugins/crypto-auth/package.json +0 -66
- package/plugins/crypto-auth/server/AuthMiddleware.ts +0 -181
- package/plugins/crypto-auth/server/CryptoAuthService.ts +0 -186
- package/plugins/crypto-auth/server/index.ts +0 -22
- package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +0 -65
- package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +0 -26
- package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +0 -76
- package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +0 -45
- package/plugins/crypto-auth/server/middlewares/helpers.ts +0 -140
- package/plugins/crypto-auth/server/middlewares/index.ts +0 -22
- package/plugins/crypto-auth/server/middlewares.ts +0 -19
- package/test-crypto-auth.ts +0 -101
|
@@ -1,475 +0,0 @@
|
|
|
1
|
-
# 🔐 Crypto Auth - Guia de Middlewares
|
|
2
|
-
|
|
3
|
-
> **✅ Nova Abordagem**: Middlewares declarativos - sem necessidade de configurar listas de paths!
|
|
4
|
-
|
|
5
|
-
## 📖 **Visão Geral**
|
|
6
|
-
|
|
7
|
-
O plugin Crypto Auth agora usa **middlewares Elysia nativos** aplicados diretamente nas rotas. Isso torna o código mais limpo, explícito e fácil de manter.
|
|
8
|
-
|
|
9
|
-
## 🚀 **Quick Start**
|
|
10
|
-
|
|
11
|
-
### **1. Configuração Simplificada**
|
|
12
|
-
|
|
13
|
-
```typescript
|
|
14
|
-
// fluxstack.config.ts
|
|
15
|
-
plugins: {
|
|
16
|
-
enabled: ['crypto-auth'],
|
|
17
|
-
config: {
|
|
18
|
-
'crypto-auth': {
|
|
19
|
-
enabled: true,
|
|
20
|
-
maxTimeDrift: 300000, // 5 minutos
|
|
21
|
-
adminKeys: [
|
|
22
|
-
'abc123def456...' // Chaves públicas dos admins
|
|
23
|
-
],
|
|
24
|
-
enableMetrics: true
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
**✅ Removido**: `protectedRoutes` e `publicRoutes`
|
|
31
|
-
**✅ Novo**: Middlewares aplicados diretamente nas rotas
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
## 🔌 **Middlewares Disponíveis**
|
|
36
|
-
|
|
37
|
-
### **1. `cryptoAuthRequired()` - Requer Autenticação**
|
|
38
|
-
|
|
39
|
-
Bloqueia a rota se não houver assinatura válida.
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
import { cryptoAuthRequired, getCryptoAuthUser } from '@/plugins/crypto-auth/server'
|
|
43
|
-
import { Elysia } from 'elysia'
|
|
44
|
-
|
|
45
|
-
export const protectedRoutes = new Elysia()
|
|
46
|
-
.use(cryptoAuthRequired()) // ⚡ Middleware aplicado
|
|
47
|
-
|
|
48
|
-
.get('/profile', ({ request }) => {
|
|
49
|
-
const user = getCryptoAuthUser(request)! // Garantido que existe
|
|
50
|
-
return {
|
|
51
|
-
publicKey: user.publicKey,
|
|
52
|
-
isAdmin: user.isAdmin
|
|
53
|
-
}
|
|
54
|
-
})
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
**Response se não autenticado (401):**
|
|
58
|
-
```json
|
|
59
|
-
{
|
|
60
|
-
"error": {
|
|
61
|
-
"message": "Authentication required",
|
|
62
|
-
"code": "CRYPTO_AUTH_REQUIRED",
|
|
63
|
-
"statusCode": 401
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
### **2. `cryptoAuthAdmin()` - Requer Admin**
|
|
71
|
-
|
|
72
|
-
Bloqueia a rota se não for administrador.
|
|
73
|
-
|
|
74
|
-
```typescript
|
|
75
|
-
import { cryptoAuthAdmin } from '@/plugins/crypto-auth/server'
|
|
76
|
-
|
|
77
|
-
export const adminRoutes = new Elysia()
|
|
78
|
-
.use(cryptoAuthAdmin()) // ⚡ Requer admin
|
|
79
|
-
|
|
80
|
-
.delete('/users/:id', ({ params, request }) => {
|
|
81
|
-
const user = getCryptoAuthUser(request)! // Garantido admin
|
|
82
|
-
return {
|
|
83
|
-
deleted: params.id,
|
|
84
|
-
by: user.publicKey
|
|
85
|
-
}
|
|
86
|
-
})
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
**Response se não for admin (403):**
|
|
90
|
-
```json
|
|
91
|
-
{
|
|
92
|
-
"error": {
|
|
93
|
-
"message": "Admin privileges required",
|
|
94
|
-
"code": "ADMIN_REQUIRED",
|
|
95
|
-
"statusCode": 403,
|
|
96
|
-
"yourPermissions": ["user", "read"]
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
### **3. `cryptoAuthPermissions([...])` - Requer Permissões**
|
|
104
|
-
|
|
105
|
-
Bloqueia se não tiver as permissões específicas.
|
|
106
|
-
|
|
107
|
-
```typescript
|
|
108
|
-
import { cryptoAuthPermissions } from '@/plugins/crypto-auth/server'
|
|
109
|
-
|
|
110
|
-
export const writeRoutes = new Elysia()
|
|
111
|
-
.use(cryptoAuthPermissions(['write', 'edit'])) // ⚡ Requer ambas
|
|
112
|
-
|
|
113
|
-
.post('/posts', ({ body }) => {
|
|
114
|
-
return { created: body }
|
|
115
|
-
})
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
**Response se sem permissão (403):**
|
|
119
|
-
```json
|
|
120
|
-
{
|
|
121
|
-
"error": {
|
|
122
|
-
"message": "Insufficient permissions",
|
|
123
|
-
"code": "PERMISSION_DENIED",
|
|
124
|
-
"statusCode": 403,
|
|
125
|
-
"required": ["write", "edit"],
|
|
126
|
-
"yours": ["read"]
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
### **4. `cryptoAuthOptional()` - Autenticação Opcional**
|
|
134
|
-
|
|
135
|
-
Não bloqueia, mas adiciona `user` se autenticado.
|
|
136
|
-
|
|
137
|
-
```typescript
|
|
138
|
-
import { cryptoAuthOptional, getCryptoAuthUser } from '@/plugins/crypto-auth/server'
|
|
139
|
-
|
|
140
|
-
export const feedRoutes = new Elysia()
|
|
141
|
-
.use(cryptoAuthOptional()) // ⚡ Opcional
|
|
142
|
-
|
|
143
|
-
.get('/posts', ({ request }) => {
|
|
144
|
-
const user = getCryptoAuthUser(request) // Pode ser null
|
|
145
|
-
|
|
146
|
-
return {
|
|
147
|
-
posts: getPosts(),
|
|
148
|
-
personalizedFor: user ? user.publicKey : 'anonymous'
|
|
149
|
-
}
|
|
150
|
-
})
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
## 🎯 **Padrões de Uso**
|
|
156
|
-
|
|
157
|
-
### **Padrão 1: Grupo de Rotas Protegidas**
|
|
158
|
-
|
|
159
|
-
```typescript
|
|
160
|
-
import { Elysia } from 'elysia'
|
|
161
|
-
import { cryptoAuthRequired } from '@/plugins/crypto-auth/server'
|
|
162
|
-
|
|
163
|
-
export const apiRoutes = new Elysia({ prefix: '/api' })
|
|
164
|
-
|
|
165
|
-
// Rotas públicas
|
|
166
|
-
.get('/health', () => ({ status: 'ok' }))
|
|
167
|
-
.get('/docs', () => ({ version: '1.0.0' }))
|
|
168
|
-
|
|
169
|
-
// Grupo protegido
|
|
170
|
-
.group('/users', (app) => app
|
|
171
|
-
.use(cryptoAuthRequired()) // ⚡ Todas as rotas do grupo requerem auth
|
|
172
|
-
|
|
173
|
-
.get('/', ({ request }) => {
|
|
174
|
-
const user = getCryptoAuthUser(request)!
|
|
175
|
-
return { users: getUsers(user.publicKey) }
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
.post('/', ({ body }) => {
|
|
179
|
-
return { created: body }
|
|
180
|
-
})
|
|
181
|
-
)
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
---
|
|
185
|
-
|
|
186
|
-
### **Padrão 2: Mix de Permissões no Mesmo Grupo**
|
|
187
|
-
|
|
188
|
-
```typescript
|
|
189
|
-
export const postsRoutes = new Elysia({ prefix: '/api/posts' })
|
|
190
|
-
|
|
191
|
-
// Leitura: apenas auth
|
|
192
|
-
.group('', (app) => app
|
|
193
|
-
.use(cryptoAuthRequired())
|
|
194
|
-
|
|
195
|
-
.get('/', () => ({ posts: [] }))
|
|
196
|
-
.get('/:id', ({ params }) => ({ post: params.id }))
|
|
197
|
-
)
|
|
198
|
-
|
|
199
|
-
// Escrita: auth + permissão write
|
|
200
|
-
.group('', (app) => app
|
|
201
|
-
.use(cryptoAuthPermissions(['write']))
|
|
202
|
-
|
|
203
|
-
.post('/', ({ body }) => ({ created: body }))
|
|
204
|
-
.put('/:id', ({ params, body }) => ({ updated: params.id }))
|
|
205
|
-
)
|
|
206
|
-
|
|
207
|
-
// Deleção: só admin
|
|
208
|
-
.group('', (app) => app
|
|
209
|
-
.use(cryptoAuthAdmin())
|
|
210
|
-
|
|
211
|
-
.delete('/:id', ({ params }) => ({ deleted: params.id }))
|
|
212
|
-
)
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
---
|
|
216
|
-
|
|
217
|
-
### **Padrão 3: Auth Opcional com Comportamento Diferente**
|
|
218
|
-
|
|
219
|
-
```typescript
|
|
220
|
-
import { cryptoAuthOptional, getCryptoAuthUser, isCryptoAuthAdmin } from '@/plugins/crypto-auth/server'
|
|
221
|
-
|
|
222
|
-
export const contentRoutes = new Elysia({ prefix: '/api/content' })
|
|
223
|
-
.use(cryptoAuthOptional()) // ⚡ Auth opcional para todas
|
|
224
|
-
|
|
225
|
-
.get('/articles/:id', ({ request, params }) => {
|
|
226
|
-
const user = getCryptoAuthUser(request)
|
|
227
|
-
const isAdmin = isCryptoAuthAdmin(request)
|
|
228
|
-
const article = getArticle(params.id)
|
|
229
|
-
|
|
230
|
-
return {
|
|
231
|
-
...article,
|
|
232
|
-
premium: user ? article.premiumContent : '[Premium - Login Required]',
|
|
233
|
-
canEdit: isAdmin,
|
|
234
|
-
canComment: !!user
|
|
235
|
-
}
|
|
236
|
-
})
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
---
|
|
240
|
-
|
|
241
|
-
## 🛠️ **Helpers Disponíveis**
|
|
242
|
-
|
|
243
|
-
### **`getCryptoAuthUser(request)`**
|
|
244
|
-
|
|
245
|
-
Retorna o usuário autenticado ou `null`.
|
|
246
|
-
|
|
247
|
-
```typescript
|
|
248
|
-
import { getCryptoAuthUser } from '@/plugins/crypto-auth/server'
|
|
249
|
-
|
|
250
|
-
.get('/me', ({ request }) => {
|
|
251
|
-
const user = getCryptoAuthUser(request)
|
|
252
|
-
|
|
253
|
-
if (!user) {
|
|
254
|
-
return { error: 'Not authenticated' }
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
return { user }
|
|
258
|
-
})
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
### **`isCryptoAuthAuthenticated(request)`**
|
|
264
|
-
|
|
265
|
-
Verifica se está autenticado.
|
|
266
|
-
|
|
267
|
-
```typescript
|
|
268
|
-
import { isCryptoAuthAuthenticated } from '@/plugins/crypto-auth/server'
|
|
269
|
-
|
|
270
|
-
.get('/status', ({ request }) => {
|
|
271
|
-
return {
|
|
272
|
-
authenticated: isCryptoAuthAuthenticated(request)
|
|
273
|
-
}
|
|
274
|
-
})
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
---
|
|
278
|
-
|
|
279
|
-
### **`isCryptoAuthAdmin(request)`**
|
|
280
|
-
|
|
281
|
-
Verifica se é admin.
|
|
282
|
-
|
|
283
|
-
```typescript
|
|
284
|
-
import { isCryptoAuthAdmin } from '@/plugins/crypto-auth/server'
|
|
285
|
-
|
|
286
|
-
.get('/posts/:id', ({ request, params }) => {
|
|
287
|
-
const post = getPost(params.id)
|
|
288
|
-
|
|
289
|
-
return {
|
|
290
|
-
...post,
|
|
291
|
-
canEdit: isCryptoAuthAdmin(request)
|
|
292
|
-
}
|
|
293
|
-
})
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
---
|
|
297
|
-
|
|
298
|
-
### **`hasCryptoAuthPermission(request, permission)`**
|
|
299
|
-
|
|
300
|
-
Verifica permissão específica.
|
|
301
|
-
|
|
302
|
-
```typescript
|
|
303
|
-
import { hasCryptoAuthPermission } from '@/plugins/crypto-auth/server'
|
|
304
|
-
|
|
305
|
-
.post('/posts/:id/publish', ({ request, params }) => {
|
|
306
|
-
if (!hasCryptoAuthPermission(request, 'publish')) {
|
|
307
|
-
return { error: 'Permission denied' }
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
return publishPost(params.id)
|
|
311
|
-
})
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
---
|
|
315
|
-
|
|
316
|
-
## 📋 **Estrutura do User**
|
|
317
|
-
|
|
318
|
-
```typescript
|
|
319
|
-
interface CryptoAuthUser {
|
|
320
|
-
publicKey: string // Chave pública Ed25519 (hex)
|
|
321
|
-
isAdmin: boolean // Se está na lista adminKeys
|
|
322
|
-
permissions: string[] // ['read', 'write', 'admin', ...]
|
|
323
|
-
}
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
**Como o `isAdmin` é determinado:**
|
|
327
|
-
```typescript
|
|
328
|
-
// Plugin verifica se a publicKey está em adminKeys
|
|
329
|
-
const isAdmin = config.adminKeys.includes(user.publicKey)
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
---
|
|
333
|
-
|
|
334
|
-
## 🔄 **Migrando da Abordagem Antiga**
|
|
335
|
-
|
|
336
|
-
### **❌ Antes (listas de paths)**
|
|
337
|
-
|
|
338
|
-
```typescript
|
|
339
|
-
// fluxstack.config.ts
|
|
340
|
-
plugins: {
|
|
341
|
-
config: {
|
|
342
|
-
'crypto-auth': {
|
|
343
|
-
protectedRoutes: ['/api/users/*', '/api/admin/*'],
|
|
344
|
-
publicRoutes: ['/api/health', '/api/docs']
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// Rotas (sem controle explícito)
|
|
350
|
-
export const routes = new Elysia()
|
|
351
|
-
.get('/api/users', handler) // Protegido pelo plugin
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
### **✅ Agora (middlewares declarativos)**
|
|
355
|
-
|
|
356
|
-
```typescript
|
|
357
|
-
// fluxstack.config.ts
|
|
358
|
-
plugins: {
|
|
359
|
-
config: {
|
|
360
|
-
'crypto-auth': {
|
|
361
|
-
adminKeys: ['abc123...']
|
|
362
|
-
// Sem protectedRoutes/publicRoutes!
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// Rotas (controle explícito)
|
|
368
|
-
import { cryptoAuthRequired } from '@/plugins/crypto-auth/server'
|
|
369
|
-
|
|
370
|
-
export const routes = new Elysia()
|
|
371
|
-
.get('/health', handler) // ✅ Público explicitamente
|
|
372
|
-
|
|
373
|
-
.group('/users', (app) => app
|
|
374
|
-
.use(cryptoAuthRequired()) // ✅ Protegido explicitamente
|
|
375
|
-
.get('/', handler)
|
|
376
|
-
)
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
---
|
|
380
|
-
|
|
381
|
-
## 🎯 **Vantagens da Nova Abordagem**
|
|
382
|
-
|
|
383
|
-
| Aspecto | Antes | Agora |
|
|
384
|
-
|---------|-------|-------|
|
|
385
|
-
| **Clareza** | Rotas implicitamente protegidas | ✅ Explícito no código |
|
|
386
|
-
| **Manutenção** | Editar config + rotas | ✅ Editar apenas rotas |
|
|
387
|
-
| **Type Safety** | Sem garantia de user | ✅ TypeScript sabe que user existe |
|
|
388
|
-
| **Flexibilidade** | Apenas on/off | ✅ Permissões, admin, opcional |
|
|
389
|
-
| **Debugging** | Difícil rastrear proteção | ✅ Fácil ver middleware aplicado |
|
|
390
|
-
|
|
391
|
-
---
|
|
392
|
-
|
|
393
|
-
## 🧪 **Testando**
|
|
394
|
-
|
|
395
|
-
### **Rota Pública**
|
|
396
|
-
```bash
|
|
397
|
-
curl http://localhost:3000/api/crypto-auth/public
|
|
398
|
-
# ✅ 200 OK - sem headers
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
### **Rota Protegida (sem auth)**
|
|
402
|
-
```bash
|
|
403
|
-
curl http://localhost:3000/api/crypto-auth/protected
|
|
404
|
-
# ❌ 401 Unauthorized
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
### **Rota Protegida (com auth)**
|
|
408
|
-
```bash
|
|
409
|
-
curl http://localhost:3000/api/crypto-auth/protected \
|
|
410
|
-
-H "x-public-key: abc123..." \
|
|
411
|
-
-H "x-timestamp: 1234567890" \
|
|
412
|
-
-H "x-nonce: xyz789" \
|
|
413
|
-
-H "x-signature: def456..."
|
|
414
|
-
# ✅ 200 OK
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
### **Rota Admin (sem ser admin)**
|
|
418
|
-
```bash
|
|
419
|
-
curl http://localhost:3000/api/crypto-auth/admin \
|
|
420
|
-
-H "x-public-key: user123..." \
|
|
421
|
-
-H "x-signature: ..."
|
|
422
|
-
# ❌ 403 Forbidden - "Admin privileges required"
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
---
|
|
426
|
-
|
|
427
|
-
## 📚 **Exemplos Completos**
|
|
428
|
-
|
|
429
|
-
Veja exemplos práticos em:
|
|
430
|
-
- `app/server/routes/crypto-auth-demo.routes.ts` - Rotas de demonstração
|
|
431
|
-
- `plugins/crypto-auth/server/middlewares.ts` - Implementação dos middlewares
|
|
432
|
-
|
|
433
|
-
---
|
|
434
|
-
|
|
435
|
-
## 🆘 **Troubleshooting**
|
|
436
|
-
|
|
437
|
-
### **Erro: "CryptoAuthService not initialized"**
|
|
438
|
-
|
|
439
|
-
**Causa**: Plugin não está carregado.
|
|
440
|
-
|
|
441
|
-
**Solução**:
|
|
442
|
-
```typescript
|
|
443
|
-
// fluxstack.config.ts
|
|
444
|
-
plugins: {
|
|
445
|
-
enabled: ['crypto-auth'], // ✅ Adicione aqui
|
|
446
|
-
}
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
### **User sempre null**
|
|
450
|
-
|
|
451
|
-
**Causa**: Não está usando o middleware.
|
|
452
|
-
|
|
453
|
-
**Solução**:
|
|
454
|
-
```typescript
|
|
455
|
-
// ❌ Errado
|
|
456
|
-
.get('/protected', ({ request }) => {
|
|
457
|
-
const user = getCryptoAuthUser(request) // null
|
|
458
|
-
})
|
|
459
|
-
|
|
460
|
-
// ✅ Correto
|
|
461
|
-
.use(cryptoAuthRequired())
|
|
462
|
-
.get('/protected', ({ request }) => {
|
|
463
|
-
const user = getCryptoAuthUser(request)! // Garantido
|
|
464
|
-
})
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
### **403 ao invés de 401**
|
|
468
|
-
|
|
469
|
-
**Causa**: Usuário autenticado mas sem permissão.
|
|
470
|
-
|
|
471
|
-
**Solução**: Verificar se `adminKeys` ou permissões estão corretas.
|
|
472
|
-
|
|
473
|
-
---
|
|
474
|
-
|
|
475
|
-
**✅ Pronto!** Agora você tem controle total e explícito sobre quais rotas são protegidas, sem precisar configurar listas de paths!
|