mirror of
https://github.com/bknd-io/bknd/
synced 2026-08-04 09:06:01 +00:00
added cookie option partitioned, as well as cors origin to be array, option to enable credentials (#214)
* added cookie option `partitioned`, as well as cors `origin` to be array, option to enable `credentials` * fix server test * fix data api (updated jsonv-ts)
This commit is contained in:
@@ -4,7 +4,7 @@ import { runtimeSupports, truncate, $console } from "core/utils";
|
||||
import type { Context, Hono } from "hono";
|
||||
import { deleteCookie, getSignedCookie, setSignedCookie } from "hono/cookie";
|
||||
import { sign, verify } from "hono/jwt";
|
||||
import type { CookieOptions } from "hono/utils/cookie";
|
||||
import { type CookieOptions, serializeSigned } from "hono/utils/cookie";
|
||||
import type { ServerEnv } from "modules/Controller";
|
||||
import { pick } from "lodash-es";
|
||||
import { InvalidConditionsException } from "auth/errors";
|
||||
@@ -58,6 +58,7 @@ export const cookieConfig = s
|
||||
secure: s.boolean({ default: true }),
|
||||
httpOnly: s.boolean({ default: true }),
|
||||
expires: s.number({ default: defaultCookieExpires }), // seconds
|
||||
partitioned: s.boolean({ default: false }),
|
||||
renew: s.boolean({ default: true }),
|
||||
pathSuccess: s.string({ default: "/" }),
|
||||
pathLoggedOut: s.string({ default: "/" }),
|
||||
@@ -334,6 +335,11 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
|
||||
await setSignedCookie(c, "auth", token, secret, this.cookieOptions);
|
||||
}
|
||||
|
||||
async unsafeGetAuthCookie(token: string): Promise<string | undefined> {
|
||||
// this works for as long as cookieOptions.prefix is not set
|
||||
return serializeSigned("auth", token, this.config.jwt.secret, this.cookieOptions);
|
||||
}
|
||||
|
||||
private deleteAuthCookie(c: Context) {
|
||||
$console.debug("deleting auth cookie");
|
||||
deleteCookie(c, "auth", this.cookieOptions);
|
||||
|
||||
@@ -42,6 +42,7 @@ export type ParseOptions = {
|
||||
withDefaults?: boolean;
|
||||
withExtendedDefaults?: boolean;
|
||||
coerce?: boolean;
|
||||
coerceDropUnknown?: boolean;
|
||||
clone?: boolean;
|
||||
skipMark?: boolean; // @todo: do something with this
|
||||
forceParse?: boolean; // @todo: do something with this
|
||||
@@ -59,7 +60,10 @@ export function parse<S extends s.Schema, Options extends ParseOptions = ParseOp
|
||||
opts?: Options,
|
||||
): Options extends { coerce: true } ? s.StaticCoerced<S> : s.Static<S> {
|
||||
const schema = (opts?.clone ? cloneSchema(_schema as any) : _schema) as s.Schema;
|
||||
let value = opts?.coerce !== false ? schema.coerce(v) : v;
|
||||
let value =
|
||||
opts?.coerce !== false
|
||||
? schema.coerce(v, { dropUnknown: opts?.coerceDropUnknown ?? false })
|
||||
: v;
|
||||
if (opts?.withDefaults !== false) {
|
||||
value = schema.template(value, {
|
||||
withOptional: true,
|
||||
|
||||
@@ -206,7 +206,7 @@ export class DataController extends Controller {
|
||||
|
||||
const entitiesEnum = this.getEntitiesEnum(this.em);
|
||||
// @todo: make dynamic based on entity
|
||||
const idType = s.anyOf([s.number(), s.string()], { coerce: (v) => v as any });
|
||||
const idType = s.anyOf([s.number(), s.string()], { coerce: (v) => v as number | string });
|
||||
|
||||
/**
|
||||
* Function endpoints
|
||||
@@ -387,7 +387,7 @@ export class DataController extends Controller {
|
||||
if (!this.entityExists(entity)) {
|
||||
return this.notFound(c);
|
||||
}
|
||||
const options = (await c.req.json()) as RepoQuery;
|
||||
const options = c.req.valid("json") as RepoQuery;
|
||||
const result = await this.em.repository(entity).findMany(options);
|
||||
|
||||
return c.json(result, { status: result.data ? 200 : 404 });
|
||||
@@ -397,7 +397,7 @@ export class DataController extends Controller {
|
||||
/**
|
||||
* Mutation endpoints
|
||||
*/
|
||||
// insert one
|
||||
// insert one or many
|
||||
hono.post(
|
||||
"/:entity",
|
||||
describeRoute({
|
||||
|
||||
@@ -64,7 +64,7 @@ export class Controller {
|
||||
return c.notFound();
|
||||
}
|
||||
|
||||
protected getEntitiesEnum(em: EntityManager<any>) {
|
||||
protected getEntitiesEnum(em: EntityManager<any>): s.StringSchema {
|
||||
const entities = em.entities.map((e) => e.name);
|
||||
// @todo: current workaround to allow strings (sometimes building is not fast enough to get the entities)
|
||||
return entities.length > 0 ? s.anyOf([s.string({ enum: entities }), s.string()]) : s.string();
|
||||
|
||||
@@ -17,6 +17,7 @@ export const serverConfigSchema = s.strictObject({
|
||||
allow_headers: s.array(s.string(), {
|
||||
default: ["Content-Type", "Content-Length", "Authorization", "Accept"],
|
||||
}),
|
||||
allow_credentials: s.boolean({ default: true }),
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -36,12 +37,14 @@ export class AppServer extends Module<AppServerConfig> {
|
||||
}
|
||||
|
||||
override async build() {
|
||||
const origin = this.config.cors.origin ?? "";
|
||||
this.client.use(
|
||||
"*",
|
||||
cors({
|
||||
origin: this.config.cors.origin,
|
||||
origin: origin.includes(",") ? origin.split(",").map((o) => o.trim()) : origin,
|
||||
allowMethods: this.config.cors.allow_methods,
|
||||
allowHeaders: this.config.cors.allow_headers,
|
||||
credentials: this.config.cors.allow_credentials,
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -323,6 +323,7 @@ export class SystemController extends Controller {
|
||||
local: datetimeStringLocal(),
|
||||
utc: datetimeStringUTC(),
|
||||
},
|
||||
origin: new URL(c.req.raw.url).origin,
|
||||
plugins: Array.from(this.app.plugins.keys()),
|
||||
walk: {
|
||||
auth: [
|
||||
|
||||
Reference in New Issue
Block a user