feat: add auth extension points and one ssh connect pipeline

This commit is contained in:
LukeGus committed 2026-09-23 00:44:33 -05:00
1 parent d3c209af13
commit d774df8b41
159 files changed
+43243 -7451

No files matched your search

+23
View File
@@ -269,6 +269,29 @@ async function initializeCompleteDatabase(): Promise<void> {
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS user_external_identities (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
provider_id TEXT NOT NULL,
subject TEXT NOT NULL,
email TEXT,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE (provider_id, subject),
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_user_external_identities_user ON user_external_identities (user_id);
CREATE TABLE IF NOT EXISTS user_second_factors (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
plugin_id TEXT NOT NULL,
factor_id TEXT NOT NULL,
enrolled_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE (user_id, plugin_id, factor_id),
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS webauthn_credentials (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
+54
View File
@@ -120,6 +120,60 @@ export const trustedDevices = mysqlTable(
(table) => [index("idx_trusted_devices_user_id").on(table.userId)],
);
/**
* A sign-in identity from an external provider (OIDC, LDAP, GitHub, ...).
* Replaces identifier strings like "ldap:<provider>:<id>" on users.
*/
export const userExternalIdentities = mysqlTable(
"user_external_identities",
{
id: int("id").autoincrement().primaryKey(),
userId: varchar("user_id", { length: 255 })
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
providerId: varchar("provider_id", { length: 255 }).notNull(),
/** The provider's id for the user, at most 255 characters. */
subject: varchar("subject", { length: 255 }).notNull(),
email: text("email"),
createdAt: varchar("created_at", { length: 255 })
.notNull()
.default(sql`(CURRENT_TIMESTAMP)`),
},
(table) => [
uniqueIndex("idx_user_external_identities_provider_subject").on(
table.providerId,
table.subject,
),
index("idx_user_external_identities_user").on(table.userId),
],
);
/**
* Which second factors a user enrolled in, by plugin. Kept when the plugin is
* disabled or removed, so login fails closed instead of skipping the factor.
*/
export const userSecondFactors = mysqlTable(
"user_second_factors",
{
id: int("id").autoincrement().primaryKey(),
userId: varchar("user_id", { length: 255 })
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
pluginId: varchar("plugin_id", { length: 255 }).notNull(),
factorId: varchar("factor_id", { length: 255 }).notNull(),
enrolledAt: text("enrolled_at")
.notNull()
.default(sql`(CURRENT_TIMESTAMP)`),
},
(table) => [
uniqueIndex("idx_user_second_factors_user_factor").on(
table.userId,
table.pluginId,
table.factorId,
),
],
);
export const webauthnCredentials = mysqlTable("webauthn_credentials", {
id: varchar("id", { length: 255 }).primaryKey(),
userId: varchar("user_id", { length: 255 })
+54
View File
@@ -121,6 +121,60 @@ export const trustedDevices = pgTable(
(table) => [index("idx_trusted_devices_user_id").on(table.userId)],
);
/**
* A sign-in identity from an external provider (OIDC, LDAP, GitHub, ...).
* Replaces identifier strings like "ldap:<provider>:<id>" on users.
*/
export const userExternalIdentities = pgTable(
"user_external_identities",
{
id: serial("id").primaryKey(),
userId: varchar("user_id", { length: 255 })
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
providerId: varchar("provider_id", { length: 255 }).notNull(),
/** The provider's id for the user, at most 255 characters. */
subject: varchar("subject", { length: 255 }).notNull(),
email: text("email"),
createdAt: varchar("created_at", { length: 255 })
.notNull()
.default(sql`CURRENT_TIMESTAMP`),
},
(table) => [
uniqueIndex("idx_user_external_identities_provider_subject").on(
table.providerId,
table.subject,
),
index("idx_user_external_identities_user").on(table.userId),
],
);
/**
* Which second factors a user enrolled in, by plugin. Kept when the plugin is
* disabled or removed, so login fails closed instead of skipping the factor.
*/
export const userSecondFactors = pgTable(
"user_second_factors",
{
id: serial("id").primaryKey(),
userId: varchar("user_id", { length: 255 })
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
pluginId: varchar("plugin_id", { length: 255 }).notNull(),
factorId: varchar("factor_id", { length: 255 }).notNull(),
enrolledAt: text("enrolled_at")
.notNull()
.default(sql`CURRENT_TIMESTAMP`),
},
(table) => [
uniqueIndex("idx_user_second_factors_user_factor").on(
table.userId,
table.pluginId,
table.factorId,
),
],
);
export const webauthnCredentials = pgTable("webauthn_credentials", {
id: varchar("id", { length: 255 }).primaryKey(),
userId: varchar("user_id", { length: 255 })
+54
View File
@@ -111,6 +111,60 @@ export const trustedDevices = sqliteTable(
(table) => [index("idx_trusted_devices_user_id").on(table.userId)],
);
/**
* A sign-in identity from an external provider (OIDC, LDAP, GitHub, ...).
* Replaces identifier strings like "ldap:<provider>:<id>" on users.
*/
export const userExternalIdentities = sqliteTable(
"user_external_identities",
{
id: integer("id").primaryKey({ autoIncrement: true }),
userId: text("user_id")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
providerId: text("provider_id").notNull(),
/** The provider's id for the user, at most 255 characters. */
subject: text("subject").notNull(),
email: text("email"),
createdAt: text("created_at")
.notNull()
.default(sql`CURRENT_TIMESTAMP`),
},
(table) => [
uniqueIndex("idx_user_external_identities_provider_subject").on(
table.providerId,
table.subject,
),
index("idx_user_external_identities_user").on(table.userId),
],
);
/**
* Which second factors a user enrolled in, by plugin. Kept when the plugin is
* disabled or removed, so login fails closed instead of skipping the factor.
*/
export const userSecondFactors = sqliteTable(
"user_second_factors",
{
id: integer("id").primaryKey({ autoIncrement: true }),
userId: text("user_id")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
pluginId: text("plugin_id").notNull(),
factorId: text("factor_id").notNull(),
enrolledAt: text("enrolled_at")
.notNull()
.default(sql`CURRENT_TIMESTAMP`),
},
(table) => [
uniqueIndex("idx_user_second_factors_user_factor").on(
table.userId,
table.pluginId,
table.factorId,
),
],
);
export const webauthnCredentials = sqliteTable("webauthn_credentials", {
id: text("id").primaryKey(),
userId: text("user_id")