create-fluxstack 1.4.1 → 1.5.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/.env.example +8 -1
- package/CRYPTO-AUTH-MIDDLEWARE-GUIDE.md +475 -0
- package/CRYPTO-AUTH-MIDDLEWARES.md +473 -0
- package/CRYPTO-AUTH-USAGE.md +491 -0
- package/EXEMPLO-ROTA-PROTEGIDA.md +347 -0
- package/QUICK-START-CRYPTO-AUTH.md +221 -0
- package/app/client/src/App.tsx +4 -1
- package/app/client/src/pages/CryptoAuthPage.tsx +394 -0
- package/app/server/index.ts +4 -0
- package/app/server/routes/crypto-auth-demo.routes.ts +167 -0
- package/app/server/routes/example-with-crypto-auth.routes.ts +235 -0
- package/app/server/routes/exemplo-posts.routes.ts +161 -0
- package/app/server/routes/index.ts +5 -1
- package/config/index.ts +9 -1
- package/core/cli/generators/plugin.ts +324 -34
- package/core/cli/generators/template-engine.ts +5 -0
- package/core/cli/plugin-discovery.ts +33 -12
- package/core/framework/server.ts +10 -0
- package/core/plugins/dependency-manager.ts +89 -22
- package/core/plugins/index.ts +4 -0
- package/core/plugins/manager.ts +3 -2
- package/core/plugins/module-resolver.ts +216 -0
- package/core/plugins/registry.ts +28 -1
- package/core/utils/logger/index.ts +4 -0
- package/fluxstack.config.ts +253 -114
- package/package.json +117 -117
- package/plugins/crypto-auth/README.md +722 -172
- package/plugins/crypto-auth/ai-context.md +1282 -0
- package/plugins/crypto-auth/cli/make-protected-route.command.ts +383 -0
- package/plugins/crypto-auth/client/CryptoAuthClient.ts +136 -159
- package/plugins/crypto-auth/client/components/AuthProvider.tsx +35 -94
- package/plugins/crypto-auth/client/components/LoginButton.tsx +36 -53
- package/plugins/crypto-auth/client/components/ProtectedRoute.tsx +17 -37
- package/plugins/crypto-auth/client/components/index.ts +1 -4
- package/plugins/crypto-auth/client/index.ts +1 -1
- package/plugins/crypto-auth/config/index.ts +34 -0
- package/plugins/crypto-auth/index.ts +84 -152
- package/plugins/crypto-auth/package.json +65 -64
- package/plugins/crypto-auth/server/AuthMiddleware.ts +19 -75
- package/plugins/crypto-auth/server/CryptoAuthService.ts +60 -167
- package/plugins/crypto-auth/server/index.ts +15 -2
- package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +65 -0
- package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +26 -0
- package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +76 -0
- package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +45 -0
- package/plugins/crypto-auth/server/middlewares/helpers.ts +140 -0
- package/plugins/crypto-auth/server/middlewares/index.ts +22 -0
- package/plugins/crypto-auth/server/middlewares.ts +19 -0
- package/test-crypto-auth.ts +101 -0
- package/plugins/crypto-auth/client/components/SessionInfo.tsx +0 -242
- package/plugins/crypto-auth/plugin.json +0 -29
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Componente de Informações da Sessão
|
|
3
|
-
* Exibe informações detalhadas sobre a sessão atual
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import React, { useState } from 'react'
|
|
7
|
-
import { useAuth } from './AuthProvider'
|
|
8
|
-
|
|
9
|
-
export interface SessionInfoProps {
|
|
10
|
-
className?: string
|
|
11
|
-
showPrivateKey?: boolean
|
|
12
|
-
showFullSessionId?: boolean
|
|
13
|
-
compact?: boolean
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const SessionInfo: React.FC<SessionInfoProps> = ({
|
|
17
|
-
className = '',
|
|
18
|
-
showPrivateKey = false,
|
|
19
|
-
showFullSessionId = false,
|
|
20
|
-
compact = false
|
|
21
|
-
}) => {
|
|
22
|
-
const { session, isAuthenticated, isAdmin, permissions, isLoading } = useAuth()
|
|
23
|
-
const [showDetails, setShowDetails] = useState(!compact)
|
|
24
|
-
|
|
25
|
-
if (isLoading) {
|
|
26
|
-
return (
|
|
27
|
-
<div className={`animate-pulse ${className}`}>
|
|
28
|
-
<div className="h-4 bg-gray-200 rounded w-3/4 mb-2"></div>
|
|
29
|
-
<div className="h-4 bg-gray-200 rounded w-1/2"></div>
|
|
30
|
-
</div>
|
|
31
|
-
)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (!isAuthenticated || !session) {
|
|
35
|
-
return (
|
|
36
|
-
<div className={`text-gray-500 ${className}`}>
|
|
37
|
-
<p>Não autenticado</p>
|
|
38
|
-
</div>
|
|
39
|
-
)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const formatDate = (date: Date) => {
|
|
43
|
-
return new Intl.DateTimeFormat('pt-BR', {
|
|
44
|
-
dateStyle: 'short',
|
|
45
|
-
timeStyle: 'medium'
|
|
46
|
-
}).format(date)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const truncateId = (id: string, length: number = 8) => {
|
|
50
|
-
return showFullSessionId ? id : `${id.substring(0, length)}...`
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const copyToClipboard = async (text: string) => {
|
|
54
|
-
try {
|
|
55
|
-
await navigator.clipboard.writeText(text)
|
|
56
|
-
// Você pode adicionar um toast/notification aqui
|
|
57
|
-
} catch (err) {
|
|
58
|
-
console.error('Erro ao copiar para clipboard:', err)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (compact) {
|
|
63
|
-
return (
|
|
64
|
-
<div className={`flex items-center gap-2 ${className}`}>
|
|
65
|
-
<div className="flex items-center gap-2">
|
|
66
|
-
<div className="w-2 h-2 bg-green-500 rounded-full"></div>
|
|
67
|
-
<span className="text-sm font-medium">
|
|
68
|
-
{truncateId(session.sessionId)}
|
|
69
|
-
</span>
|
|
70
|
-
{isAdmin && (
|
|
71
|
-
<span className="px-2 py-0.5 bg-blue-100 text-blue-800 text-xs rounded-full">
|
|
72
|
-
Admin
|
|
73
|
-
</span>
|
|
74
|
-
)}
|
|
75
|
-
</div>
|
|
76
|
-
<button
|
|
77
|
-
onClick={() => setShowDetails(!showDetails)}
|
|
78
|
-
className="text-gray-400 hover:text-gray-600 transition-colors"
|
|
79
|
-
>
|
|
80
|
-
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
81
|
-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
82
|
-
</svg>
|
|
83
|
-
</button>
|
|
84
|
-
|
|
85
|
-
{showDetails && (
|
|
86
|
-
<div className="absolute z-10 mt-2 p-4 bg-white border border-gray-200 rounded-lg shadow-lg min-w-80">
|
|
87
|
-
<SessionDetails
|
|
88
|
-
session={session}
|
|
89
|
-
isAdmin={isAdmin}
|
|
90
|
-
permissions={permissions}
|
|
91
|
-
showPrivateKey={showPrivateKey}
|
|
92
|
-
showFullSessionId={showFullSessionId}
|
|
93
|
-
onCopy={copyToClipboard}
|
|
94
|
-
/>
|
|
95
|
-
</div>
|
|
96
|
-
)}
|
|
97
|
-
</div>
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return (
|
|
102
|
-
<div className={`bg-white border border-gray-200 rounded-lg p-4 ${className}`}>
|
|
103
|
-
<SessionDetails
|
|
104
|
-
session={session}
|
|
105
|
-
isAdmin={isAdmin}
|
|
106
|
-
permissions={permissions}
|
|
107
|
-
showPrivateKey={showPrivateKey}
|
|
108
|
-
showFullSessionId={showFullSessionId}
|
|
109
|
-
onCopy={copyToClipboard}
|
|
110
|
-
/>
|
|
111
|
-
</div>
|
|
112
|
-
)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
interface SessionDetailsProps {
|
|
116
|
-
session: any
|
|
117
|
-
isAdmin: boolean
|
|
118
|
-
permissions: string[]
|
|
119
|
-
showPrivateKey: boolean
|
|
120
|
-
showFullSessionId: boolean
|
|
121
|
-
onCopy: (text: string) => void
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const SessionDetails: React.FC<SessionDetailsProps> = ({
|
|
125
|
-
session,
|
|
126
|
-
isAdmin,
|
|
127
|
-
permissions,
|
|
128
|
-
showPrivateKey,
|
|
129
|
-
showFullSessionId,
|
|
130
|
-
onCopy
|
|
131
|
-
}) => {
|
|
132
|
-
const formatDate = (date: Date) => {
|
|
133
|
-
return new Intl.DateTimeFormat('pt-BR', {
|
|
134
|
-
dateStyle: 'short',
|
|
135
|
-
timeStyle: 'medium'
|
|
136
|
-
}).format(date)
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const CopyButton: React.FC<{ text: string }> = ({ text }) => (
|
|
140
|
-
<button
|
|
141
|
-
onClick={() => onCopy(text)}
|
|
142
|
-
className="ml-2 text-gray-400 hover:text-gray-600 transition-colors"
|
|
143
|
-
title="Copiar"
|
|
144
|
-
>
|
|
145
|
-
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
146
|
-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
|
|
147
|
-
</svg>
|
|
148
|
-
</button>
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
return (
|
|
152
|
-
<div className="space-y-3">
|
|
153
|
-
<div className="flex items-center justify-between">
|
|
154
|
-
<h3 className="text-lg font-semibold text-gray-900">Informações da Sessão</h3>
|
|
155
|
-
<div className="flex items-center gap-2">
|
|
156
|
-
<div className="w-2 h-2 bg-green-500 rounded-full"></div>
|
|
157
|
-
<span className="text-sm text-green-600 font-medium">Ativo</span>
|
|
158
|
-
</div>
|
|
159
|
-
</div>
|
|
160
|
-
|
|
161
|
-
<div className="grid grid-cols-1 gap-3 text-sm">
|
|
162
|
-
<div>
|
|
163
|
-
<label className="block text-gray-600 font-medium mb-1">Session ID</label>
|
|
164
|
-
<div className="flex items-center">
|
|
165
|
-
<code className="bg-gray-100 px-2 py-1 rounded text-xs font-mono break-all">
|
|
166
|
-
{showFullSessionId ? session.sessionId : `${session.sessionId.substring(0, 16)}...`}
|
|
167
|
-
</code>
|
|
168
|
-
<CopyButton text={session.sessionId} />
|
|
169
|
-
</div>
|
|
170
|
-
</div>
|
|
171
|
-
|
|
172
|
-
<div>
|
|
173
|
-
<label className="block text-gray-600 font-medium mb-1">Chave Pública</label>
|
|
174
|
-
<div className="flex items-center">
|
|
175
|
-
<code className="bg-gray-100 px-2 py-1 rounded text-xs font-mono break-all">
|
|
176
|
-
{showFullSessionId ? session.publicKey : `${session.publicKey.substring(0, 16)}...`}
|
|
177
|
-
</code>
|
|
178
|
-
<CopyButton text={session.publicKey} />
|
|
179
|
-
</div>
|
|
180
|
-
</div>
|
|
181
|
-
|
|
182
|
-
{showPrivateKey && (
|
|
183
|
-
<div>
|
|
184
|
-
<label className="block text-red-600 font-medium mb-1">
|
|
185
|
-
Chave Privada
|
|
186
|
-
<span className="text-xs text-red-500 ml-1">(Confidencial)</span>
|
|
187
|
-
</label>
|
|
188
|
-
<div className="flex items-center">
|
|
189
|
-
<code className="bg-red-50 border border-red-200 px-2 py-1 rounded text-xs font-mono break-all">
|
|
190
|
-
{session.privateKey.substring(0, 16)}...
|
|
191
|
-
</code>
|
|
192
|
-
<CopyButton text={session.privateKey} />
|
|
193
|
-
</div>
|
|
194
|
-
</div>
|
|
195
|
-
)}
|
|
196
|
-
|
|
197
|
-
<div className="flex gap-4">
|
|
198
|
-
<div>
|
|
199
|
-
<label className="block text-gray-600 font-medium mb-1">Status</label>
|
|
200
|
-
<div className="flex items-center gap-2">
|
|
201
|
-
<span className={`px-2 py-1 rounded-full text-xs font-medium ${
|
|
202
|
-
isAdmin
|
|
203
|
-
? 'bg-blue-100 text-blue-800'
|
|
204
|
-
: 'bg-green-100 text-green-800'
|
|
205
|
-
}`}>
|
|
206
|
-
{isAdmin ? 'Administrador' : 'Usuário'}
|
|
207
|
-
</span>
|
|
208
|
-
</div>
|
|
209
|
-
</div>
|
|
210
|
-
|
|
211
|
-
<div>
|
|
212
|
-
<label className="block text-gray-600 font-medium mb-1">Permissões</label>
|
|
213
|
-
<div className="flex flex-wrap gap-1">
|
|
214
|
-
{permissions.map((permission) => (
|
|
215
|
-
<span
|
|
216
|
-
key={permission}
|
|
217
|
-
className="px-2 py-0.5 bg-gray-100 text-gray-700 text-xs rounded-full"
|
|
218
|
-
>
|
|
219
|
-
{permission}
|
|
220
|
-
</span>
|
|
221
|
-
))}
|
|
222
|
-
</div>
|
|
223
|
-
</div>
|
|
224
|
-
</div>
|
|
225
|
-
|
|
226
|
-
<div className="flex gap-4">
|
|
227
|
-
<div>
|
|
228
|
-
<label className="block text-gray-600 font-medium mb-1">Criado em</label>
|
|
229
|
-
<span className="text-gray-800">{formatDate(session.createdAt)}</span>
|
|
230
|
-
</div>
|
|
231
|
-
|
|
232
|
-
<div>
|
|
233
|
-
<label className="block text-gray-600 font-medium mb-1">Último uso</label>
|
|
234
|
-
<span className="text-gray-800">{formatDate(session.lastUsed)}</span>
|
|
235
|
-
</div>
|
|
236
|
-
</div>
|
|
237
|
-
</div>
|
|
238
|
-
</div>
|
|
239
|
-
)
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
export default SessionInfo
|
|
@@ -1,29 +0,0 @@
|
|
|
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
|
-
}
|