create-fluxstack 1.0.22 → 1.4.0
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/app/server/backend-only.ts +5 -5
- package/app/server/index.ts +63 -54
- package/app/server/live/FluxStackConfig.ts +43 -39
- package/app/server/live/SystemMonitorIntegration.ts +2 -2
- package/app/server/live/register-components.ts +6 -26
- package/app/server/middleware/errorHandling.ts +6 -4
- package/app/server/routes/config.ts +145 -0
- package/app/server/routes/index.ts +5 -3
- package/config/app.config.ts +113 -0
- package/config/build.config.ts +24 -0
- package/config/database.config.ts +99 -0
- package/config/index.ts +68 -0
- package/config/logger.config.ts +27 -0
- package/config/runtime.config.ts +92 -0
- package/config/server.config.ts +46 -0
- package/config/services.config.ts +130 -0
- package/config/system.config.ts +105 -0
- package/core/build/bundler.ts +53 -5
- package/core/build/flux-plugins-generator.ts +315 -0
- package/core/build/index.ts +11 -7
- package/core/build/live-components-generator.ts +231 -0
- package/core/build/optimizer.ts +2 -54
- package/core/cli/index.ts +31 -13
- package/core/config/env.ts +38 -94
- package/core/config/runtime-config.ts +61 -58
- package/core/config/schema.ts +1 -0
- package/core/framework/server.ts +55 -11
- package/core/plugins/built-in/index.ts +7 -17
- package/core/plugins/built-in/static/index.ts +24 -10
- package/core/plugins/built-in/swagger/index.ts +228 -228
- package/core/plugins/built-in/vite/index.ts +374 -358
- package/core/plugins/dependency-manager.ts +5 -5
- package/core/plugins/manager.ts +57 -14
- package/core/plugins/registry.ts +3 -3
- package/core/server/index.ts +0 -1
- package/core/server/live/ComponentRegistry.ts +34 -8
- package/core/server/live/LiveComponentPerformanceMonitor.ts +1 -1
- package/core/server/live/websocket-plugin.ts +434 -434
- package/core/server/middleware/README.md +488 -0
- package/core/server/middleware/elysia-helpers.ts +227 -0
- package/core/server/middleware/index.ts +25 -9
- package/core/server/plugins/static-files-plugin.ts +231 -231
- package/core/utils/config-schema.ts +484 -0
- package/core/utils/env.ts +306 -0
- package/core/utils/helpers.ts +9 -3
- package/core/utils/logger/colors.ts +114 -0
- package/core/utils/logger/config.ts +35 -0
- package/core/utils/logger/formatter.ts +82 -0
- package/core/utils/logger/group-logger.ts +101 -0
- package/core/utils/logger/index.ts +199 -250
- package/core/utils/logger/stack-trace.ts +92 -0
- package/core/utils/logger/startup-banner.ts +92 -0
- package/core/utils/logger/winston-logger.ts +152 -0
- package/core/utils/version.ts +5 -0
- package/create-fluxstack.ts +1 -0
- package/fluxstack.config.ts +6 -12
- package/package.json +117 -114
- package/plugins/crypto-auth/README.md +238 -0
- package/plugins/crypto-auth/client/CryptoAuthClient.ts +325 -0
- package/plugins/crypto-auth/client/components/AuthProvider.tsx +190 -0
- package/plugins/crypto-auth/client/components/LoginButton.tsx +155 -0
- package/plugins/crypto-auth/client/components/ProtectedRoute.tsx +109 -0
- package/plugins/crypto-auth/client/components/SessionInfo.tsx +242 -0
- package/plugins/crypto-auth/client/components/index.ts +15 -0
- package/plugins/crypto-auth/client/index.ts +12 -0
- package/plugins/crypto-auth/index.ts +230 -0
- package/plugins/crypto-auth/package.json +65 -0
- package/plugins/crypto-auth/plugin.json +29 -0
- package/plugins/crypto-auth/server/AuthMiddleware.ts +237 -0
- package/plugins/crypto-auth/server/CryptoAuthService.ts +293 -0
- package/plugins/crypto-auth/server/index.ts +9 -0
- package/vite.config.ts +16 -0
- package/core/config/env-dynamic.ts +0 -326
- package/core/plugins/built-in/logger/index.ts +0 -180
- package/core/server/plugins/logger.ts +0 -47
- package/core/utils/env-runtime-v2.ts +0 -232
- package/core/utils/env-runtime.ts +0 -259
- package/core/utils/logger/formatters.ts +0 -222
- package/core/utils/logger/middleware.ts +0 -253
- package/core/utils/logger/performance.ts +0 -384
- package/core/utils/logger/transports.ts +0 -365
- package/core/utils/logger.ts +0 -106
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exportações dos componentes do cliente
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export { LoginButton } from './LoginButton'
|
|
6
|
+
export type { LoginButtonProps } from './LoginButton'
|
|
7
|
+
|
|
8
|
+
export { AuthProvider, useAuth } from './AuthProvider'
|
|
9
|
+
export type { AuthProviderProps, AuthContextValue } from './AuthProvider'
|
|
10
|
+
|
|
11
|
+
export { ProtectedRoute, withAuth } from './ProtectedRoute'
|
|
12
|
+
export type { ProtectedRouteProps } from './ProtectedRoute'
|
|
13
|
+
|
|
14
|
+
export { SessionInfo } from './SessionInfo'
|
|
15
|
+
export type { SessionInfoProps } from './SessionInfo'
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exportações principais do cliente de autenticação
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export { CryptoAuthClient } from './CryptoAuthClient'
|
|
6
|
+
export type { SessionInfo, AuthConfig, SignedRequestOptions } from './CryptoAuthClient'
|
|
7
|
+
|
|
8
|
+
// Componentes React
|
|
9
|
+
export * from './components'
|
|
10
|
+
|
|
11
|
+
// Re-exportar para compatibilidade
|
|
12
|
+
export { CryptoAuthClient as default } from './CryptoAuthClient'
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FluxStack Crypto Auth Plugin
|
|
3
|
+
* Sistema de autenticação baseado em criptografia Ed25519
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { FluxStack, PluginContext, RequestContext, ResponseContext } from "../../core/plugins/types"
|
|
7
|
+
|
|
8
|
+
type Plugin = FluxStack.Plugin
|
|
9
|
+
import { CryptoAuthService, AuthMiddleware } from "./server"
|
|
10
|
+
|
|
11
|
+
export const cryptoAuthPlugin: Plugin = {
|
|
12
|
+
name: "crypto-auth",
|
|
13
|
+
version: "1.0.0",
|
|
14
|
+
description: "Sistema de autenticação baseado em criptografia Ed25519 para FluxStack",
|
|
15
|
+
author: "FluxStack Team",
|
|
16
|
+
priority: 100, // Alta prioridade para autenticação
|
|
17
|
+
category: "auth",
|
|
18
|
+
tags: ["authentication", "ed25519", "cryptography", "security"],
|
|
19
|
+
dependencies: [],
|
|
20
|
+
|
|
21
|
+
configSchema: {
|
|
22
|
+
type: "object",
|
|
23
|
+
properties: {
|
|
24
|
+
enabled: {
|
|
25
|
+
type: "boolean",
|
|
26
|
+
description: "Habilitar autenticação criptográfica"
|
|
27
|
+
},
|
|
28
|
+
sessionTimeout: {
|
|
29
|
+
type: "number",
|
|
30
|
+
minimum: 300000, // 5 minutos mínimo
|
|
31
|
+
description: "Timeout da sessão em millisegundos"
|
|
32
|
+
},
|
|
33
|
+
maxTimeDrift: {
|
|
34
|
+
type: "number",
|
|
35
|
+
minimum: 30000,
|
|
36
|
+
description: "Máximo drift de tempo permitido em millisegundos"
|
|
37
|
+
},
|
|
38
|
+
adminKeys: {
|
|
39
|
+
type: "array",
|
|
40
|
+
items: { type: "string" },
|
|
41
|
+
description: "Chaves públicas dos administradores"
|
|
42
|
+
},
|
|
43
|
+
protectedRoutes: {
|
|
44
|
+
type: "array",
|
|
45
|
+
items: { type: "string" },
|
|
46
|
+
description: "Rotas que requerem autenticação"
|
|
47
|
+
},
|
|
48
|
+
publicRoutes: {
|
|
49
|
+
type: "array",
|
|
50
|
+
items: { type: "string" },
|
|
51
|
+
description: "Rotas públicas (não requerem autenticação)"
|
|
52
|
+
},
|
|
53
|
+
enableMetrics: {
|
|
54
|
+
type: "boolean",
|
|
55
|
+
description: "Habilitar métricas de autenticação"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
additionalProperties: false
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
defaultConfig: {
|
|
62
|
+
enabled: true,
|
|
63
|
+
sessionTimeout: 1800000, // 30 minutos
|
|
64
|
+
maxTimeDrift: 300000, // 5 minutos
|
|
65
|
+
adminKeys: [],
|
|
66
|
+
protectedRoutes: ["/api/admin/*", "/api/protected/*"],
|
|
67
|
+
publicRoutes: ["/api/auth/*", "/api/health", "/api/docs"],
|
|
68
|
+
enableMetrics: true
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
setup: async (context: PluginContext) => {
|
|
72
|
+
const config = getPluginConfig(context)
|
|
73
|
+
|
|
74
|
+
if (!config.enabled) {
|
|
75
|
+
context.logger.info('Crypto Auth plugin desabilitado por configuração')
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Inicializar serviço de autenticação
|
|
80
|
+
const authService = new CryptoAuthService({
|
|
81
|
+
sessionTimeout: config.sessionTimeout,
|
|
82
|
+
maxTimeDrift: config.maxTimeDrift,
|
|
83
|
+
adminKeys: config.adminKeys,
|
|
84
|
+
logger: context.logger
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
// Inicializar middleware de autenticação
|
|
88
|
+
const authMiddleware = new AuthMiddleware(authService, {
|
|
89
|
+
protectedRoutes: config.protectedRoutes,
|
|
90
|
+
publicRoutes: config.publicRoutes,
|
|
91
|
+
logger: context.logger
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
// Armazenar instâncias no contexto para uso posterior
|
|
95
|
+
;(context as any).authService = authService
|
|
96
|
+
;(context as any).authMiddleware = authMiddleware
|
|
97
|
+
|
|
98
|
+
// Registrar rotas de autenticação
|
|
99
|
+
context.app.group("/api/auth", (app: any) => {
|
|
100
|
+
// Rota para inicializar sessão
|
|
101
|
+
app.post("/session/init", async ({ body, set }: any) => {
|
|
102
|
+
try {
|
|
103
|
+
const result = await authService.initializeSession(body)
|
|
104
|
+
return result
|
|
105
|
+
} catch (error) {
|
|
106
|
+
context.logger.error("Erro ao inicializar sessão", { error })
|
|
107
|
+
set.status = 500
|
|
108
|
+
return { success: false, error: "Erro interno do servidor" }
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
// Rota para validar sessão
|
|
113
|
+
app.post("/session/validate", async ({ body, set }: any) => {
|
|
114
|
+
try {
|
|
115
|
+
const result = await authService.validateSession(body)
|
|
116
|
+
return result
|
|
117
|
+
} catch (error) {
|
|
118
|
+
context.logger.error("Erro ao validar sessão", { error })
|
|
119
|
+
set.status = 500
|
|
120
|
+
return { success: false, error: "Erro interno do servidor" }
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
// Rota para obter informações da sessão
|
|
125
|
+
app.get("/session/info", async ({ headers, set }: any) => {
|
|
126
|
+
try {
|
|
127
|
+
const sessionId = headers['x-session-id']
|
|
128
|
+
if (!sessionId) {
|
|
129
|
+
set.status = 401
|
|
130
|
+
return { success: false, error: "Session ID não fornecido" }
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const sessionInfo = await authService.getSessionInfo(sessionId)
|
|
134
|
+
return { success: true, session: sessionInfo }
|
|
135
|
+
} catch (error) {
|
|
136
|
+
context.logger.error("Erro ao obter informações da sessão", { error })
|
|
137
|
+
set.status = 500
|
|
138
|
+
return { success: false, error: "Erro interno do servidor" }
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
// Rota para logout
|
|
143
|
+
app.post("/session/logout", async ({ headers, set }: any) => {
|
|
144
|
+
try {
|
|
145
|
+
const sessionId = headers['x-session-id']
|
|
146
|
+
if (!sessionId) {
|
|
147
|
+
set.status = 401
|
|
148
|
+
return { success: false, error: "Session ID não fornecido" }
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
await authService.destroySession(sessionId)
|
|
152
|
+
return { success: true, message: "Sessão encerrada com sucesso" }
|
|
153
|
+
} catch (error) {
|
|
154
|
+
context.logger.error("Erro ao encerrar sessão", { error })
|
|
155
|
+
set.status = 500
|
|
156
|
+
return { success: false, error: "Erro interno do servidor" }
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
context.logger.info("Crypto Auth plugin inicializado com sucesso", {
|
|
162
|
+
sessionTimeout: config.sessionTimeout,
|
|
163
|
+
adminKeys: config.adminKeys.length,
|
|
164
|
+
protectedRoutes: config.protectedRoutes.length
|
|
165
|
+
})
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
onRequest: async (context: RequestContext) => {
|
|
169
|
+
const pluginContext = (context as any).pluginContext
|
|
170
|
+
if (!pluginContext?.authMiddleware) return
|
|
171
|
+
|
|
172
|
+
// Aplicar middleware de autenticação
|
|
173
|
+
const authResult = await pluginContext.authMiddleware.authenticate(context)
|
|
174
|
+
|
|
175
|
+
if (!authResult.success && authResult.required) {
|
|
176
|
+
// Marcar como handled para evitar processamento adicional
|
|
177
|
+
;(context as any).handled = true
|
|
178
|
+
;(context as any).authError = authResult.error
|
|
179
|
+
} else if (authResult.success && authResult.user) {
|
|
180
|
+
// Adicionar usuário ao contexto
|
|
181
|
+
;(context as any).user = authResult.user
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
onResponse: async (context: ResponseContext) => {
|
|
186
|
+
const config = getPluginConfig((context as any).pluginContext)
|
|
187
|
+
|
|
188
|
+
if (config.enableMetrics) {
|
|
189
|
+
// Log métricas de autenticação
|
|
190
|
+
const user = (context as any).user
|
|
191
|
+
const authError = (context as any).authError
|
|
192
|
+
|
|
193
|
+
if (user) {
|
|
194
|
+
;((context as any).pluginContext?.logger || console).debug("Requisição autenticada", {
|
|
195
|
+
sessionId: user.sessionId,
|
|
196
|
+
isAdmin: user.isAdmin,
|
|
197
|
+
path: context.path,
|
|
198
|
+
method: context.method,
|
|
199
|
+
duration: context.duration
|
|
200
|
+
})
|
|
201
|
+
} else if (authError) {
|
|
202
|
+
;((context as any).pluginContext?.logger || console).warn("Falha na autenticação", {
|
|
203
|
+
error: authError,
|
|
204
|
+
path: context.path,
|
|
205
|
+
method: context.method
|
|
206
|
+
})
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
onServerStart: async (context: PluginContext) => {
|
|
212
|
+
const config = getPluginConfig(context)
|
|
213
|
+
|
|
214
|
+
if (config.enabled) {
|
|
215
|
+
context.logger.info("Crypto Auth plugin ativo", {
|
|
216
|
+
protectedRoutes: config.protectedRoutes.length,
|
|
217
|
+
publicRoutes: config.publicRoutes.length,
|
|
218
|
+
adminKeys: config.adminKeys.length
|
|
219
|
+
})
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Helper function para obter configuração do plugin
|
|
225
|
+
function getPluginConfig(context: PluginContext) {
|
|
226
|
+
const pluginConfig = context.config.plugins.config?.['crypto-auth'] || {}
|
|
227
|
+
return { ...cryptoAuthPlugin.defaultConfig, ...pluginConfig }
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export default cryptoAuthPlugin
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fluxstack/crypto-auth-plugin",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Plugin de autenticação criptográfica Ed25519 para FluxStack",
|
|
5
|
+
"main": "index.ts",
|
|
6
|
+
"types": "index.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./index.ts",
|
|
10
|
+
"types": "./index.ts"
|
|
11
|
+
},
|
|
12
|
+
"./client": {
|
|
13
|
+
"import": "./client/index.ts",
|
|
14
|
+
"types": "./client/index.ts"
|
|
15
|
+
},
|
|
16
|
+
"./server": {
|
|
17
|
+
"import": "./server/index.ts",
|
|
18
|
+
"types": "./server/index.ts"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"fluxstack",
|
|
23
|
+
"plugin",
|
|
24
|
+
"authentication",
|
|
25
|
+
"ed25519",
|
|
26
|
+
"cryptography",
|
|
27
|
+
"security",
|
|
28
|
+
"react",
|
|
29
|
+
"typescript"
|
|
30
|
+
],
|
|
31
|
+
"author": "FluxStack Team",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"react": ">=16.8.0"
|
|
35
|
+
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"react": {
|
|
38
|
+
"optional": true
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@noble/curves": "^1.2.0",
|
|
43
|
+
"@noble/hashes": "^1.3.2"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/react": "^18.0.0",
|
|
47
|
+
"typescript": "^5.0.0"
|
|
48
|
+
},
|
|
49
|
+
"fluxstack": {
|
|
50
|
+
"version": "^1.0.0",
|
|
51
|
+
"hooks": [
|
|
52
|
+
"setup",
|
|
53
|
+
"onServerStart",
|
|
54
|
+
"onRequest",
|
|
55
|
+
"onResponse"
|
|
56
|
+
],
|
|
57
|
+
"category": "auth",
|
|
58
|
+
"tags": [
|
|
59
|
+
"authentication",
|
|
60
|
+
"ed25519",
|
|
61
|
+
"cryptography",
|
|
62
|
+
"security"
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "crypto-auth",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Sistema de autenticação baseado em criptografia Ed25519 para FluxStack",
|
|
5
|
+
"author": "FluxStack Team",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "index.ts",
|
|
8
|
+
"keywords": ["fluxstack", "plugin", "authentication", "ed25519", "cryptography"],
|
|
9
|
+
"fluxstack": {
|
|
10
|
+
"plugin": true,
|
|
11
|
+
"version": "^1.0.0",
|
|
12
|
+
"category": "auth",
|
|
13
|
+
"tags": ["authentication", "ed25519", "cryptography", "security"]
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@noble/curves": "^1.2.0",
|
|
17
|
+
"@noble/hashes": "^1.3.2",
|
|
18
|
+
"react": ">=16.8.0"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"react": ">=16.8.0"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"index.ts",
|
|
25
|
+
"server/",
|
|
26
|
+
"client/",
|
|
27
|
+
"README.md"
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Middleware de Autenticação
|
|
3
|
+
* Intercepta requisições e valida autenticação
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { RequestContext } from '../../../core/plugins/types'
|
|
7
|
+
import type { CryptoAuthService } from './CryptoAuthService'
|
|
8
|
+
|
|
9
|
+
export interface Logger {
|
|
10
|
+
debug(message: string, meta?: any): void
|
|
11
|
+
info(message: string, meta?: any): void
|
|
12
|
+
warn(message: string, meta?: any): void
|
|
13
|
+
error(message: string, meta?: any): void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface AuthMiddlewareConfig {
|
|
17
|
+
protectedRoutes: string[]
|
|
18
|
+
publicRoutes: string[]
|
|
19
|
+
logger?: Logger
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface AuthMiddlewareResult {
|
|
23
|
+
success: boolean
|
|
24
|
+
required: boolean
|
|
25
|
+
error?: string
|
|
26
|
+
user?: {
|
|
27
|
+
sessionId: string
|
|
28
|
+
isAdmin: boolean
|
|
29
|
+
isSuperAdmin: boolean
|
|
30
|
+
permissions: string[]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class AuthMiddleware {
|
|
35
|
+
private authService: CryptoAuthService
|
|
36
|
+
private config: AuthMiddlewareConfig
|
|
37
|
+
private logger?: Logger
|
|
38
|
+
|
|
39
|
+
constructor(authService: CryptoAuthService, config: AuthMiddlewareConfig) {
|
|
40
|
+
this.authService = authService
|
|
41
|
+
this.config = config
|
|
42
|
+
this.logger = config.logger
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Autenticar requisição
|
|
47
|
+
*/
|
|
48
|
+
async authenticate(context: RequestContext): Promise<AuthMiddlewareResult> {
|
|
49
|
+
const path = context.path
|
|
50
|
+
const method = context.method
|
|
51
|
+
|
|
52
|
+
// Verificar se a rota é pública
|
|
53
|
+
if (this.isPublicRoute(path)) {
|
|
54
|
+
return {
|
|
55
|
+
success: true,
|
|
56
|
+
required: false
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Verificar se a rota requer autenticação
|
|
61
|
+
if (!this.isProtectedRoute(path)) {
|
|
62
|
+
return {
|
|
63
|
+
success: true,
|
|
64
|
+
required: false
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Extrair headers de autenticação
|
|
69
|
+
const authHeaders = this.extractAuthHeaders(context.headers)
|
|
70
|
+
if (!authHeaders) {
|
|
71
|
+
this.logger?.warn("Headers de autenticação ausentes", {
|
|
72
|
+
path,
|
|
73
|
+
method,
|
|
74
|
+
headers: Object.keys(context.headers)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
success: false,
|
|
79
|
+
required: true,
|
|
80
|
+
error: "Headers de autenticação obrigatórios"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Validar sessão
|
|
85
|
+
try {
|
|
86
|
+
const validationResult = await this.authService.validateSession({
|
|
87
|
+
sessionId: authHeaders.sessionId,
|
|
88
|
+
timestamp: authHeaders.timestamp,
|
|
89
|
+
nonce: authHeaders.nonce,
|
|
90
|
+
signature: authHeaders.signature,
|
|
91
|
+
message: this.buildMessage(context)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
if (!validationResult.success) {
|
|
95
|
+
this.logger?.warn("Falha na validação da sessão", {
|
|
96
|
+
path,
|
|
97
|
+
method,
|
|
98
|
+
sessionId: authHeaders.sessionId.substring(0, 8) + "...",
|
|
99
|
+
error: validationResult.error
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
success: false,
|
|
104
|
+
required: true,
|
|
105
|
+
error: validationResult.error
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
this.logger?.debug("Requisição autenticada com sucesso", {
|
|
110
|
+
path,
|
|
111
|
+
method,
|
|
112
|
+
sessionId: authHeaders.sessionId.substring(0, 8) + "...",
|
|
113
|
+
isAdmin: validationResult.user?.isAdmin
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
success: true,
|
|
118
|
+
required: true,
|
|
119
|
+
user: validationResult.user
|
|
120
|
+
}
|
|
121
|
+
} catch (error) {
|
|
122
|
+
this.logger?.error("Erro durante autenticação", {
|
|
123
|
+
path,
|
|
124
|
+
method,
|
|
125
|
+
error
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
success: false,
|
|
130
|
+
required: true,
|
|
131
|
+
error: "Erro interno de autenticação"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Verificar se a rota é pública
|
|
138
|
+
*/
|
|
139
|
+
private isPublicRoute(path: string): boolean {
|
|
140
|
+
return this.config.publicRoutes.some(route => {
|
|
141
|
+
if (route.endsWith('/*')) {
|
|
142
|
+
const prefix = route.slice(0, -2)
|
|
143
|
+
return path.startsWith(prefix)
|
|
144
|
+
}
|
|
145
|
+
return path === route
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Verificar se a rota é protegida
|
|
151
|
+
*/
|
|
152
|
+
private isProtectedRoute(path: string): boolean {
|
|
153
|
+
return this.config.protectedRoutes.some(route => {
|
|
154
|
+
if (route.endsWith('/*')) {
|
|
155
|
+
const prefix = route.slice(0, -2)
|
|
156
|
+
return path.startsWith(prefix)
|
|
157
|
+
}
|
|
158
|
+
return path === route
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Extrair headers de autenticação
|
|
164
|
+
*/
|
|
165
|
+
private extractAuthHeaders(headers: Record<string, string>): {
|
|
166
|
+
sessionId: string
|
|
167
|
+
timestamp: number
|
|
168
|
+
nonce: string
|
|
169
|
+
signature: string
|
|
170
|
+
} | null {
|
|
171
|
+
const sessionId = headers['x-session-id']
|
|
172
|
+
const timestampStr = headers['x-timestamp']
|
|
173
|
+
const nonce = headers['x-nonce']
|
|
174
|
+
const signature = headers['x-signature']
|
|
175
|
+
|
|
176
|
+
if (!sessionId || !timestampStr || !nonce || !signature) {
|
|
177
|
+
return null
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const timestamp = parseInt(timestampStr, 10)
|
|
181
|
+
if (isNaN(timestamp)) {
|
|
182
|
+
return null
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
sessionId,
|
|
187
|
+
timestamp,
|
|
188
|
+
nonce,
|
|
189
|
+
signature
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Construir mensagem para assinatura
|
|
195
|
+
*/
|
|
196
|
+
private buildMessage(context: RequestContext): string {
|
|
197
|
+
// Incluir método, path e body (se houver) na mensagem
|
|
198
|
+
let message = `${context.method}:${context.path}`
|
|
199
|
+
|
|
200
|
+
if (context.body && typeof context.body === 'string') {
|
|
201
|
+
message += `:${context.body}`
|
|
202
|
+
} else if (context.body && typeof context.body === 'object') {
|
|
203
|
+
message += `:${JSON.stringify(context.body)}`
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return message
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Verificar se usuário tem permissão para acessar rota
|
|
211
|
+
*/
|
|
212
|
+
hasPermission(user: any, requiredPermission: string): boolean {
|
|
213
|
+
if (!user || !user.permissions) {
|
|
214
|
+
return false
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return user.permissions.includes(requiredPermission) || user.permissions.includes('admin')
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Verificar se usuário é admin
|
|
222
|
+
*/
|
|
223
|
+
isAdmin(user: any): boolean {
|
|
224
|
+
return user && user.isAdmin === true
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Obter estatísticas do middleware
|
|
229
|
+
*/
|
|
230
|
+
getStats() {
|
|
231
|
+
return {
|
|
232
|
+
protectedRoutes: this.config.protectedRoutes.length,
|
|
233
|
+
publicRoutes: this.config.publicRoutes.length,
|
|
234
|
+
authService: this.authService.getStats()
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|