refactor(api): ♻️ Rewrite full authentication code to go OpenID-only

This commit is contained in:
Jesse Wierzbinski 2025-08-21 00:45:58 +02:00
parent 4eae4cd062
commit 1bfc5fb013
No known key found for this signature in database
39 changed files with 3076 additions and 2009 deletions

View file

@ -12,13 +12,13 @@ import {
} from "drizzle-orm";
import type { z } from "zod/v4";
import { db } from "../tables/db.ts";
import { Applications } from "../tables/schema.ts";
import { Clients } from "../tables/schema.ts";
import { BaseInterface } from "./base.ts";
import { Token } from "./token.ts";
type ApplicationType = InferSelectModel<typeof Applications>;
type ApplicationType = InferSelectModel<typeof Clients>;
export class Application extends BaseInterface<typeof Applications> {
export class Application extends BaseInterface<typeof Clients> {
public static $type: ApplicationType;
public async reload(): Promise<void> {
@ -36,18 +36,18 @@ export class Application extends BaseInterface<typeof Applications> {
return null;
}
return await Application.fromSql(eq(Applications.id, id));
return await Application.fromSql(eq(Clients.id, id));
}
public static async fromIds(ids: string[]): Promise<Application[]> {
return await Application.manyFromSql(inArray(Applications.id, ids));
return await Application.manyFromSql(inArray(Clients.id, ids));
}
public static async fromSql(
sql: SQL<unknown> | undefined,
orderBy: SQL<unknown> | undefined = desc(Applications.id),
orderBy: SQL<unknown> | undefined = desc(Clients.id),
): Promise<Application | null> {
const found = await db.query.Applications.findFirst({
const found = await db.query.Clients.findFirst({
where: sql,
orderBy,
});
@ -60,12 +60,12 @@ export class Application extends BaseInterface<typeof Applications> {
public static async manyFromSql(
sql: SQL<unknown> | undefined,
orderBy: SQL<unknown> | undefined = desc(Applications.id),
orderBy: SQL<unknown> | undefined = desc(Clients.id),
limit?: number,
offset?: number,
extra?: Parameters<typeof db.query.Applications.findMany>[0],
extra?: Parameters<typeof db.query.Clients.findMany>[0],
): Promise<Application[]> {
const found = await db.query.Applications.findMany({
const found = await db.query.Clients.findMany({
where: sql,
orderBy,
limit,
@ -81,22 +81,20 @@ export class Application extends BaseInterface<typeof Applications> {
): Promise<Application | null> {
const result = await Token.fromAccessToken(token);
return result?.data.application
? new Application(result.data.application)
: null;
return result?.data.client ? new Application(result.data.client) : null;
}
public static fromClientId(clientId: string): Promise<Application | null> {
return Application.fromSql(eq(Applications.clientId, clientId));
return Application.fromSql(eq(Clients.id, clientId));
}
public async update(
newApplication: Partial<ApplicationType>,
): Promise<ApplicationType> {
await db
.update(Applications)
.update(Clients)
.set(newApplication)
.where(eq(Applications.id, this.id));
.where(eq(Clients.id, this.id));
const updated = await Application.fromId(this.data.id);
@ -114,18 +112,16 @@ export class Application extends BaseInterface<typeof Applications> {
public async delete(ids?: string[]): Promise<void> {
if (Array.isArray(ids)) {
await db.delete(Applications).where(inArray(Applications.id, ids));
await db.delete(Clients).where(inArray(Clients.id, ids));
} else {
await db.delete(Applications).where(eq(Applications.id, this.id));
await db.delete(Clients).where(eq(Clients.id, this.id));
}
}
public static async insert(
data: InferInsertModel<typeof Applications>,
data: InferInsertModel<typeof Clients>,
): Promise<Application> {
const inserted = (
await db.insert(Applications).values(data).returning()
)[0];
const inserted = (await db.insert(Clients).values(data).returning())[0];
const application = await Application.fromId(inserted.id);
@ -144,9 +140,9 @@ export class Application extends BaseInterface<typeof Applications> {
return {
name: this.data.name,
website: this.data.website,
scopes: this.data.scopes.split(" "),
redirect_uri: this.data.redirectUri,
redirect_uris: this.data.redirectUri.split("\n"),
scopes: this.data.scopes,
redirect_uri: this.data.redirectUris.join(" "),
redirect_uris: this.data.redirectUris,
};
}
@ -154,12 +150,12 @@ export class Application extends BaseInterface<typeof Applications> {
return {
name: this.data.name,
website: this.data.website,
client_id: this.data.clientId,
client_id: this.data.id,
client_secret: this.data.secret,
client_secret_expires_at: "0",
scopes: this.data.scopes.split(" "),
redirect_uri: this.data.redirectUri,
redirect_uris: this.data.redirectUri.split("\n"),
scopes: this.data.scopes,
redirect_uri: this.data.redirectUris.join(" "),
redirect_uris: this.data.redirectUris,
};
}
}

View file

@ -12,4 +12,4 @@ export { Relationship } from "./relationship.ts";
export { Role } from "./role.ts";
export { Timeline } from "./timeline.ts";
export { Token } from "./token.ts";
export { User } from "./user.ts";
export { transformOutputToUserWithRelations, User } from "./user.ts";

View file

@ -15,7 +15,7 @@ import { BaseInterface } from "./base.ts";
import { User } from "./user.ts";
type TokenType = InferSelectModel<typeof Tokens> & {
application: typeof Application.$type | null;
client: typeof Application.$type;
};
export class Token extends BaseInterface<typeof Tokens, TokenType> {
@ -51,7 +51,7 @@ export class Token extends BaseInterface<typeof Tokens, TokenType> {
where: sql,
orderBy,
with: {
application: true,
client: true,
},
});
@ -74,7 +74,7 @@ export class Token extends BaseInterface<typeof Tokens, TokenType> {
limit,
offset,
with: {
application: true,
client: true,
...extra?.with,
},
});
@ -159,7 +159,7 @@ export class Token extends BaseInterface<typeof Tokens, TokenType> {
return {
access_token: this.data.accessToken,
token_type: "Bearer",
scope: this.data.scope,
scope: this.data.scopes.join(" "),
created_at: Math.floor(
new Date(this.data.createdAt).getTime() / 1000,
),

View file

@ -77,6 +77,7 @@ export const userRelations = {
},
} as const;
// TODO: Remove this function and use what drizzle outputs directly instead of transforming it
export const transformOutputToUserWithRelations = (
user: Omit<InferSelectModel<typeof Users>, "endpoints"> & {
followerCount: unknown;
@ -525,15 +526,15 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
providers: {
id: string;
name: string;
url: string;
url: ProxiableUrl;
icon?: ProxiableUrl;
}[],
): Promise<
{
id: string;
name: string;
url: string;
icon?: string | undefined;
url: ProxiableUrl;
icon?: ProxiableUrl;
server_id: string;
}[]
> {
@ -556,7 +557,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
id: issuer.id,
name: issuer.name,
url: issuer.url,
icon: issuer.icon?.proxied,
icon: issuer.icon,
server_id: account.serverId,
};
})