added format command and added trailing commas to reduce conflicts

This commit is contained in:
dswbx
2025-02-26 20:06:03 +01:00
parent 88b5359f1c
commit 7743f71a11
414 changed files with 3622 additions and 3610 deletions

View File

@@ -7,7 +7,7 @@ import {
Type,
parse,
runtimeSupports,
transformObject
transformObject,
} from "core/utils";
import type { Context, Hono } from "hono";
import { deleteCookie, getSignedCookie, setSignedCookie } from "hono/cookie";
@@ -71,9 +71,9 @@ export const cookieConfig = Type.Partial(
expires: Type.Number({ default: defaultCookieExpires }), // seconds
renew: Type.Boolean({ default: true }),
pathSuccess: Type.String({ default: "/" }),
pathLoggedOut: Type.String({ default: "/" })
pathLoggedOut: Type.String({ default: "/" }),
}),
{ default: {}, additionalProperties: false }
{ default: {}, additionalProperties: false },
);
// @todo: maybe add a config to not allow cookie/api tokens to be used interchangably?
@@ -86,16 +86,16 @@ export const jwtConfig = Type.Object(
alg: Type.Optional(StringEnum(["HS256", "HS384", "HS512"], { default: "HS256" })),
expires: Type.Optional(Type.Number()), // seconds
issuer: Type.Optional(Type.String()),
fields: Type.Array(Type.String(), { default: ["id", "email", "role"] })
fields: Type.Array(Type.String(), { default: ["id", "email", "role"] }),
},
{
default: {},
additionalProperties: false
}
additionalProperties: false,
},
);
export const authenticatorConfig = Type.Object({
jwt: jwtConfig,
cookie: cookieConfig
cookie: cookieConfig,
});
type AuthConfig = Static<typeof authenticatorConfig>;
@@ -104,7 +104,7 @@ export type AuthUserResolver = (
action: AuthAction,
strategy: Strategy,
identifier: string,
profile: ProfileExchange
profile: ProfileExchange,
) => Promise<SafeUser | undefined>;
type AuthClaims = SafeUser & {
iat: number;
@@ -127,7 +127,7 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
action: AuthAction,
strategy: Strategy,
identifier: string,
profile: ProfileExchange
profile: ProfileExchange,
): Promise<AuthResponse> {
//console.log("resolve", { action, strategy: strategy.getName(), profile });
const user = await this.userResolver(action, strategy, identifier, profile);
@@ -135,7 +135,7 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
if (user) {
return {
user,
token: await this.jwt(user)
token: await this.jwt(user),
};
}
@@ -148,7 +148,7 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
strategy<
StrategyName extends keyof Strategies,
Strat extends Strategy = Strategies[StrategyName]
Strat extends Strategy = Strategies[StrategyName],
>(strategy: StrategyName): Strat {
try {
return this.strategies[strategy] as unknown as Strat;
@@ -168,7 +168,7 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
const payload: JWTPayload = {
...user,
iat: Math.floor(Date.now() / 1000)
iat: Math.floor(Date.now() / 1000),
};
// issuer
@@ -194,7 +194,7 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
const payload = await verify(
jwt,
this.config.jwt?.secret ?? "",
this.config.jwt?.alg ?? "HS256"
this.config.jwt?.alg ?? "HS256",
);
// manually verify issuer (hono doesn't support it)
@@ -215,7 +215,7 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
return {
...cookieConfig,
expires: new Date(Date.now() + expires * 1000)
expires: new Date(Date.now() + expires * 1000),
};
}
@@ -342,17 +342,17 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
toJSON(secrets?: boolean) {
return {
...this.config,
jwt: secrets ? this.config.jwt : undefined
jwt: secrets ? this.config.jwt : undefined,
};
}
}
export function createStrategyAction<S extends TObject>(
schema: S,
preprocess: (input: Static<S>) => Promise<Partial<DB["users"]>>
preprocess: (input: Static<S>) => Promise<Partial<DB["users"]>>,
) {
return {
schema,
preprocess
preprocess,
} as StrategyAction<S>;
}

View File

@@ -9,7 +9,7 @@ type LoginSchema = { username: string; password: string } | { email: string; pas
type RegisterSchema = { email: string; password: string; [key: string]: any };
const schema = Type.Object({
hashing: StringEnum(["plain", "sha256" /*, "bcrypt"*/] as const, { default: "sha256" })
hashing: StringEnum(["plain", "sha256" /*, "bcrypt"*/] as const, { default: "sha256" }),
});
export type PasswordStrategyOptions = Static<typeof schema>;
@@ -49,7 +49,7 @@ export class PasswordStrategy implements Strategy {
return {
...input,
password: await this.hash(input.password)
password: await this.hash(input.password),
};
}
@@ -62,8 +62,8 @@ export class PasswordStrategy implements Strategy {
tb(
"query",
Type.Object({
redirect: Type.Optional(Type.String())
})
redirect: Type.Optional(Type.String()),
}),
),
async (c) => {
const body = await authenticator.getBody(c);
@@ -75,22 +75,22 @@ export class PasswordStrategy implements Strategy {
"login",
this,
payload.password,
payload
payload,
);
return await authenticator.respond(c, data, redirect);
} catch (e) {
return await authenticator.respond(c, e);
}
}
},
)
.post(
"/register",
tb(
"query",
Type.Object({
redirect: Type.Optional(Type.String())
})
redirect: Type.Optional(Type.String()),
}),
),
async (c) => {
const body = await authenticator.getBody(c);
@@ -101,11 +101,11 @@ export class PasswordStrategy implements Strategy {
"register",
this,
payload.password,
payload
payload,
);
return await authenticator.respond(c, data, redirect);
}
},
);
}
@@ -114,19 +114,19 @@ export class PasswordStrategy implements Strategy {
create: createStrategyAction(
Type.Object({
email: Type.String({
pattern: "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$"
pattern: "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$",
}),
password: Type.String({
minLength: 8 // @todo: this should be configurable
})
minLength: 8, // @todo: this should be configurable
}),
}),
async ({ password, ...input }) => {
return {
...input,
strategy_value: await this.hash(password)
strategy_value: await this.hash(password),
};
}
)
},
),
};
}

View File

@@ -9,5 +9,5 @@ export {
type PasswordStrategyOptions,
OAuthStrategy,
OAuthCallbackException,
CustomOAuthStrategy
CustomOAuthStrategy,
};

View File

@@ -15,11 +15,11 @@ const oauthSchemaCustom = Type.Object(
{
client_id: Type.String(),
client_secret: Type.String(),
token_endpoint_auth_method: StringEnum(["client_secret_basic"])
token_endpoint_auth_method: StringEnum(["client_secret_basic"]),
},
{
additionalProperties: false
}
additionalProperties: false,
},
),
as: Type.Object(
{
@@ -29,15 +29,15 @@ const oauthSchemaCustom = Type.Object(
scope_separator: Type.Optional(Type.String({ default: " " })),
authorization_endpoint: Type.Optional(UrlString),
token_endpoint: Type.Optional(UrlString),
userinfo_endpoint: Type.Optional(UrlString)
userinfo_endpoint: Type.Optional(UrlString),
},
{
additionalProperties: false
}
)
additionalProperties: false,
},
),
// @todo: profile mapping
},
{ title: "Custom OAuth", additionalProperties: false }
{ title: "Custom OAuth", additionalProperties: false },
);
type OAuthConfigCustom = Static<typeof oauthSchemaCustom>;
@@ -57,7 +57,7 @@ export type IssuerConfig<UserInfo = any> = {
profile: (
info: UserInfo,
config: Omit<IssuerConfig, "profile">,
tokenResponse: any
tokenResponse: any,
) => Promise<UserProfile>;
};

View File

@@ -18,14 +18,14 @@ const schemaProvided = Type.Object(
client: Type.Object(
{
client_id: Type.String(),
client_secret: Type.String()
client_secret: Type.String(),
},
{
additionalProperties: false
}
)
additionalProperties: false,
},
),
},
{ title: "OAuth" }
{ title: "OAuth" },
);
type ProvidedOAuthConfig = Static<typeof schemaProvided>;
@@ -56,7 +56,7 @@ export type IssuerConfig<UserInfo = any> = {
profile: (
info: UserInfo,
config: Omit<IssuerConfig, "profile">,
tokenResponse: any
tokenResponse: any,
) => Promise<UserProfile>;
};
@@ -65,7 +65,7 @@ export class OAuthCallbackException extends Exception {
constructor(
public error: any,
public step: string
public step: string,
) {
super("OAuthCallbackException on " + step);
}
@@ -103,8 +103,8 @@ export class OAuthStrategy implements Strategy {
type: info.type,
client: {
...info.client,
...this._config.client
}
...this._config.client,
},
};
}
@@ -129,7 +129,7 @@ export class OAuthStrategy implements Strategy {
const { challenge_supported, challenge, challenge_method } = await this.getCodeChallenge(
as,
options.state
options.state,
);
if (!as.authorization_endpoint) {
@@ -150,7 +150,7 @@ export class OAuthStrategy implements Strategy {
client_id: client.client_id,
redirect_uri: options.redirect_uri,
response_type: "code",
scope: scopes.join(as.scope_separator ?? " ")
scope: scopes.join(as.scope_separator ?? " "),
};
if (challenge_supported) {
params.code_challenge = challenge;
@@ -162,13 +162,13 @@ export class OAuthStrategy implements Strategy {
return {
url: new URL(endpoint) + "?" + new URLSearchParams(params).toString(),
endpoint,
params
params,
};
}
private async oidc(
callbackParams: URL | URLSearchParams,
options: { redirect_uri: string; state: string; scopes?: string[] }
options: { redirect_uri: string; state: string; scopes?: string[] },
) {
const config = await this.getConfig();
const { client, as, type } = config;
@@ -178,7 +178,7 @@ export class OAuthStrategy implements Strategy {
as,
client, // no client_secret required
callbackParams,
oauth.expectNoState
oauth.expectNoState,
);
if (oauth.isOAuth2Error(parameters)) {
//console.log("callback.error", parameters);
@@ -193,7 +193,7 @@ export class OAuthStrategy implements Strategy {
client,
parameters,
options.redirect_uri,
options.state
options.state,
);
//console.log("callback.response", response);
@@ -213,7 +213,7 @@ export class OAuthStrategy implements Strategy {
as,
client,
response,
expectedNonce
expectedNonce,
);
if (oauth.isOAuth2Error(result)) {
console.log("callback.error", result);
@@ -236,7 +236,7 @@ export class OAuthStrategy implements Strategy {
private async oauth2(
callbackParams: URL | URLSearchParams,
options: { redirect_uri: string; state: string; scopes?: string[] }
options: { redirect_uri: string; state: string; scopes?: string[] },
) {
const config = await this.getConfig();
const { client, type, as, profile } = config;
@@ -246,7 +246,7 @@ export class OAuthStrategy implements Strategy {
as,
client, // no client_secret required
callbackParams,
oauth.expectNoState
oauth.expectNoState,
);
if (oauth.isOAuth2Error(parameters)) {
console.log("callback.error", parameters);
@@ -254,14 +254,14 @@ export class OAuthStrategy implements Strategy {
}
console.log(
"callback.parameters",
JSON.stringify(Object.fromEntries(parameters.entries()), null, 2)
JSON.stringify(Object.fromEntries(parameters.entries()), null, 2),
);
const response = await oauth.authorizationCodeGrantRequest(
as,
client,
parameters,
options.redirect_uri,
options.state
options.state,
);
const challenges = oauth.parseWwwAuthenticateChallenges(response);
@@ -297,7 +297,7 @@ export class OAuthStrategy implements Strategy {
async callback(
callbackParams: URL | URLSearchParams,
options: { redirect_uri: string; state: string; scopes?: string[] }
options: { redirect_uri: string; state: string; scopes?: string[] },
): Promise<UserProfile> {
const type = this.getIssuerConfig().type;
@@ -330,7 +330,7 @@ export class OAuthStrategy implements Strategy {
secure: true,
httpOnly: true,
sameSite: "Lax",
maxAge: 60 * 5 // 5 minutes
maxAge: 60 * 5, // 5 minutes
});
};
@@ -339,7 +339,7 @@ export class OAuthStrategy implements Strategy {
return {
state: c.req.header("X-State-Challenge"),
action: c.req.header("X-State-Action"),
mode: "token"
mode: "token",
} as any;
}
@@ -366,7 +366,7 @@ export class OAuthStrategy implements Strategy {
const profile = await this.callback(params, {
redirect_uri,
state: state.state
state: state.state,
});
try {
@@ -392,7 +392,7 @@ export class OAuthStrategy implements Strategy {
const params = new URLSearchParams(url.search);
return c.json({
code: params.get("code") ?? null
code: params.get("code") ?? null,
});
});
@@ -410,7 +410,7 @@ export class OAuthStrategy implements Strategy {
const state = oauth.generateRandomCodeVerifier();
const response = await this.request({
redirect_uri,
state
state,
});
//console.log("_state", state);
@@ -433,7 +433,7 @@ export class OAuthStrategy implements Strategy {
const state = oauth.generateRandomCodeVerifier();
const response = await this.request({
redirect_uri,
state
state,
});
if (isDebug()) {
@@ -442,14 +442,14 @@ export class OAuthStrategy implements Strategy {
redirect_uri,
challenge: state,
action,
params: response.params
params: response.params,
});
}
return c.json({
url: response.url,
challenge: state,
action
action,
});
});
@@ -477,7 +477,7 @@ export class OAuthStrategy implements Strategy {
return {
type: this.getIssuerConfig().type,
...config
...config,
};
}
}