hapta 1.0.1 → 1.0.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/helpers/HTTP/Request/Context.ts +3 -2
- package/index.ts +42 -15
- package/package.json +1 -1
|
@@ -80,7 +80,7 @@ type TokenOptions = {
|
|
|
80
80
|
iat: number
|
|
81
81
|
}
|
|
82
82
|
type VerifyFn = (token: string) => Promise<Principal>;
|
|
83
|
-
|
|
83
|
+
type TempTokenFn = (amount_of_uses: number, expiresAt: '1h' | '1d' | '1y'|'') => Promise<string | null>
|
|
84
84
|
export type ServiceConfigs = {
|
|
85
85
|
Clover: {
|
|
86
86
|
Tenant_ID: string;
|
|
@@ -88,7 +88,8 @@ export type ServiceConfigs = {
|
|
|
88
88
|
Authorized_Users: string[];
|
|
89
89
|
Authenticate: AuthenticateFn;
|
|
90
90
|
Register: RegisterFn;
|
|
91
|
-
Verify?: VerifyFn;
|
|
91
|
+
Verify?: VerifyFn;
|
|
92
|
+
createTemporaryToken: TempTokenFn // just verify token
|
|
92
93
|
};
|
|
93
94
|
};
|
|
94
95
|
|
package/index.ts
CHANGED
|
@@ -13,7 +13,7 @@ import * as z from "zod";
|
|
|
13
13
|
import { watch } from "fs";
|
|
14
14
|
import fs from "fs"
|
|
15
15
|
import { pathToFileURL } from "url";
|
|
16
|
-
|
|
16
|
+
const token_uses = new Map<string, number>()
|
|
17
17
|
// --- Global server and router instances ---
|
|
18
18
|
let server: Server;
|
|
19
19
|
// MODIFIED: Make the router a single, persistent instance
|
|
@@ -103,7 +103,8 @@ async function createServeConfig(): Promise<Serve> {
|
|
|
103
103
|
|
|
104
104
|
return {
|
|
105
105
|
port: config.port,
|
|
106
|
-
async fetch(req: Request) {
|
|
106
|
+
async fetch(req: Request) {
|
|
107
|
+
console.log(req.method)
|
|
107
108
|
if (req.method === "OPTIONS") {
|
|
108
109
|
console.log("ran")
|
|
109
110
|
return new Response(null, {
|
|
@@ -115,7 +116,8 @@ async function createServeConfig(): Promise<Serve> {
|
|
|
115
116
|
"Access-Control-Max-Age": "86400",
|
|
116
117
|
},
|
|
117
118
|
});
|
|
118
|
-
}
|
|
119
|
+
}
|
|
120
|
+
console.log("ran")
|
|
119
121
|
const url = new URL(req.url);
|
|
120
122
|
const routeMatch = router.match(url.href);
|
|
121
123
|
|
|
@@ -218,17 +220,18 @@ async function buildRequestContext(req: Request, headers: Headers) {
|
|
|
218
220
|
const reqJSON = await req.json().catch(() => ({}));
|
|
219
221
|
|
|
220
222
|
const hasToken = headers.has("Authorization")
|
|
221
|
-
var isAuthenticated = false;
|
|
223
|
+
var isAuthenticated = false;
|
|
222
224
|
if (hasToken) {
|
|
225
|
+
|
|
223
226
|
try {
|
|
224
|
-
|
|
227
|
+
|
|
225
228
|
isAuthenticated = true
|
|
226
229
|
} catch (error) {
|
|
227
230
|
isAuthenticated = false
|
|
228
231
|
}
|
|
229
232
|
}
|
|
230
|
-
const context
|
|
231
|
-
principal: { isAuthenticated },
|
|
233
|
+
const context = {
|
|
234
|
+
principal: { isAuthenticated: isAuthenticated as boolean },
|
|
232
235
|
services: {
|
|
233
236
|
Clover: {
|
|
234
237
|
Tenant_ID: primaryTenantData.id,
|
|
@@ -274,7 +277,7 @@ async function buildRequestContext(req: Request, headers: Headers) {
|
|
|
274
277
|
}
|
|
275
278
|
|
|
276
279
|
|
|
277
|
-
const authRes = await fetch(`${config.Clover_Server_Url}
|
|
280
|
+
const authRes = await fetch(`${config.Clover_Server_Url}/${options.type === "oauth" ? 'oauth/token' :'auth'}`, {
|
|
278
281
|
method: "POST",
|
|
279
282
|
headers: {
|
|
280
283
|
"Content-Type": "application/json",
|
|
@@ -285,7 +288,7 @@ async function buildRequestContext(req: Request, headers: Headers) {
|
|
|
285
288
|
body: JSON.stringify(fetchBody),
|
|
286
289
|
});
|
|
287
290
|
|
|
288
|
-
if (!authRes.ok) {
|
|
291
|
+
if (!authRes.ok) {
|
|
289
292
|
return {
|
|
290
293
|
isAuthenticated: false,
|
|
291
294
|
error: true,
|
|
@@ -314,18 +317,29 @@ async function buildRequestContext(req: Request, headers: Headers) {
|
|
|
314
317
|
Verify: async (token) => {
|
|
315
318
|
try {
|
|
316
319
|
const payload = jwt.verify(token, config.JWT_SECRET);
|
|
320
|
+
if(token_uses.has(token) && token_uses.get(token) >= payload.amount_of_uses){
|
|
321
|
+
// this is basic auth token
|
|
322
|
+
throw new Error("token has been used wayy to many times, it is expired")
|
|
323
|
+
}else{
|
|
324
|
+
token_uses.set(token, Number(token_uses.get(token)) + 1)
|
|
325
|
+
}
|
|
317
326
|
return {
|
|
318
|
-
isAuthenticated: true,
|
|
319
|
-
id: payload.id,
|
|
320
|
-
clover_group_assigned_To: payload.Group,
|
|
321
|
-
clover_assigned_id: payload.clover_assigned_id,
|
|
322
|
-
Roles: payload.Roles,
|
|
327
|
+
isAuthenticated: true,
|
|
328
|
+
id: payload.id || crypto.randomUUID(),
|
|
329
|
+
clover_group_assigned_To: payload.Group || [],
|
|
330
|
+
clover_assigned_id: payload.clover_assigned_id || primaryTenantData.id,
|
|
331
|
+
Roles: payload.Roles || [],
|
|
323
332
|
token,
|
|
324
333
|
};
|
|
325
334
|
} catch {
|
|
326
335
|
return { isAuthenticated: false };
|
|
327
336
|
}
|
|
328
337
|
},
|
|
338
|
+
createTemporaryToken(amount_of_uses: number, expiresAt: string) {
|
|
339
|
+
const token = jwt.sign({amount_of_uses, isBasicAuth: true, security_level: 0}, config.JWT_SECRET, { expiresIn: expiresAt })
|
|
340
|
+
token_uses.set(token, 0)
|
|
341
|
+
return token
|
|
342
|
+
},
|
|
329
343
|
Roles: Array.isArray(primaryTenantData.Tenant_Roles)
|
|
330
344
|
? primaryTenantData.Tenant_Roles
|
|
331
345
|
: [primaryTenantData.Tenant_Roles],
|
|
@@ -362,13 +376,26 @@ async function buildRequestContext(req: Request, headers: Headers) {
|
|
|
362
376
|
"Access-Control-Allow-Headers": "Content-Type, Authorization"
|
|
363
377
|
}
|
|
364
378
|
})
|
|
379
|
+
},
|
|
380
|
+
text: (value: string, status?:number, statusText?: string) => {
|
|
381
|
+
return new Response(value, {
|
|
382
|
+
...(status && {status}),
|
|
383
|
+
...(statusText && {statusText}),
|
|
384
|
+
headers:{
|
|
385
|
+
"Content-Type": "text/html",
|
|
386
|
+
"Access-Control-Allow-Origin": config.origin,
|
|
387
|
+
"Access-Control-Allow-Methods": "GET,PATCH,PUT,DELETE",
|
|
388
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization"
|
|
389
|
+
}
|
|
390
|
+
})
|
|
365
391
|
}
|
|
366
392
|
};
|
|
367
393
|
|
|
368
394
|
const authHeader = headers.get("authorization");
|
|
369
395
|
const token = authHeader?.startsWith("Bearer ") ? authHeader.split(" ")[1] : authHeader;
|
|
396
|
+
|
|
370
397
|
|
|
371
|
-
if (token) {
|
|
398
|
+
if (token) {
|
|
372
399
|
context.principal = await context.services.Clover.Verify(token);
|
|
373
400
|
}
|
|
374
401
|
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"bin": {
|
|
4
4
|
"hapta":"./index.ts"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.2",
|
|
7
7
|
"description": "modular, scalable, and feature-rich backend framework designed to extend Pocketbase with authentication, schema validation, caching, and tenant-based service orchestration.",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"jsonwebtoken": "^9.0.2",
|