hightjs 0.1.1 → 0.2.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/README.md +147 -9
- package/dist/api/http.js +5 -3
- package/dist/auth/client.d.ts +11 -1
- package/dist/auth/client.js +78 -0
- package/dist/auth/core.d.ts +21 -4
- package/dist/auth/core.js +66 -17
- package/dist/auth/example.d.ts +40 -0
- package/dist/auth/example.js +104 -0
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.js +2 -1
- package/dist/auth/providers/credentials.d.ts +68 -0
- package/dist/auth/providers/credentials.js +132 -0
- package/dist/auth/providers/discord.d.ts +67 -0
- package/dist/auth/providers/discord.js +198 -0
- package/dist/auth/providers/index.d.ts +2 -0
- package/dist/auth/providers/index.js +19 -0
- package/dist/auth/providers.d.ts +2 -5
- package/dist/auth/providers.js +6 -12
- package/dist/auth/react.js +20 -13
- package/dist/auth/routes.d.ts +2 -2
- package/dist/auth/routes.js +45 -13
- package/dist/auth/types.d.ts +36 -21
- package/dist/router.js +9 -1
- package/package.json +1 -1
- package/src/api/http.ts +6 -2
- package/src/auth/client.ts +84 -3
- package/src/auth/core.ts +75 -19
- package/src/auth/example.ts +115 -0
- package/src/auth/index.ts +2 -1
- package/src/auth/providers/credentials.ts +158 -0
- package/src/auth/providers/discord.ts +231 -0
- package/src/auth/providers/index.ts +4 -0
- package/src/auth/providers.ts +3 -12
- package/src/auth/react.tsx +21 -13
- package/src/auth/routes.ts +51 -18
- package/src/auth/types.ts +49 -26
- package/src/router.ts +9 -1
package/README.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
> Um framework web full‑stack moderno para Node.js, focado em simplicidade, DX e velocidade. Bundler via esbuild, hot reload, roteamento automático, APIs, autenticação JWT, CLI e muito mais.
|
|
4
4
|
|
|
5
|
+
<br>
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/HIGHTJS)
|
|
8
|
+
|
|
9
|
+
# Precisa de ajuda?
|
|
10
|
+
Caso tenha alguma dúvida, entre em contato por uma das redes abaixo:
|
|
11
|
+
|
|
12
|
+
[](https://discord.com/users/1264710048786026588)
|
|
13
|
+
[](mailto:murillofrazaocunha@gmail.com)
|
|
14
|
+
[](https://instagram.com/itsmuh_)
|
|
15
|
+
[](https://github.com/murillo-frazao-cunha)
|
|
16
|
+
|
|
5
17
|
---
|
|
6
18
|
|
|
7
19
|
## 📑 Índice
|
|
@@ -118,7 +130,7 @@ src/
|
|
|
118
130
|
routes/
|
|
119
131
|
index.tsx // Página inicial "/"
|
|
120
132
|
about.tsx // Página "/about"
|
|
121
|
-
blog
|
|
133
|
+
blog.tsx // Rota dinâmica "/blog/123"
|
|
122
134
|
backend/
|
|
123
135
|
routes/
|
|
124
136
|
middleware.ts // Middlewares globais da pasta
|
|
@@ -152,8 +164,6 @@ export default config;
|
|
|
152
164
|
|
|
153
165
|
### Rotas Dinâmicas com Parâmetros
|
|
154
166
|
|
|
155
|
-
Use colchetes: `blog/[slug].tsx` → `/blog/post`.
|
|
156
|
-
|
|
157
167
|
```tsx
|
|
158
168
|
import {RouteConfig} from "hightjs/client";
|
|
159
169
|
import React from "react";
|
|
@@ -332,7 +342,7 @@ O jeito recomendado é criar as rotas diretamente no `auth.ts` e importar onde q
|
|
|
332
342
|
`src/auth.ts`:
|
|
333
343
|
|
|
334
344
|
```ts
|
|
335
|
-
import { CredentialsProvider, createAuthRoutes } from 'hightjs/auth';
|
|
345
|
+
import { CredentialsProvider, DiscordProvider, createAuthRoutes } from 'hightjs/auth';
|
|
336
346
|
import type { AuthConfig } from 'hightjs/auth';
|
|
337
347
|
|
|
338
348
|
export const authConfig: AuthConfig = {
|
|
@@ -357,6 +367,13 @@ export const authConfig: AuthConfig = {
|
|
|
357
367
|
return null;
|
|
358
368
|
}
|
|
359
369
|
}),
|
|
370
|
+
new DiscordProvider({
|
|
371
|
+
clientId: "ID",
|
|
372
|
+
clientSecret: "TOKEN",
|
|
373
|
+
callbackUrl: "http://localhost:3000/api/auth/callback/discord",
|
|
374
|
+
scope: ['identify', 'email', 'guilds'],
|
|
375
|
+
successUrl: "http://localhost:3000/"
|
|
376
|
+
})
|
|
360
377
|
],
|
|
361
378
|
session: {
|
|
362
379
|
strategy: 'jwt',
|
|
@@ -382,6 +399,125 @@ import { authRoutes } from "../../../auth";
|
|
|
382
399
|
export default authRoutes;
|
|
383
400
|
```
|
|
384
401
|
|
|
402
|
+
### Configurando o Frontend
|
|
403
|
+
|
|
404
|
+
Para usar autenticação no frontend, você precisa configurar o `SessionProvider` no layout:
|
|
405
|
+
|
|
406
|
+
`src/web/layout.tsx`:
|
|
407
|
+
|
|
408
|
+
```tsx
|
|
409
|
+
import { SessionProvider } from 'hightjs/auth/react';
|
|
410
|
+
|
|
411
|
+
export const metadata = { title: 'Meu App', description: 'Descrição global' };
|
|
412
|
+
|
|
413
|
+
export default function Layout({ children }: { children: React.ReactNode }) {
|
|
414
|
+
return (
|
|
415
|
+
<SessionProvider>
|
|
416
|
+
{children}
|
|
417
|
+
</SessionProvider>
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### Fazendo Login no Frontend
|
|
423
|
+
|
|
424
|
+
Exemplo de como implementar login com credenciais e Discord:
|
|
425
|
+
|
|
426
|
+
```tsx
|
|
427
|
+
import { useSession } from 'hightjs/auth/react';
|
|
428
|
+
import React, { useState } from 'react';
|
|
429
|
+
|
|
430
|
+
function LoginPage() {
|
|
431
|
+
const { signIn } = useSession();
|
|
432
|
+
const [username, setUsername] = useState('');
|
|
433
|
+
const [password, setPassword] = useState('');
|
|
434
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
435
|
+
const [error, setError] = useState<string | null>(null);
|
|
436
|
+
|
|
437
|
+
const handleDiscordLogin = async () => {
|
|
438
|
+
const result = await signIn('discord');
|
|
439
|
+
if(result) {
|
|
440
|
+
if (result.url != null) {
|
|
441
|
+
window.location.href = result.url
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const handleLogin = async (e: React.FormEvent) => {
|
|
447
|
+
e.preventDefault();
|
|
448
|
+
setIsLoading(true);
|
|
449
|
+
setError(null);
|
|
450
|
+
|
|
451
|
+
try {
|
|
452
|
+
const result = await signIn('credentials', {
|
|
453
|
+
redirect: false,
|
|
454
|
+
username: username,
|
|
455
|
+
password: password,
|
|
456
|
+
callbackUrl: '/'
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
if (!result || result.error) {
|
|
460
|
+
setError('Credenciais inválidas. Verifique seus dados e senha.');
|
|
461
|
+
setIsLoading(false);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
} catch (err) {
|
|
466
|
+
setError('Ocorreu um erro inesperado. Tente novamente.');
|
|
467
|
+
setIsLoading(false);
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
return (
|
|
472
|
+
<div>
|
|
473
|
+
<form onSubmit={handleLogin}>
|
|
474
|
+
<input
|
|
475
|
+
type="text"
|
|
476
|
+
value={username}
|
|
477
|
+
onChange={(e) => setUsername(e.target.value)}
|
|
478
|
+
placeholder="Username"
|
|
479
|
+
/>
|
|
480
|
+
<input
|
|
481
|
+
type="password"
|
|
482
|
+
value={password}
|
|
483
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
484
|
+
placeholder="Password"
|
|
485
|
+
/>
|
|
486
|
+
<button type="submit" disabled={isLoading}>Login</button>
|
|
487
|
+
</form>
|
|
488
|
+
|
|
489
|
+
<button onClick={handleDiscordLogin}>Login com Discord</button>
|
|
490
|
+
|
|
491
|
+
{error && <p style={{color: 'red'}}>{error}</p>}
|
|
492
|
+
</div>
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
### Acessando Dados do Usuário
|
|
498
|
+
|
|
499
|
+
Para acessar informações do usuário autenticado:
|
|
500
|
+
|
|
501
|
+
```tsx
|
|
502
|
+
import { useSession } from 'hightjs/auth/react';
|
|
503
|
+
|
|
504
|
+
function UserProfile() {
|
|
505
|
+
const { data: session, status, signOut } = useSession();
|
|
506
|
+
|
|
507
|
+
if (status === 'loading') return <p>Carregando...</p>;
|
|
508
|
+
|
|
509
|
+
if (!session) return <p>Não autenticado</p>;
|
|
510
|
+
|
|
511
|
+
return (
|
|
512
|
+
<div>
|
|
513
|
+
<h1>Bem-vindo, {session.user?.name}</h1>
|
|
514
|
+
<p>Email: {session.user?.email}</p>
|
|
515
|
+
<button onClick={() => signOut()}>Logout</button>
|
|
516
|
+
</div>
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
```
|
|
520
|
+
|
|
385
521
|
### Protegendo rotas backend
|
|
386
522
|
|
|
387
523
|
```ts
|
|
@@ -408,10 +544,11 @@ export default route;
|
|
|
408
544
|
|
|
409
545
|
### Métodos principais
|
|
410
546
|
|
|
411
|
-
- `
|
|
412
|
-
- `
|
|
413
|
-
- `
|
|
414
|
-
- `authRoutes.auth.
|
|
547
|
+
- `signIn()` - Fazer login (credenciais ou provider)
|
|
548
|
+
- `signOut()` - Fazer logout
|
|
549
|
+
- `useSession()` - Hook para acessar sessão no frontend
|
|
550
|
+
- `authRoutes.auth.getSession()` - Verificar sessão no backend
|
|
551
|
+
- `authRoutes.auth.isAuthenticated()` - Verificar se está autenticado
|
|
415
552
|
|
|
416
553
|
---
|
|
417
554
|
|
|
@@ -505,4 +642,5 @@ Copyright 2025 itsmuzin
|
|
|
505
642
|
|
|
506
643
|
Este projeto está licenciado sob a [Licença Apache 2.0](LICENSE).
|
|
507
644
|
|
|
508
|
-
---
|
|
645
|
+
---
|
|
646
|
+
|
package/dist/api/http.js
CHANGED
|
@@ -362,14 +362,16 @@ class HightJSResponse {
|
|
|
362
362
|
res.cookie(name, value, options);
|
|
363
363
|
}
|
|
364
364
|
});
|
|
365
|
+
// Handle redirects specifically
|
|
366
|
+
if (this._headers['Location']) {
|
|
367
|
+
res.redirect(this._headers['Location']);
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
365
370
|
// Envia o corpo se foi definido
|
|
366
371
|
if (this._sent && this._body !== null) {
|
|
367
372
|
if (this._headers['Content-Type']?.includes('application/json')) {
|
|
368
373
|
res.json(JSON.parse(this._body));
|
|
369
374
|
}
|
|
370
|
-
else if (this._headers['Location']) {
|
|
371
|
-
res.redirect(this._headers['Location']);
|
|
372
|
-
}
|
|
373
375
|
else {
|
|
374
376
|
res.send(this._body);
|
|
375
377
|
}
|
package/dist/auth/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Session } from './types';
|
|
1
|
+
import type { SignInOptions, SignInResult, Session } from './types';
|
|
2
2
|
export declare function setBasePath(path: string): void;
|
|
3
3
|
/**
|
|
4
4
|
* Função para obter a sessão atual (similar ao NextAuth getSession)
|
|
@@ -12,3 +12,13 @@ export declare function getCsrfToken(): Promise<string | null>;
|
|
|
12
12
|
* Função para obter providers disponíveis
|
|
13
13
|
*/
|
|
14
14
|
export declare function getProviders(): Promise<any[] | null>;
|
|
15
|
+
/**
|
|
16
|
+
* Função para fazer login (similar ao NextAuth signIn)
|
|
17
|
+
*/
|
|
18
|
+
export declare function signIn(provider?: string, options?: SignInOptions): Promise<SignInResult | undefined>;
|
|
19
|
+
/**
|
|
20
|
+
* Função para fazer logout (similar ao NextAuth signOut)
|
|
21
|
+
*/
|
|
22
|
+
export declare function signOut(options?: {
|
|
23
|
+
callbackUrl?: string;
|
|
24
|
+
}): Promise<void>;
|
package/dist/auth/client.js
CHANGED
|
@@ -4,6 +4,8 @@ exports.setBasePath = setBasePath;
|
|
|
4
4
|
exports.getSession = getSession;
|
|
5
5
|
exports.getCsrfToken = getCsrfToken;
|
|
6
6
|
exports.getProviders = getProviders;
|
|
7
|
+
exports.signIn = signIn;
|
|
8
|
+
exports.signOut = signOut;
|
|
7
9
|
// Configuração global do client
|
|
8
10
|
let basePath = '/api/auth';
|
|
9
11
|
function setBasePath(path) {
|
|
@@ -66,3 +68,79 @@ async function getProviders() {
|
|
|
66
68
|
return null;
|
|
67
69
|
}
|
|
68
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Função para fazer login (similar ao NextAuth signIn)
|
|
73
|
+
*/
|
|
74
|
+
async function signIn(provider = 'credentials', options = {}) {
|
|
75
|
+
try {
|
|
76
|
+
const { redirect = true, callbackUrl, ...credentials } = options;
|
|
77
|
+
const response = await fetch(`${basePath}/signin`, {
|
|
78
|
+
method: 'POST',
|
|
79
|
+
headers: {
|
|
80
|
+
'Content-Type': 'application/json',
|
|
81
|
+
},
|
|
82
|
+
credentials: 'include',
|
|
83
|
+
body: JSON.stringify({
|
|
84
|
+
provider,
|
|
85
|
+
...credentials
|
|
86
|
+
})
|
|
87
|
+
});
|
|
88
|
+
const data = await response.json();
|
|
89
|
+
if (response.ok && data.success) {
|
|
90
|
+
// Se é OAuth, redireciona para URL fornecida
|
|
91
|
+
if (data.type === 'oauth' && data.redirectUrl) {
|
|
92
|
+
if (redirect && typeof window !== 'undefined') {
|
|
93
|
+
window.location.href = data.redirectUrl;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
ok: true,
|
|
97
|
+
status: 200,
|
|
98
|
+
url: data.redirectUrl
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// Se é sessão (credentials), redireciona para callbackUrl
|
|
102
|
+
if (data.type === 'session') {
|
|
103
|
+
if (redirect && typeof window !== 'undefined') {
|
|
104
|
+
window.location.href = callbackUrl || '/';
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
ok: true,
|
|
108
|
+
status: 200,
|
|
109
|
+
url: callbackUrl || '/'
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
return {
|
|
115
|
+
error: data.error || 'Authentication failed',
|
|
116
|
+
status: response.status,
|
|
117
|
+
ok: false
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
console.error('[hweb-auth] Erro no signIn:', error);
|
|
123
|
+
return {
|
|
124
|
+
error: 'Network error',
|
|
125
|
+
status: 500,
|
|
126
|
+
ok: false
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Função para fazer logout (similar ao NextAuth signOut)
|
|
132
|
+
*/
|
|
133
|
+
async function signOut(options = {}) {
|
|
134
|
+
try {
|
|
135
|
+
await fetch(`${basePath}/signout`, {
|
|
136
|
+
method: 'POST',
|
|
137
|
+
credentials: 'include'
|
|
138
|
+
});
|
|
139
|
+
if (typeof window !== 'undefined') {
|
|
140
|
+
window.location.href = options.callbackUrl || '/';
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
console.error('[hweb-auth] Erro no signOut:', error);
|
|
145
|
+
}
|
|
146
|
+
}
|
package/dist/auth/core.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HightJSRequest, HightJSResponse } from '../api/http';
|
|
2
|
-
import type { AuthConfig, Session } from './types';
|
|
2
|
+
import type { AuthConfig, AuthProviderClass, Session } from './types';
|
|
3
3
|
export declare class HWebAuth {
|
|
4
4
|
private config;
|
|
5
5
|
private sessionManager;
|
|
@@ -9,16 +9,18 @@ export declare class HWebAuth {
|
|
|
9
9
|
*/
|
|
10
10
|
private middleware;
|
|
11
11
|
/**
|
|
12
|
-
* Autentica um usuário
|
|
12
|
+
* Autentica um usuário usando um provider específico
|
|
13
13
|
*/
|
|
14
|
-
signIn(
|
|
14
|
+
signIn(providerId: string, credentials: Record<string, string>): Promise<{
|
|
15
15
|
session: Session;
|
|
16
16
|
token: string;
|
|
17
|
+
} | {
|
|
18
|
+
redirectUrl: string;
|
|
17
19
|
} | null>;
|
|
18
20
|
/**
|
|
19
21
|
* Faz logout do usuário
|
|
20
22
|
*/
|
|
21
|
-
signOut(): HightJSResponse
|
|
23
|
+
signOut(req: HightJSRequest): Promise<HightJSResponse>;
|
|
22
24
|
/**
|
|
23
25
|
* Obtém a sessão atual
|
|
24
26
|
*/
|
|
@@ -27,6 +29,21 @@ export declare class HWebAuth {
|
|
|
27
29
|
* Verifica se o usuário está autenticado
|
|
28
30
|
*/
|
|
29
31
|
isAuthenticated(req: HightJSRequest): Promise<boolean>;
|
|
32
|
+
/**
|
|
33
|
+
* Retorna todos os providers disponíveis (dados públicos)
|
|
34
|
+
*/
|
|
35
|
+
getProviders(): any[];
|
|
36
|
+
/**
|
|
37
|
+
* Busca um provider específico
|
|
38
|
+
*/
|
|
39
|
+
getProvider(id: string): AuthProviderClass | null;
|
|
40
|
+
/**
|
|
41
|
+
* Retorna todas as rotas adicionais dos providers
|
|
42
|
+
*/
|
|
43
|
+
getAllAdditionalRoutes(): Array<{
|
|
44
|
+
provider: string;
|
|
45
|
+
route: any;
|
|
46
|
+
}>;
|
|
30
47
|
/**
|
|
31
48
|
* Cria resposta com cookie de autenticação - Secure implementation
|
|
32
49
|
*/
|
package/dist/auth/core.js
CHANGED
|
@@ -27,49 +27,67 @@ class HWebAuth {
|
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
-
* Autentica um usuário
|
|
30
|
+
* Autentica um usuário usando um provider específico
|
|
31
31
|
*/
|
|
32
|
-
async signIn(
|
|
33
|
-
const
|
|
34
|
-
if (!
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
if (!authProvider.authorize) {
|
|
32
|
+
async signIn(providerId, credentials) {
|
|
33
|
+
const provider = this.config.providers.find(p => p.id === providerId);
|
|
34
|
+
if (!provider) {
|
|
35
|
+
console.error(`[hweb-auth] Provider not found: ${providerId}`);
|
|
38
36
|
return null;
|
|
39
37
|
}
|
|
40
38
|
try {
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
// Usa o método handleSignIn do provider
|
|
40
|
+
const result = await provider.handleSignIn(credentials);
|
|
41
|
+
if (!result)
|
|
43
42
|
return null;
|
|
43
|
+
// Se resultado é string, é URL de redirecionamento OAuth
|
|
44
|
+
if (typeof result === 'string') {
|
|
45
|
+
return { redirectUrl: result };
|
|
46
|
+
}
|
|
47
|
+
// Se resultado é User, cria sessão
|
|
48
|
+
const user = result;
|
|
44
49
|
// Callback de signIn se definido
|
|
45
50
|
if (this.config.callbacks?.signIn) {
|
|
46
|
-
const allowed = await this.config.callbacks.signIn(user, { provider }, {});
|
|
51
|
+
const allowed = await this.config.callbacks.signIn(user, { provider: providerId }, {});
|
|
47
52
|
if (!allowed)
|
|
48
53
|
return null;
|
|
49
54
|
}
|
|
50
|
-
const
|
|
55
|
+
const sessionResult = this.sessionManager.createSession(user);
|
|
51
56
|
// Callback de sessão se definido
|
|
52
57
|
if (this.config.callbacks?.session) {
|
|
53
|
-
|
|
58
|
+
sessionResult.session = await this.config.callbacks.session(sessionResult.session, user);
|
|
54
59
|
}
|
|
55
|
-
return
|
|
60
|
+
return sessionResult;
|
|
56
61
|
}
|
|
57
62
|
catch (error) {
|
|
58
|
-
console.error(
|
|
63
|
+
console.error(`[hweb-auth] Erro no signIn com provider ${providerId}:`, error);
|
|
59
64
|
return null;
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
/**
|
|
63
68
|
* Faz logout do usuário
|
|
64
69
|
*/
|
|
65
|
-
signOut() {
|
|
70
|
+
async signOut(req) {
|
|
71
|
+
// Busca a sessão atual para saber qual provider usar
|
|
72
|
+
const { session } = await this.middleware(req);
|
|
73
|
+
if (session?.user?.provider) {
|
|
74
|
+
const provider = this.config.providers.find(p => p.id === session.user.provider);
|
|
75
|
+
if (provider && provider.handleSignOut) {
|
|
76
|
+
try {
|
|
77
|
+
await provider.handleSignOut();
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error(`[hweb-auth] Erro no signOut do provider ${provider.id}:`, error);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
66
84
|
return http_1.HightJSResponse
|
|
67
85
|
.json({ success: true })
|
|
68
86
|
.clearCookie('hweb-auth-token', {
|
|
69
87
|
path: '/',
|
|
70
88
|
httpOnly: true,
|
|
71
|
-
secure: true,
|
|
72
|
-
sameSite: 'strict'
|
|
89
|
+
secure: true,
|
|
90
|
+
sameSite: 'strict'
|
|
73
91
|
});
|
|
74
92
|
}
|
|
75
93
|
/**
|
|
@@ -86,6 +104,37 @@ class HWebAuth {
|
|
|
86
104
|
const session = await this.getSession(req);
|
|
87
105
|
return session !== null;
|
|
88
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Retorna todos os providers disponíveis (dados públicos)
|
|
109
|
+
*/
|
|
110
|
+
getProviders() {
|
|
111
|
+
return this.config.providers.map(provider => ({
|
|
112
|
+
id: provider.id,
|
|
113
|
+
name: provider.name,
|
|
114
|
+
type: provider.type,
|
|
115
|
+
config: provider.getConfig ? provider.getConfig() : {}
|
|
116
|
+
}));
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Busca um provider específico
|
|
120
|
+
*/
|
|
121
|
+
getProvider(id) {
|
|
122
|
+
return this.config.providers.find(p => p.id === id) || null;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Retorna todas as rotas adicionais dos providers
|
|
126
|
+
*/
|
|
127
|
+
getAllAdditionalRoutes() {
|
|
128
|
+
const routes = [];
|
|
129
|
+
for (const provider of this.config.providers) {
|
|
130
|
+
if (provider.additionalRoutes) {
|
|
131
|
+
for (const route of provider.additionalRoutes) {
|
|
132
|
+
routes.push({ provider: provider.id, route });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return routes;
|
|
137
|
+
}
|
|
89
138
|
/**
|
|
90
139
|
* Cria resposta com cookie de autenticação - Secure implementation
|
|
91
140
|
*/
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exemplo de como usar os novos providers baseados em classes
|
|
3
|
+
*/
|
|
4
|
+
export declare const authRoutes: {
|
|
5
|
+
pattern: string;
|
|
6
|
+
GET(req: import("..").HightJSRequest, params: {
|
|
7
|
+
[key: string]: string;
|
|
8
|
+
}): Promise<any>;
|
|
9
|
+
POST(req: import("..").HightJSRequest, params: {
|
|
10
|
+
[key: string]: string;
|
|
11
|
+
}): Promise<any>;
|
|
12
|
+
auth: import("./core").HWebAuth;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Como usar em suas rotas API:
|
|
16
|
+
*
|
|
17
|
+
* // arquivo: /api/auth/[...value].ts
|
|
18
|
+
* import { authRoutes } from '../../../src/auth/example';
|
|
19
|
+
*
|
|
20
|
+
* export const GET = authRoutes.GET;
|
|
21
|
+
* export const POST = authRoutes.POST;
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Rotas disponíveis automaticamente:
|
|
25
|
+
*
|
|
26
|
+
* Core routes:
|
|
27
|
+
* - GET /api/auth/session - Obter sessão atual
|
|
28
|
+
* - GET /api/auth/providers - Listar providers
|
|
29
|
+
* - GET /api/auth/csrf - Obter token CSRF
|
|
30
|
+
* - POST /api/auth/signin - Login
|
|
31
|
+
* - POST /api/auth/signout - Logout
|
|
32
|
+
*
|
|
33
|
+
* Provider específico (CredentialsProvider):
|
|
34
|
+
* - GET /api/auth/credentials/config - Config do provider
|
|
35
|
+
*
|
|
36
|
+
* Provider específico (DiscordProvider):
|
|
37
|
+
* - GET /api/auth/signin/discord - Iniciar OAuth Discord
|
|
38
|
+
* - GET /api/auth/callback/discord - Callback OAuth Discord
|
|
39
|
+
* - GET /api/auth/discord/config - Config do provider Discord
|
|
40
|
+
*/
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Exemplo de como usar os novos providers baseados em classes
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.authRoutes = void 0;
|
|
7
|
+
const routes_1 = require("./routes");
|
|
8
|
+
const providers_1 = require("./providers");
|
|
9
|
+
// Exemplo de configuração com os novos providers
|
|
10
|
+
const authConfig = {
|
|
11
|
+
providers: [
|
|
12
|
+
// Provider de credenciais customizado
|
|
13
|
+
new providers_1.CredentialsProvider({
|
|
14
|
+
name: "Login com Email",
|
|
15
|
+
credentials: {
|
|
16
|
+
email: {
|
|
17
|
+
label: "Email",
|
|
18
|
+
type: "email",
|
|
19
|
+
placeholder: "seu@email.com"
|
|
20
|
+
},
|
|
21
|
+
password: {
|
|
22
|
+
label: "Senha",
|
|
23
|
+
type: "password"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
async authorize(credentials) {
|
|
27
|
+
// Aqui você faz a validação com seu banco de dados
|
|
28
|
+
const { email, password } = credentials;
|
|
29
|
+
// Exemplo de validação (substitua pela sua lógica)
|
|
30
|
+
if (email === "admin@example.com" && password === "123456") {
|
|
31
|
+
return {
|
|
32
|
+
id: "1",
|
|
33
|
+
name: "Admin User",
|
|
34
|
+
email: email,
|
|
35
|
+
role: "admin"
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// Retorna null se credenciais inválidas
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}),
|
|
42
|
+
// Provider do Discord
|
|
43
|
+
new providers_1.DiscordProvider({
|
|
44
|
+
clientId: process.env.DISCORD_CLIENT_ID,
|
|
45
|
+
clientSecret: process.env.DISCORD_CLIENT_SECRET,
|
|
46
|
+
callbackUrl: "http://localhost:3000/api/auth/callback/discord"
|
|
47
|
+
})
|
|
48
|
+
],
|
|
49
|
+
secret: process.env.HWEB_AUTH_SECRET || "seu-super-secret-aqui-32-chars-min",
|
|
50
|
+
session: {
|
|
51
|
+
strategy: 'jwt',
|
|
52
|
+
maxAge: 86400 // 24 horas
|
|
53
|
+
},
|
|
54
|
+
pages: {
|
|
55
|
+
signIn: '/auth/signin',
|
|
56
|
+
signOut: '/auth/signout'
|
|
57
|
+
},
|
|
58
|
+
callbacks: {
|
|
59
|
+
async signIn(user, account, profile) {
|
|
60
|
+
// Lógica customizada antes do login
|
|
61
|
+
console.log(`Usuário ${user.email} fazendo login via ${account.provider}`);
|
|
62
|
+
return true; // permitir login
|
|
63
|
+
},
|
|
64
|
+
async session(session, user) {
|
|
65
|
+
// Adicionar dados customizados à sessão
|
|
66
|
+
return {
|
|
67
|
+
...session,
|
|
68
|
+
user: {
|
|
69
|
+
...session.user,
|
|
70
|
+
customData: "dados extras"
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
// Criar as rotas de autenticação
|
|
77
|
+
exports.authRoutes = (0, routes_1.createAuthRoutes)(authConfig);
|
|
78
|
+
/**
|
|
79
|
+
* Como usar em suas rotas API:
|
|
80
|
+
*
|
|
81
|
+
* // arquivo: /api/auth/[...value].ts
|
|
82
|
+
* import { authRoutes } from '../../../src/auth/example';
|
|
83
|
+
*
|
|
84
|
+
* export const GET = authRoutes.GET;
|
|
85
|
+
* export const POST = authRoutes.POST;
|
|
86
|
+
*/
|
|
87
|
+
/**
|
|
88
|
+
* Rotas disponíveis automaticamente:
|
|
89
|
+
*
|
|
90
|
+
* Core routes:
|
|
91
|
+
* - GET /api/auth/session - Obter sessão atual
|
|
92
|
+
* - GET /api/auth/providers - Listar providers
|
|
93
|
+
* - GET /api/auth/csrf - Obter token CSRF
|
|
94
|
+
* - POST /api/auth/signin - Login
|
|
95
|
+
* - POST /api/auth/signout - Logout
|
|
96
|
+
*
|
|
97
|
+
* Provider específico (CredentialsProvider):
|
|
98
|
+
* - GET /api/auth/credentials/config - Config do provider
|
|
99
|
+
*
|
|
100
|
+
* Provider específico (DiscordProvider):
|
|
101
|
+
* - GET /api/auth/signin/discord - Iniciar OAuth Discord
|
|
102
|
+
* - GET /api/auth/callback/discord - Callback OAuth Discord
|
|
103
|
+
* - GET /api/auth/discord/config - Config do provider Discord
|
|
104
|
+
*/
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -3,5 +3,5 @@ export * from './providers';
|
|
|
3
3
|
export * from './core';
|
|
4
4
|
export * from './routes';
|
|
5
5
|
export * from './jwt';
|
|
6
|
-
export { CredentialsProvider } from './providers';
|
|
6
|
+
export { CredentialsProvider, DiscordProvider } from './providers';
|
|
7
7
|
export { createAuthRoutes } from './routes';
|
package/dist/auth/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.createAuthRoutes = exports.CredentialsProvider = void 0;
|
|
17
|
+
exports.createAuthRoutes = exports.DiscordProvider = exports.CredentialsProvider = void 0;
|
|
18
18
|
// Exportações principais do sistema de autenticação
|
|
19
19
|
__exportStar(require("./types"), exports);
|
|
20
20
|
__exportStar(require("./providers"), exports);
|
|
@@ -23,5 +23,6 @@ __exportStar(require("./routes"), exports);
|
|
|
23
23
|
__exportStar(require("./jwt"), exports);
|
|
24
24
|
var providers_1 = require("./providers");
|
|
25
25
|
Object.defineProperty(exports, "CredentialsProvider", { enumerable: true, get: function () { return providers_1.CredentialsProvider; } });
|
|
26
|
+
Object.defineProperty(exports, "DiscordProvider", { enumerable: true, get: function () { return providers_1.DiscordProvider; } });
|
|
26
27
|
var routes_1 = require("./routes");
|
|
27
28
|
Object.defineProperty(exports, "createAuthRoutes", { enumerable: true, get: function () { return routes_1.createAuthRoutes; } });
|