diff --git a/server/db/asns.ts b/server/db/asns.ts index f78577f5..baeb7488 100644 --- a/server/db/asns.ts +++ b/server/db/asns.ts @@ -68,7 +68,7 @@ export const MAJOR_ASNS = [ code: "AS36351", asn: 36351 }, - + // CDNs { name: "Cloudflare", @@ -90,7 +90,7 @@ export const MAJOR_ASNS = [ code: "AS16625", asn: 16625 }, - + // Mobile Carriers - US { name: "T-Mobile USA", @@ -117,7 +117,7 @@ export const MAJOR_ASNS = [ code: "AS6430", asn: 6430 }, - + // Mobile Carriers - Europe { name: "Vodafone UK", @@ -144,7 +144,7 @@ export const MAJOR_ASNS = [ code: "AS12430", asn: 12430 }, - + // Mobile Carriers - Asia { name: "NTT DoCoMo (Japan)", @@ -176,7 +176,7 @@ export const MAJOR_ASNS = [ code: "AS9808", asn: 9808 }, - + // Major US ISPs { name: "AT&T Services", @@ -208,7 +208,7 @@ export const MAJOR_ASNS = [ code: "AS209", asn: 209 }, - + // Major European ISPs { name: "Deutsche Telekom", @@ -235,7 +235,7 @@ export const MAJOR_ASNS = [ code: "AS12956", asn: 12956 }, - + // Major Asian ISPs { name: "China Telecom", @@ -262,7 +262,7 @@ export const MAJOR_ASNS = [ code: "AS55836", asn: 55836 }, - + // VPN/Proxy Providers { name: "Private Internet Access", @@ -279,7 +279,7 @@ export const MAJOR_ASNS = [ code: "AS213281", asn: 213281 }, - + // Social Media / Major Tech { name: "Facebook/Meta", @@ -301,7 +301,7 @@ export const MAJOR_ASNS = [ code: "AS2906", asn: 2906 }, - + // Academic/Research { name: "MIT", diff --git a/server/db/pg/schema/schema.ts b/server/db/pg/schema/schema.ts index a64f0394..fdd6bfa0 100644 --- a/server/db/pg/schema/schema.ts +++ b/server/db/pg/schema/schema.ts @@ -134,13 +134,15 @@ export const resources = pgTable("resources", { proxyProtocol: boolean("proxyProtocol").notNull().default(false), proxyProtocolVersion: integer("proxyProtocolVersion").default(1), - maintenanceModeEnabled: boolean("maintenanceModeEnabled").notNull().default(false), + maintenanceModeEnabled: boolean("maintenanceModeEnabled") + .notNull() + .default(false), maintenanceModeType: text("maintenanceModeType", { enum: ["forced", "automatic"] }).default("forced"), // "forced" = always show, "automatic" = only when down maintenanceTitle: text("maintenanceTitle"), maintenanceMessage: text("maintenanceMessage"), - maintenanceEstimatedTime: text("maintenanceEstimatedTime"), + maintenanceEstimatedTime: text("maintenanceEstimatedTime") }); export const targets = pgTable("targets", { @@ -464,13 +466,22 @@ export const resourceHeaderAuth = pgTable("resourceHeaderAuth", { headerAuthHash: varchar("headerAuthHash").notNull() }); -export const resourceHeaderAuthExtendedCompatibility = pgTable("resourceHeaderAuthExtendedCompatibility", { - headerAuthExtendedCompatibilityId: serial("headerAuthExtendedCompatibilityId").primaryKey(), - resourceId: integer("resourceId") - .notNull() - .references(() => resources.resourceId, { onDelete: "cascade" }), - extendedCompatibilityIsActivated: boolean("extendedCompatibilityIsActivated").notNull().default(true), -}); +export const resourceHeaderAuthExtendedCompatibility = pgTable( + "resourceHeaderAuthExtendedCompatibility", + { + headerAuthExtendedCompatibilityId: serial( + "headerAuthExtendedCompatibilityId" + ).primaryKey(), + resourceId: integer("resourceId") + .notNull() + .references(() => resources.resourceId, { onDelete: "cascade" }), + extendedCompatibilityIsActivated: boolean( + "extendedCompatibilityIsActivated" + ) + .notNull() + .default(true) + } +); export const resourceAccessToken = pgTable("resourceAccessToken", { accessTokenId: varchar("accessTokenId").primaryKey(), @@ -872,7 +883,9 @@ export type ResourceSession = InferSelectModel; export type ResourcePincode = InferSelectModel; export type ResourcePassword = InferSelectModel; export type ResourceHeaderAuth = InferSelectModel; -export type ResourceHeaderAuthExtendedCompatibility = InferSelectModel; +export type ResourceHeaderAuthExtendedCompatibility = InferSelectModel< + typeof resourceHeaderAuthExtendedCompatibility +>; export type ResourceOtp = InferSelectModel; export type ResourceAccessToken = InferSelectModel; export type ResourceWhitelist = InferSelectModel; diff --git a/server/db/queries/verifySessionQueries.ts b/server/db/queries/verifySessionQueries.ts index 381185e5..3c6c5420 100644 --- a/server/db/queries/verifySessionQueries.ts +++ b/server/db/queries/verifySessionQueries.ts @@ -1,6 +1,4 @@ -import { - db, loginPage, LoginPage, loginPageOrg, Org, orgs, -} from "@server/db"; +import { db, loginPage, LoginPage, loginPageOrg, Org, orgs } from "@server/db"; import { Resource, ResourcePassword, @@ -27,7 +25,7 @@ export type ResourceWithAuth = { pincode: ResourcePincode | null; password: ResourcePassword | null; headerAuth: ResourceHeaderAuth | null; - headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null + headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null; org: Org; }; @@ -59,12 +57,12 @@ export async function getResourceByDomain( ) .leftJoin( resourceHeaderAuthExtendedCompatibility, - eq(resourceHeaderAuthExtendedCompatibility.resourceId, resources.resourceId) - ) - .innerJoin( - orgs, - eq(orgs.orgId, resources.orgId) + eq( + resourceHeaderAuthExtendedCompatibility.resourceId, + resources.resourceId + ) ) + .innerJoin(orgs, eq(orgs.orgId, resources.orgId)) .where(eq(resources.fullDomain, domain)) .limit(1); @@ -77,7 +75,8 @@ export async function getResourceByDomain( pincode: result.resourcePincode, password: result.resourcePassword, headerAuth: result.resourceHeaderAuth, - headerAuthExtendedCompatibility: result.resourceHeaderAuthExtendedCompatibility, + headerAuthExtendedCompatibility: + result.resourceHeaderAuthExtendedCompatibility, org: result.orgs }; } diff --git a/server/db/sqlite/schema/schema.ts b/server/db/sqlite/schema/schema.ts index 5ae82ba9..0f29bab1 100644 --- a/server/db/sqlite/schema/schema.ts +++ b/server/db/sqlite/schema/schema.ts @@ -12,22 +12,22 @@ import { no } from "zod/v4/locales"; export const domains = sqliteTable("domains", { domainId: text("domainId").primaryKey(), baseDomain: text("baseDomain").notNull(), - configManaged: integer("configManaged", {mode: "boolean"}) + configManaged: integer("configManaged", { mode: "boolean" }) .notNull() .default(false), type: text("type"), // "ns", "cname", "wildcard" - verified: integer("verified", {mode: "boolean"}).notNull().default(false), - failed: integer("failed", {mode: "boolean"}).notNull().default(false), + verified: integer("verified", { mode: "boolean" }).notNull().default(false), + failed: integer("failed", { mode: "boolean" }).notNull().default(false), tries: integer("tries").notNull().default(0), certResolver: text("certResolver"), - preferWildcardCert: integer("preferWildcardCert", {mode: "boolean"}) + preferWildcardCert: integer("preferWildcardCert", { mode: "boolean" }) }); export const dnsRecords = sqliteTable("dnsRecords", { - id: integer("id").primaryKey({autoIncrement: true}), + id: integer("id").primaryKey({ autoIncrement: true }), domainId: text("domainId") .notNull() - .references(() => domains.domainId, {onDelete: "cascade"}), + .references(() => domains.domainId, { onDelete: "cascade" }), recordType: text("recordType").notNull(), // "NS" | "CNAME" | "A" | "TXT" baseDomain: text("baseDomain"), @@ -41,7 +41,7 @@ export const orgs = sqliteTable("orgs", { subnet: text("subnet"), utilitySubnet: text("utilitySubnet"), // this is the subnet for utility addresses createdAt: text("createdAt"), - requireTwoFactor: integer("requireTwoFactor", {mode: "boolean"}), + requireTwoFactor: integer("requireTwoFactor", { mode: "boolean" }), maxSessionLengthHours: integer("maxSessionLengthHours"), // hours passwordExpiryDays: integer("passwordExpiryDays"), // days settingsLogRetentionDaysRequest: integer("settingsLogRetentionDaysRequest") // where 0 = dont keep logs and -1 = keep forever and 9001 = end of the following year @@ -58,23 +58,23 @@ export const orgs = sqliteTable("orgs", { export const userDomains = sqliteTable("userDomains", { userId: text("userId") .notNull() - .references(() => users.userId, {onDelete: "cascade"}), + .references(() => users.userId, { onDelete: "cascade" }), domainId: text("domainId") .notNull() - .references(() => domains.domainId, {onDelete: "cascade"}) + .references(() => domains.domainId, { onDelete: "cascade" }) }); export const orgDomains = sqliteTable("orgDomains", { orgId: text("orgId") .notNull() - .references(() => orgs.orgId, {onDelete: "cascade"}), + .references(() => orgs.orgId, { onDelete: "cascade" }), domainId: text("domainId") .notNull() - .references(() => domains.domainId, {onDelete: "cascade"}) + .references(() => domains.domainId, { onDelete: "cascade" }) }); export const sites = sqliteTable("sites", { - siteId: integer("siteId").primaryKey({autoIncrement: true}), + siteId: integer("siteId").primaryKey({ autoIncrement: true }), orgId: text("orgId") .references(() => orgs.orgId, { onDelete: "cascade" @@ -91,7 +91,7 @@ export const sites = sqliteTable("sites", { megabytesOut: integer("bytesOut").default(0), lastBandwidthUpdate: text("lastBandwidthUpdate"), type: text("type").notNull(), // "newt" or "wireguard" - online: integer("online", {mode: "boolean"}).notNull().default(false), + online: integer("online", { mode: "boolean" }).notNull().default(false), // exit node stuff that is how to connect to the site when it has a wg server address: text("address"), // this is the address of the wireguard interface in newt @@ -99,14 +99,14 @@ export const sites = sqliteTable("sites", { publicKey: text("publicKey"), // TODO: Fix typo in publicKey lastHolePunch: integer("lastHolePunch"), listenPort: integer("listenPort"), - dockerSocketEnabled: integer("dockerSocketEnabled", {mode: "boolean"}) + dockerSocketEnabled: integer("dockerSocketEnabled", { mode: "boolean" }) .notNull() .default(true) }); export const resources = sqliteTable("resources", { - resourceId: integer("resourceId").primaryKey({autoIncrement: true}), - resourceGuid: text("resourceGuid", {length: 36}) + resourceId: integer("resourceId").primaryKey({ autoIncrement: true }), + resourceGuid: text("resourceGuid", { length: 36 }) .unique() .notNull() .$defaultFn(() => randomUUID()), @@ -122,35 +122,39 @@ export const resources = sqliteTable("resources", { domainId: text("domainId").references(() => domains.domainId, { onDelete: "set null" }), - ssl: integer("ssl", {mode: "boolean"}).notNull().default(false), - blockAccess: integer("blockAccess", {mode: "boolean"}) + ssl: integer("ssl", { mode: "boolean" }).notNull().default(false), + blockAccess: integer("blockAccess", { mode: "boolean" }) .notNull() .default(false), - sso: integer("sso", {mode: "boolean"}).notNull().default(true), - http: integer("http", {mode: "boolean"}).notNull().default(true), + sso: integer("sso", { mode: "boolean" }).notNull().default(true), + http: integer("http", { mode: "boolean" }).notNull().default(true), protocol: text("protocol").notNull(), proxyPort: integer("proxyPort"), - emailWhitelistEnabled: integer("emailWhitelistEnabled", {mode: "boolean"}) + emailWhitelistEnabled: integer("emailWhitelistEnabled", { mode: "boolean" }) .notNull() .default(false), - applyRules: integer("applyRules", {mode: "boolean"}) + applyRules: integer("applyRules", { mode: "boolean" }) .notNull() .default(false), - enabled: integer("enabled", {mode: "boolean"}).notNull().default(true), - stickySession: integer("stickySession", {mode: "boolean"}) + enabled: integer("enabled", { mode: "boolean" }).notNull().default(true), + stickySession: integer("stickySession", { mode: "boolean" }) .notNull() .default(false), tlsServerName: text("tlsServerName"), setHostHeader: text("setHostHeader"), - enableProxy: integer("enableProxy", {mode: "boolean"}).default(true), + enableProxy: integer("enableProxy", { mode: "boolean" }).default(true), skipToIdpId: integer("skipToIdpId").references(() => idp.idpId, { onDelete: "set null" }), headers: text("headers"), // comma-separated list of headers to add to the request - proxyProtocol: integer("proxyProtocol", { mode: "boolean" }).notNull().default(false), + proxyProtocol: integer("proxyProtocol", { mode: "boolean" }) + .notNull() + .default(false), proxyProtocolVersion: integer("proxyProtocolVersion").default(1), - maintenanceModeEnabled: integer("maintenanceModeEnabled", { mode: "boolean" }) + maintenanceModeEnabled: integer("maintenanceModeEnabled", { + mode: "boolean" + }) .notNull() .default(false), maintenanceModeType: text("maintenanceModeType", { @@ -158,12 +162,11 @@ export const resources = sqliteTable("resources", { }).default("forced"), // "forced" = always show, "automatic" = only when down maintenanceTitle: text("maintenanceTitle"), maintenanceMessage: text("maintenanceMessage"), - maintenanceEstimatedTime: text("maintenanceEstimatedTime"), - + maintenanceEstimatedTime: text("maintenanceEstimatedTime") }); export const targets = sqliteTable("targets", { - targetId: integer("targetId").primaryKey({autoIncrement: true}), + targetId: integer("targetId").primaryKey({ autoIncrement: true }), resourceId: integer("resourceId") .references(() => resources.resourceId, { onDelete: "cascade" @@ -178,7 +181,7 @@ export const targets = sqliteTable("targets", { method: text("method"), port: integer("port").notNull(), internalPort: integer("internalPort"), - enabled: integer("enabled", {mode: "boolean"}).notNull().default(true), + enabled: integer("enabled", { mode: "boolean" }).notNull().default(true), path: text("path"), pathMatchType: text("pathMatchType"), // exact, prefix, regex rewritePath: text("rewritePath"), // if set, rewrites the path to this value before sending to the target @@ -192,8 +195,8 @@ export const targetHealthCheck = sqliteTable("targetHealthCheck", { }), targetId: integer("targetId") .notNull() - .references(() => targets.targetId, {onDelete: "cascade"}), - hcEnabled: integer("hcEnabled", {mode: "boolean"}) + .references(() => targets.targetId, { onDelete: "cascade" }), + hcEnabled: integer("hcEnabled", { mode: "boolean" }) .notNull() .default(false), hcPath: text("hcPath"), @@ -215,7 +218,7 @@ export const targetHealthCheck = sqliteTable("targetHealthCheck", { }); export const exitNodes = sqliteTable("exitNodes", { - exitNodeId: integer("exitNodeId").primaryKey({autoIncrement: true}), + exitNodeId: integer("exitNodeId").primaryKey({ autoIncrement: true }), name: text("name").notNull(), address: text("address").notNull(), // this is the address of the wireguard interface in gerbil endpoint: text("endpoint").notNull(), // this is how to reach gerbil externally - gets put into the wireguard config @@ -223,7 +226,7 @@ export const exitNodes = sqliteTable("exitNodes", { listenPort: integer("listenPort").notNull(), reachableAt: text("reachableAt"), // this is the internal address of the gerbil http server for command control maxConnections: integer("maxConnections"), - online: integer("online", {mode: "boolean"}).notNull().default(false), + online: integer("online", { mode: "boolean" }).notNull().default(false), lastPing: integer("lastPing"), type: text("type").default("gerbil"), // gerbil, remoteExitNode region: text("region") @@ -236,10 +239,10 @@ export const siteResources = sqliteTable("siteResources", { }), siteId: integer("siteId") .notNull() - .references(() => sites.siteId, {onDelete: "cascade"}), + .references(() => sites.siteId, { onDelete: "cascade" }), orgId: text("orgId") .notNull() - .references(() => orgs.orgId, {onDelete: "cascade"}), + .references(() => orgs.orgId, { onDelete: "cascade" }), niceId: text("niceId").notNull(), name: text("name").notNull(), mode: text("mode").notNull(), // "host" | "cidr" | "port" @@ -292,20 +295,20 @@ export const users = sqliteTable("user", { onDelete: "cascade" }), passwordHash: text("passwordHash"), - twoFactorEnabled: integer("twoFactorEnabled", {mode: "boolean"}) + twoFactorEnabled: integer("twoFactorEnabled", { mode: "boolean" }) .notNull() .default(false), twoFactorSetupRequested: integer("twoFactorSetupRequested", { mode: "boolean" }).default(false), twoFactorSecret: text("twoFactorSecret"), - emailVerified: integer("emailVerified", {mode: "boolean"}) + emailVerified: integer("emailVerified", { mode: "boolean" }) .notNull() .default(false), dateCreated: text("dateCreated").notNull(), termsAcceptedTimestamp: text("termsAcceptedTimestamp"), termsVersion: text("termsVersion"), - serverAdmin: integer("serverAdmin", {mode: "boolean"}) + serverAdmin: integer("serverAdmin", { mode: "boolean" }) .notNull() .default(false), lastPasswordChange: integer("lastPasswordChange") @@ -339,7 +342,7 @@ export const webauthnChallenge = sqliteTable("webauthnChallenge", { export const setupTokens = sqliteTable("setupTokens", { tokenId: text("tokenId").primaryKey(), token: text("token").notNull(), - used: integer("used", {mode: "boolean"}).notNull().default(false), + used: integer("used", { mode: "boolean" }).notNull().default(false), dateCreated: text("dateCreated").notNull(), dateUsed: text("dateUsed") }); @@ -378,7 +381,7 @@ export const clients = sqliteTable("clients", { lastBandwidthUpdate: text("lastBandwidthUpdate"), lastPing: integer("lastPing"), type: text("type").notNull(), // "olm" - online: integer("online", {mode: "boolean"}).notNull().default(false), + online: integer("online", { mode: "boolean" }).notNull().default(false), // endpoint: text("endpoint"), lastHolePunch: integer("lastHolePunch") }); @@ -424,10 +427,10 @@ export const olms = sqliteTable("olms", { }); export const twoFactorBackupCodes = sqliteTable("twoFactorBackupCodes", { - codeId: integer("id").primaryKey({autoIncrement: true}), + codeId: integer("id").primaryKey({ autoIncrement: true }), userId: text("userId") .notNull() - .references(() => users.userId, {onDelete: "cascade"}), + .references(() => users.userId, { onDelete: "cascade" }), codeHash: text("codeHash").notNull() }); @@ -435,7 +438,7 @@ export const sessions = sqliteTable("session", { sessionId: text("id").primaryKey(), userId: text("userId") .notNull() - .references(() => users.userId, {onDelete: "cascade"}), + .references(() => users.userId, { onDelete: "cascade" }), expiresAt: integer("expiresAt").notNull(), issuedAt: integer("issuedAt"), deviceAuthUsed: integer("deviceAuthUsed", { mode: "boolean" }) @@ -447,7 +450,7 @@ export const newtSessions = sqliteTable("newtSession", { sessionId: text("id").primaryKey(), newtId: text("newtId") .notNull() - .references(() => newts.newtId, {onDelete: "cascade"}), + .references(() => newts.newtId, { onDelete: "cascade" }), expiresAt: integer("expiresAt").notNull() }); @@ -455,14 +458,14 @@ export const olmSessions = sqliteTable("clientSession", { sessionId: text("id").primaryKey(), olmId: text("olmId") .notNull() - .references(() => olms.olmId, {onDelete: "cascade"}), + .references(() => olms.olmId, { onDelete: "cascade" }), expiresAt: integer("expiresAt").notNull() }); export const userOrgs = sqliteTable("userOrgs", { userId: text("userId") .notNull() - .references(() => users.userId, {onDelete: "cascade"}), + .references(() => users.userId, { onDelete: "cascade" }), orgId: text("orgId") .references(() => orgs.orgId, { onDelete: "cascade" @@ -471,28 +474,28 @@ export const userOrgs = sqliteTable("userOrgs", { roleId: integer("roleId") .notNull() .references(() => roles.roleId), - isOwner: integer("isOwner", {mode: "boolean"}).notNull().default(false), + isOwner: integer("isOwner", { mode: "boolean" }).notNull().default(false), autoProvisioned: integer("autoProvisioned", { mode: "boolean" }).default(false) }); export const emailVerificationCodes = sqliteTable("emailVerificationCodes", { - codeId: integer("id").primaryKey({autoIncrement: true}), + codeId: integer("id").primaryKey({ autoIncrement: true }), userId: text("userId") .notNull() - .references(() => users.userId, {onDelete: "cascade"}), + .references(() => users.userId, { onDelete: "cascade" }), email: text("email").notNull(), code: text("code").notNull(), expiresAt: integer("expiresAt").notNull() }); export const passwordResetTokens = sqliteTable("passwordResetTokens", { - tokenId: integer("id").primaryKey({autoIncrement: true}), + tokenId: integer("id").primaryKey({ autoIncrement: true }), email: text("email").notNull(), userId: text("userId") .notNull() - .references(() => users.userId, {onDelete: "cascade"}), + .references(() => users.userId, { onDelete: "cascade" }), tokenHash: text("tokenHash").notNull(), expiresAt: integer("expiresAt").notNull() }); @@ -504,13 +507,13 @@ export const actions = sqliteTable("actions", { }); export const roles = sqliteTable("roles", { - roleId: integer("roleId").primaryKey({autoIncrement: true}), + roleId: integer("roleId").primaryKey({ autoIncrement: true }), orgId: text("orgId") .references(() => orgs.orgId, { onDelete: "cascade" }) .notNull(), - isAdmin: integer("isAdmin", {mode: "boolean"}), + isAdmin: integer("isAdmin", { mode: "boolean" }), name: text("name").notNull(), description: text("description") }); @@ -518,92 +521,92 @@ export const roles = sqliteTable("roles", { export const roleActions = sqliteTable("roleActions", { roleId: integer("roleId") .notNull() - .references(() => roles.roleId, {onDelete: "cascade"}), + .references(() => roles.roleId, { onDelete: "cascade" }), actionId: text("actionId") .notNull() - .references(() => actions.actionId, {onDelete: "cascade"}), + .references(() => actions.actionId, { onDelete: "cascade" }), orgId: text("orgId") .notNull() - .references(() => orgs.orgId, {onDelete: "cascade"}) + .references(() => orgs.orgId, { onDelete: "cascade" }) }); export const userActions = sqliteTable("userActions", { userId: text("userId") .notNull() - .references(() => users.userId, {onDelete: "cascade"}), + .references(() => users.userId, { onDelete: "cascade" }), actionId: text("actionId") .notNull() - .references(() => actions.actionId, {onDelete: "cascade"}), + .references(() => actions.actionId, { onDelete: "cascade" }), orgId: text("orgId") .notNull() - .references(() => orgs.orgId, {onDelete: "cascade"}) + .references(() => orgs.orgId, { onDelete: "cascade" }) }); export const roleSites = sqliteTable("roleSites", { roleId: integer("roleId") .notNull() - .references(() => roles.roleId, {onDelete: "cascade"}), + .references(() => roles.roleId, { onDelete: "cascade" }), siteId: integer("siteId") .notNull() - .references(() => sites.siteId, {onDelete: "cascade"}) + .references(() => sites.siteId, { onDelete: "cascade" }) }); export const userSites = sqliteTable("userSites", { userId: text("userId") .notNull() - .references(() => users.userId, {onDelete: "cascade"}), + .references(() => users.userId, { onDelete: "cascade" }), siteId: integer("siteId") .notNull() - .references(() => sites.siteId, {onDelete: "cascade"}) + .references(() => sites.siteId, { onDelete: "cascade" }) }); export const userClients = sqliteTable("userClients", { userId: text("userId") .notNull() - .references(() => users.userId, {onDelete: "cascade"}), + .references(() => users.userId, { onDelete: "cascade" }), clientId: integer("clientId") .notNull() - .references(() => clients.clientId, {onDelete: "cascade"}) + .references(() => clients.clientId, { onDelete: "cascade" }) }); export const roleClients = sqliteTable("roleClients", { roleId: integer("roleId") .notNull() - .references(() => roles.roleId, {onDelete: "cascade"}), + .references(() => roles.roleId, { onDelete: "cascade" }), clientId: integer("clientId") .notNull() - .references(() => clients.clientId, {onDelete: "cascade"}) + .references(() => clients.clientId, { onDelete: "cascade" }) }); export const roleResources = sqliteTable("roleResources", { roleId: integer("roleId") .notNull() - .references(() => roles.roleId, {onDelete: "cascade"}), + .references(() => roles.roleId, { onDelete: "cascade" }), resourceId: integer("resourceId") .notNull() - .references(() => resources.resourceId, {onDelete: "cascade"}) + .references(() => resources.resourceId, { onDelete: "cascade" }) }); export const userResources = sqliteTable("userResources", { userId: text("userId") .notNull() - .references(() => users.userId, {onDelete: "cascade"}), + .references(() => users.userId, { onDelete: "cascade" }), resourceId: integer("resourceId") .notNull() - .references(() => resources.resourceId, {onDelete: "cascade"}) + .references(() => resources.resourceId, { onDelete: "cascade" }) }); export const userInvites = sqliteTable("userInvites", { inviteId: text("inviteId").primaryKey(), orgId: text("orgId") .notNull() - .references(() => orgs.orgId, {onDelete: "cascade"}), + .references(() => orgs.orgId, { onDelete: "cascade" }), email: text("email").notNull(), expiresAt: integer("expiresAt").notNull(), tokenHash: text("token").notNull(), roleId: integer("roleId") .notNull() - .references(() => roles.roleId, {onDelete: "cascade"}) + .references(() => roles.roleId, { onDelete: "cascade" }) }); export const resourcePincode = sqliteTable("resourcePincode", { @@ -612,7 +615,7 @@ export const resourcePincode = sqliteTable("resourcePincode", { }), resourceId: integer("resourceId") .notNull() - .references(() => resources.resourceId, {onDelete: "cascade"}), + .references(() => resources.resourceId, { onDelete: "cascade" }), pincodeHash: text("pincodeHash").notNull(), digitLength: integer("digitLength").notNull() }); @@ -623,7 +626,7 @@ export const resourcePassword = sqliteTable("resourcePassword", { }), resourceId: integer("resourceId") .notNull() - .references(() => resources.resourceId, {onDelete: "cascade"}), + .references(() => resources.resourceId, { onDelete: "cascade" }), passwordHash: text("passwordHash").notNull() }); @@ -633,28 +636,38 @@ export const resourceHeaderAuth = sqliteTable("resourceHeaderAuth", { }), resourceId: integer("resourceId") .notNull() - .references(() => resources.resourceId, {onDelete: "cascade"}), + .references(() => resources.resourceId, { onDelete: "cascade" }), headerAuthHash: text("headerAuthHash").notNull() }); -export const resourceHeaderAuthExtendedCompatibility = sqliteTable("resourceHeaderAuthExtendedCompatibility", { - headerAuthExtendedCompatibilityId: integer("headerAuthExtendedCompatibilityId").primaryKey({ - autoIncrement: true - }), - resourceId: integer("resourceId") - .notNull() - .references(() => resources.resourceId, {onDelete: "cascade"}), - extendedCompatibilityIsActivated: integer("extendedCompatibilityIsActivated", {mode: "boolean"}).notNull().default(true) -}); +export const resourceHeaderAuthExtendedCompatibility = sqliteTable( + "resourceHeaderAuthExtendedCompatibility", + { + headerAuthExtendedCompatibilityId: integer( + "headerAuthExtendedCompatibilityId" + ).primaryKey({ + autoIncrement: true + }), + resourceId: integer("resourceId") + .notNull() + .references(() => resources.resourceId, { onDelete: "cascade" }), + extendedCompatibilityIsActivated: integer( + "extendedCompatibilityIsActivated", + { mode: "boolean" } + ) + .notNull() + .default(true) + } +); export const resourceAccessToken = sqliteTable("resourceAccessToken", { accessTokenId: text("accessTokenId").primaryKey(), orgId: text("orgId") .notNull() - .references(() => orgs.orgId, {onDelete: "cascade"}), + .references(() => orgs.orgId, { onDelete: "cascade" }), resourceId: integer("resourceId") .notNull() - .references(() => resources.resourceId, {onDelete: "cascade"}), + .references(() => resources.resourceId, { onDelete: "cascade" }), tokenHash: text("tokenHash").notNull(), sessionLength: integer("sessionLength").notNull(), expiresAt: integer("expiresAt"), @@ -667,13 +680,13 @@ export const resourceSessions = sqliteTable("resourceSessions", { sessionId: text("id").primaryKey(), resourceId: integer("resourceId") .notNull() - .references(() => resources.resourceId, {onDelete: "cascade"}), + .references(() => resources.resourceId, { onDelete: "cascade" }), expiresAt: integer("expiresAt").notNull(), sessionLength: integer("sessionLength").notNull(), - doNotExtend: integer("doNotExtend", {mode: "boolean"}) + doNotExtend: integer("doNotExtend", { mode: "boolean" }) .notNull() .default(false), - isRequestToken: integer("isRequestToken", {mode: "boolean"}), + isRequestToken: integer("isRequestToken", { mode: "boolean" }), userSessionId: text("userSessionId").references(() => sessions.sessionId, { onDelete: "cascade" }), @@ -705,11 +718,11 @@ export const resourceSessions = sqliteTable("resourceSessions", { }); export const resourceWhitelist = sqliteTable("resourceWhitelist", { - whitelistId: integer("id").primaryKey({autoIncrement: true}), + whitelistId: integer("id").primaryKey({ autoIncrement: true }), email: text("email").notNull(), resourceId: integer("resourceId") .notNull() - .references(() => resources.resourceId, {onDelete: "cascade"}) + .references(() => resources.resourceId, { onDelete: "cascade" }) }); export const resourceOtp = sqliteTable("resourceOtp", { @@ -718,7 +731,7 @@ export const resourceOtp = sqliteTable("resourceOtp", { }), resourceId: integer("resourceId") .notNull() - .references(() => resources.resourceId, {onDelete: "cascade"}), + .references(() => resources.resourceId, { onDelete: "cascade" }), email: text("email").notNull(), otpHash: text("otpHash").notNull(), expiresAt: integer("expiresAt").notNull() @@ -730,11 +743,11 @@ export const versionMigrations = sqliteTable("versionMigrations", { }); export const resourceRules = sqliteTable("resourceRules", { - ruleId: integer("ruleId").primaryKey({autoIncrement: true}), + ruleId: integer("ruleId").primaryKey({ autoIncrement: true }), resourceId: integer("resourceId") .notNull() - .references(() => resources.resourceId, {onDelete: "cascade"}), - enabled: integer("enabled", {mode: "boolean"}).notNull().default(true), + .references(() => resources.resourceId, { onDelete: "cascade" }), + enabled: integer("enabled", { mode: "boolean" }).notNull().default(true), priority: integer("priority").notNull(), action: text("action").notNull(), // ACCEPT, DROP, PASS match: text("match").notNull(), // CIDR, PATH, IP @@ -742,17 +755,17 @@ export const resourceRules = sqliteTable("resourceRules", { }); export const supporterKey = sqliteTable("supporterKey", { - keyId: integer("keyId").primaryKey({autoIncrement: true}), + keyId: integer("keyId").primaryKey({ autoIncrement: true }), key: text("key").notNull(), githubUsername: text("githubUsername").notNull(), phrase: text("phrase"), tier: text("tier"), - valid: integer("valid", {mode: "boolean"}).notNull().default(false) + valid: integer("valid", { mode: "boolean" }).notNull().default(false) }); // Identity Providers export const idp = sqliteTable("idp", { - idpId: integer("idpId").primaryKey({autoIncrement: true}), + idpId: integer("idpId").primaryKey({ autoIncrement: true }), name: text("name").notNull(), type: text("type").notNull(), defaultRoleMapping: text("defaultRoleMapping"), @@ -772,7 +785,7 @@ export const idpOidcConfig = sqliteTable("idpOidcConfig", { variant: text("variant").notNull().default("oidc"), idpId: integer("idpId") .notNull() - .references(() => idp.idpId, {onDelete: "cascade"}), + .references(() => idp.idpId, { onDelete: "cascade" }), clientId: text("clientId").notNull(), clientSecret: text("clientSecret").notNull(), authUrl: text("authUrl").notNull(), @@ -800,22 +813,22 @@ export const apiKeys = sqliteTable("apiKeys", { apiKeyHash: text("apiKeyHash").notNull(), lastChars: text("lastChars").notNull(), createdAt: text("dateCreated").notNull(), - isRoot: integer("isRoot", {mode: "boolean"}).notNull().default(false) + isRoot: integer("isRoot", { mode: "boolean" }).notNull().default(false) }); export const apiKeyActions = sqliteTable("apiKeyActions", { apiKeyId: text("apiKeyId") .notNull() - .references(() => apiKeys.apiKeyId, {onDelete: "cascade"}), + .references(() => apiKeys.apiKeyId, { onDelete: "cascade" }), actionId: text("actionId") .notNull() - .references(() => actions.actionId, {onDelete: "cascade"}) + .references(() => actions.actionId, { onDelete: "cascade" }) }); export const apiKeyOrg = sqliteTable("apiKeyOrg", { apiKeyId: text("apiKeyId") .notNull() - .references(() => apiKeys.apiKeyId, {onDelete: "cascade"}), + .references(() => apiKeys.apiKeyId, { onDelete: "cascade" }), orgId: text("orgId") .references(() => orgs.orgId, { onDelete: "cascade" @@ -826,10 +839,10 @@ export const apiKeyOrg = sqliteTable("apiKeyOrg", { export const idpOrg = sqliteTable("idpOrg", { idpId: integer("idpId") .notNull() - .references(() => idp.idpId, {onDelete: "cascade"}), + .references(() => idp.idpId, { onDelete: "cascade" }), orgId: text("orgId") .notNull() - .references(() => orgs.orgId, {onDelete: "cascade"}), + .references(() => orgs.orgId, { onDelete: "cascade" }), roleMapping: text("roleMapping"), orgMapping: text("orgMapping") }); @@ -847,19 +860,19 @@ export const blueprints = sqliteTable("blueprints", { name: text("name").notNull(), source: text("source").notNull(), createdAt: integer("createdAt").notNull(), - succeeded: integer("succeeded", {mode: "boolean"}).notNull(), + succeeded: integer("succeeded", { mode: "boolean" }).notNull(), contents: text("contents").notNull(), message: text("message") }); export const requestAuditLog = sqliteTable( "requestAuditLog", { - id: integer("id").primaryKey({autoIncrement: true}), + id: integer("id").primaryKey({ autoIncrement: true }), timestamp: integer("timestamp").notNull(), // this is EPOCH time in seconds orgId: text("orgId").references(() => orgs.orgId, { onDelete: "cascade" }), - action: integer("action", {mode: "boolean"}).notNull(), + action: integer("action", { mode: "boolean" }).notNull(), reason: integer("reason").notNull(), actorType: text("actorType"), actor: text("actor"), @@ -876,7 +889,7 @@ export const requestAuditLog = sqliteTable( host: text("host"), path: text("path"), method: text("method"), - tls: integer("tls", {mode: "boolean"}) + tls: integer("tls", { mode: "boolean" }) }, (table) => [ index("idx_requestAuditLog_timestamp").on(table.timestamp), @@ -932,7 +945,9 @@ export type ResourceSession = InferSelectModel; export type ResourcePincode = InferSelectModel; export type ResourcePassword = InferSelectModel; export type ResourceHeaderAuth = InferSelectModel; -export type ResourceHeaderAuthExtendedCompatibility = InferSelectModel; +export type ResourceHeaderAuthExtendedCompatibility = InferSelectModel< + typeof resourceHeaderAuthExtendedCompatibility +>; export type ResourceOtp = InferSelectModel; export type ResourceAccessToken = InferSelectModel; export type ResourceWhitelist = InferSelectModel; diff --git a/server/lib/blueprints/MaintenanceSchema.ts b/server/lib/blueprints/MaintenanceSchema.ts index b686d0fc..b1e233bd 100644 --- a/server/lib/blueprints/MaintenanceSchema.ts +++ b/server/lib/blueprints/MaintenanceSchema.ts @@ -1,4 +1,3 @@ import { z } from "zod"; -export const MaintenanceSchema = z.object({ -}); +export const MaintenanceSchema = z.object({}); diff --git a/server/lib/blueprints/applyBlueprint.ts b/server/lib/blueprints/applyBlueprint.ts index a3f977ab..ac2f9508 100644 --- a/server/lib/blueprints/applyBlueprint.ts +++ b/server/lib/blueprints/applyBlueprint.ts @@ -1,4 +1,14 @@ -import { db, newts, blueprints, Blueprint, Site, siteResources, roleSiteResources, userSiteResources, clientSiteResources } from "@server/db"; +import { + db, + newts, + blueprints, + Blueprint, + Site, + siteResources, + roleSiteResources, + userSiteResources, + clientSiteResources +} from "@server/db"; import { Config, ConfigSchema } from "./types"; import { ProxyResourcesResults, updateProxyResources } from "./proxyResources"; import { fromError } from "zod-validation-error"; @@ -126,7 +136,7 @@ export async function applyBlueprint({ ) .then((rows) => rows.map((row) => row.roleId)); - const existingUserIds= await trx + const existingUserIds = await trx .select() .from(userSiteResources) .where( @@ -134,7 +144,8 @@ export async function applyBlueprint({ userSiteResources.siteResourceId, result.oldSiteResource.siteResourceId ) - ).then((rows) => rows.map((row) => row.userId)); + ) + .then((rows) => rows.map((row) => row.userId)); const existingClientIds = await trx .select() @@ -144,13 +155,19 @@ export async function applyBlueprint({ clientSiteResources.siteResourceId, result.oldSiteResource.siteResourceId ) - ).then((rows) => rows.map((row) => row.clientId)); + ) + .then((rows) => rows.map((row) => row.clientId)); // delete the existing site resource await trx .delete(siteResources) .where( - and(eq(siteResources.siteResourceId, result.oldSiteResource.siteResourceId)) + and( + eq( + siteResources.siteResourceId, + result.oldSiteResource.siteResourceId + ) + ) ); await rebuildClientAssociationsFromSiteResource( @@ -161,7 +178,7 @@ export async function applyBlueprint({ const [insertedSiteResource] = await trx .insert(siteResources) .values({ - ...result.newSiteResource, + ...result.newSiteResource }) .returning(); @@ -172,18 +189,20 @@ export async function applyBlueprint({ if (existingRoleIds.length > 0) { await trx.insert(roleSiteResources).values( - existingRoleIds.map((roleId) => ({ + existingRoleIds.map((roleId) => ({ roleId, - siteResourceId: insertedSiteResource!.siteResourceId + siteResourceId: + insertedSiteResource!.siteResourceId })) ); } if (existingUserIds.length > 0) { await trx.insert(userSiteResources).values( - existingUserIds.map((userId) => ({ + existingUserIds.map((userId) => ({ userId, - siteResourceId: insertedSiteResource!.siteResourceId + siteResourceId: + insertedSiteResource!.siteResourceId })) ); } @@ -192,7 +211,8 @@ export async function applyBlueprint({ await trx.insert(clientSiteResources).values( existingClientIds.map((clientId) => ({ clientId, - siteResourceId: insertedSiteResource!.siteResourceId + siteResourceId: + insertedSiteResource!.siteResourceId })) ); } @@ -201,7 +221,6 @@ export async function applyBlueprint({ insertedSiteResource, trx ); - } else { const [newSite] = await trx .select() diff --git a/server/lib/blueprints/types.ts b/server/lib/blueprints/types.ts index f169e18a..cbd2553f 100644 --- a/server/lib/blueprints/types.ts +++ b/server/lib/blueprints/types.ts @@ -54,11 +54,13 @@ export const AuthSchema = z.object({ // pincode has to have 6 digits pincode: z.number().min(100000).max(999999).optional(), password: z.string().min(1).optional(), - "basic-auth": z.object({ - user: z.string().min(1), - password: z.string().min(1), - extendedCompatibility: z.boolean().default(true) - }).optional(), + "basic-auth": z + .object({ + user: z.string().min(1), + password: z.string().min(1), + extendedCompatibility: z.boolean().default(true) + }) + .optional(), "sso-enabled": z.boolean().optional().default(false), "sso-roles": z .array(z.string()) diff --git a/server/lib/ip.ts b/server/lib/ip.ts index 87a0c3c6..280939f2 100644 --- a/server/lib/ip.ts +++ b/server/lib/ip.ts @@ -318,10 +318,7 @@ export function doCidrsOverlap(cidr1: string, cidr2: string): boolean { const range2 = cidrToRange(cidr2); // Overlap if the ranges intersect - return ( - range1.start <= range2.end && - range2.start <= range1.end - ); + return range1.start <= range2.end && range2.start <= range1.end; } export async function getNextAvailableClientSubnet( diff --git a/server/lib/readConfigFile.ts b/server/lib/readConfigFile.ts index b57a185d..da567820 100644 --- a/server/lib/readConfigFile.ts +++ b/server/lib/readConfigFile.ts @@ -216,7 +216,10 @@ export const configSchema = z .default(["newt", "wireguard", "local"]), allow_raw_resources: z.boolean().optional().default(true), file_mode: z.boolean().optional().default(false), - pp_transport_prefix: z.string().optional().default("pp-transport-v") + pp_transport_prefix: z + .string() + .optional() + .default("pp-transport-v") }) .optional() .prefault({}), diff --git a/server/lib/traefik/getTraefikConfig.ts b/server/lib/traefik/getTraefikConfig.ts index 484eaaf5..e5bf3881 100644 --- a/server/lib/traefik/getTraefikConfig.ts +++ b/server/lib/traefik/getTraefikConfig.ts @@ -294,12 +294,12 @@ export async function getTraefikConfig( certResolver: resolverName, ...(preferWildcard ? { - domains: [ - { - main: wildCard - } - ] - } + domains: [ + { + main: wildCard + } + ] + } : {}) }; @@ -475,9 +475,9 @@ export async function getTraefikConfig( // RECEIVE BANDWIDTH ENDPOINT. // TODO: HOW TO HANDLE ^^^^^^ BETTER - const anySitesOnline = ( - targets - ).some((target) => target.site.online); + const anySitesOnline = targets.some( + (target) => target.site.online + ); return ( targets @@ -544,14 +544,14 @@ export async function getTraefikConfig( })(), ...(resource.stickySession ? { - sticky: { - cookie: { - name: "p_sticky", // TODO: make this configurable via config.yml like other cookies - secure: resource.ssl, - httpOnly: true - } - } - } + sticky: { + cookie: { + name: "p_sticky", // TODO: make this configurable via config.yml like other cookies + secure: resource.ssl, + httpOnly: true + } + } + } : {}) } }; @@ -603,9 +603,9 @@ export async function getTraefikConfig( loadBalancer: { servers: (() => { // Check if any sites are online - const anySitesOnline = ( - targets - ).some((target) => target.site.online); + const anySitesOnline = targets.some( + (target) => target.site.online + ); return targets .filter((target) => { @@ -654,18 +654,18 @@ export async function getTraefikConfig( })(), ...(resource.proxyProtocol && protocol == "tcp" ? { - serversTransport: `${ppPrefix}${resource.proxyProtocolVersion || 1}@file` // TODO: does @file here cause issues? - } + serversTransport: `${ppPrefix}${resource.proxyProtocolVersion || 1}@file` // TODO: does @file here cause issues? + } : {}), ...(resource.stickySession ? { - sticky: { - ipStrategy: { - depth: 0, - sourcePort: true - } - } - } + sticky: { + ipStrategy: { + depth: 0, + sourcePort: true + } + } + } : {}) } }; diff --git a/server/private/lib/traefik/getTraefikConfig.ts b/server/private/lib/traefik/getTraefikConfig.ts index 99e5b39c..bb3fd2c5 100644 --- a/server/private/lib/traefik/getTraefikConfig.ts +++ b/server/private/lib/traefik/getTraefikConfig.ts @@ -73,7 +73,6 @@ export async function getTraefikConfig( generateLoginPageRouters = false, allowRawResources = true ): Promise { - // Get resources with their targets and sites in a single optimized query // Start from sites on this exit node, then join to targets and resources const resourcesWithTargetsAndSites = await db @@ -435,17 +434,15 @@ export async function getTraefikConfig( } } - const availableServers = targets.filter( - (target) => { - if (!target.enabled) return false; + const availableServers = targets.filter((target) => { + if (!target.enabled) return false; - if (!target.site.online) return false; + if (!target.site.online) return false; - if (target.health == "unhealthy") return false; + if (target.health == "unhealthy") return false; - return true; - } - ); + return true; + }); const hasHealthyServers = availableServers.length > 0; @@ -794,9 +791,9 @@ export async function getTraefikConfig( loadBalancer: { servers: (() => { // Check if any sites are online - const anySitesOnline = ( - targets - ).some((target) => target.site.online); + const anySitesOnline = targets.some( + (target) => target.site.online + ); return targets .filter((target) => { diff --git a/server/private/routers/hybrid.ts b/server/private/routers/hybrid.ts index a6a00645..14ed1b8b 100644 --- a/server/private/routers/hybrid.ts +++ b/server/private/routers/hybrid.ts @@ -39,7 +39,7 @@ import { resourceHeaderAuthExtendedCompatibility, ResourceHeaderAuthExtendedCompatibility, orgs, - requestAuditLog, + requestAuditLog } from "@server/db"; import { resources, @@ -503,7 +503,10 @@ hybridRouter.get( ) .leftJoin( resourceHeaderAuthExtendedCompatibility, - eq(resourceHeaderAuthExtendedCompatibility.resourceId, resources.resourceId) + eq( + resourceHeaderAuthExtendedCompatibility.resourceId, + resources.resourceId + ) ) .where(eq(resources.fullDomain, domain)) .limit(1); @@ -538,7 +541,8 @@ hybridRouter.get( pincode: result.resourcePincode, password: result.resourcePassword, headerAuth: result.resourceHeaderAuth, - headerAuthExtendedCompatibility: result.resourceHeaderAuthExtendedCompatibility + headerAuthExtendedCompatibility: + result.resourceHeaderAuthExtendedCompatibility }; return response(res, { diff --git a/server/private/routers/internal.ts b/server/private/routers/internal.ts index eedd3f50..b599d662 100644 --- a/server/private/routers/internal.ts +++ b/server/private/routers/internal.ts @@ -39,4 +39,4 @@ internalRouter.post( internalRouter.get(`/license/status`, license.getLicenseStatus); -internalRouter.get("/maintenance/info", resource.getMaintenanceInfo); \ No newline at end of file +internalRouter.get("/maintenance/info", resource.getMaintenanceInfo); diff --git a/server/private/routers/resource/index.ts b/server/private/routers/resource/index.ts index 523b0ce1..f82b5552 100644 --- a/server/private/routers/resource/index.ts +++ b/server/private/routers/resource/index.ts @@ -11,4 +11,4 @@ * This file is not licensed under the AGPLv3. */ -export * from "./getMaintenanceInfo"; \ No newline at end of file +export * from "./getMaintenanceInfo"; diff --git a/server/routers/auditLogs/queryRequestAnalytics.ts b/server/routers/auditLogs/queryRequestAnalytics.ts index fe3a4c4f..a6f9cb76 100644 --- a/server/routers/auditLogs/queryRequestAnalytics.ts +++ b/server/routers/auditLogs/queryRequestAnalytics.ts @@ -99,7 +99,7 @@ async function query(query: Q) { .where(and(baseConditions, not(isNull(requestAuditLog.location)))) .groupBy(requestAuditLog.location) .orderBy(desc(totalQ)) - .limit(DISTINCT_LIMIT+1); + .limit(DISTINCT_LIMIT + 1); if (requestsPerCountry.length > DISTINCT_LIMIT) { // throw an error diff --git a/server/routers/auditLogs/queryRequestAuditLog.ts b/server/routers/auditLogs/queryRequestAuditLog.ts index 0513feb2..98c23721 100644 --- a/server/routers/auditLogs/queryRequestAuditLog.ts +++ b/server/routers/auditLogs/queryRequestAuditLog.ts @@ -189,22 +189,22 @@ async function queryUniqueFilterAttributes( .selectDistinct({ actor: requestAuditLog.actor }) .from(requestAuditLog) .where(baseConditions) - .limit(DISTINCT_LIMIT+1), + .limit(DISTINCT_LIMIT + 1), primaryDb .selectDistinct({ locations: requestAuditLog.location }) .from(requestAuditLog) .where(baseConditions) - .limit(DISTINCT_LIMIT+1), + .limit(DISTINCT_LIMIT + 1), primaryDb .selectDistinct({ hosts: requestAuditLog.host }) .from(requestAuditLog) .where(baseConditions) - .limit(DISTINCT_LIMIT+1), + .limit(DISTINCT_LIMIT + 1), primaryDb .selectDistinct({ paths: requestAuditLog.path }) .from(requestAuditLog) .where(baseConditions) - .limit(DISTINCT_LIMIT+1), + .limit(DISTINCT_LIMIT + 1), primaryDb .selectDistinct({ id: requestAuditLog.resourceId, @@ -216,7 +216,7 @@ async function queryUniqueFilterAttributes( eq(requestAuditLog.resourceId, resources.resourceId) ) .where(baseConditions) - .limit(DISTINCT_LIMIT+1) + .limit(DISTINCT_LIMIT + 1) ]); // TODO: for stuff like the paths this is too restrictive so lets just show some of the paths and the user needs to @@ -309,10 +309,12 @@ export async function queryRequestAuditLogs( } catch (error) { logger.error(error); // if the message is "Too many distinct filter attributes to retrieve. Please refine your time range.", return a 400 and the message - if (error instanceof Error && error.message === "Too many distinct filter attributes to retrieve. Please refine your time range.") { - return next( - createHttpError(HttpCode.BAD_REQUEST, error.message) - ); + if ( + error instanceof Error && + error.message === + "Too many distinct filter attributes to retrieve. Please refine your time range." + ) { + return next(createHttpError(HttpCode.BAD_REQUEST, error.message)); } return next( createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred") diff --git a/server/routers/gerbil/getConfig.ts b/server/routers/gerbil/getConfig.ts index 488ef75b..1557edce 100644 --- a/server/routers/gerbil/getConfig.ts +++ b/server/routers/gerbil/getConfig.ts @@ -52,7 +52,7 @@ export async function getConfig( } // clean up the public key - keep only valid base64 characters (A-Z, a-z, 0-9, +, /, =) - const cleanedPublicKey = publicKey.replace(/[^A-Za-z0-9+/=]/g, ''); + const cleanedPublicKey = publicKey.replace(/[^A-Za-z0-9+/=]/g, ""); const exitNode = await createExitNode(cleanedPublicKey, reachableAt); diff --git a/server/routers/integration.ts b/server/routers/integration.ts index f66494a0..4250458a 100644 --- a/server/routers/integration.ts +++ b/server/routers/integration.ts @@ -858,7 +858,6 @@ authenticated.put( blueprints.applyJSONBlueprint ); - authenticated.get( "/org/:orgId/blueprint/:blueprintId", verifyApiKeyOrgAccess, @@ -866,7 +865,6 @@ authenticated.get( blueprints.getBlueprint ); - authenticated.get( "/org/:orgId/blueprints", verifyApiKeyOrgAccess, diff --git a/server/routers/org/pickOrgDefaults.ts b/server/routers/org/pickOrgDefaults.ts index cce46a01..e4b9f2b2 100644 --- a/server/routers/org/pickOrgDefaults.ts +++ b/server/routers/org/pickOrgDefaults.ts @@ -21,8 +21,7 @@ export async function pickOrgDefaults( // const subnet = await getNextAvailableOrgSubnet(); // Just hard code the subnet for now for everyone const subnet = config.getRawConfig().orgs.subnet_group; - const utilitySubnet = - config.getRawConfig().orgs.utility_subnet_group; + const utilitySubnet = config.getRawConfig().orgs.utility_subnet_group; return response(res, { data: { diff --git a/server/routers/org/updateOrg.ts b/server/routers/org/updateOrg.ts index cdf6aa73..844ca200 100644 --- a/server/routers/org/updateOrg.ts +++ b/server/routers/org/updateOrg.ts @@ -154,4 +154,4 @@ export async function updateOrg( createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred") ); } -} \ No newline at end of file +} diff --git a/server/routers/resource/getResourceAuthInfo.ts b/server/routers/resource/getResourceAuthInfo.ts index 5602a909..7959bff5 100644 --- a/server/routers/resource/getResourceAuthInfo.ts +++ b/server/routers/resource/getResourceAuthInfo.ts @@ -1,19 +1,20 @@ -import {Request, Response, NextFunction} from "express"; -import {z} from "zod"; +import { Request, Response, NextFunction } from "express"; +import { z } from "zod"; import { db, - resourceHeaderAuth, resourceHeaderAuthExtendedCompatibility, + resourceHeaderAuth, + resourceHeaderAuthExtendedCompatibility, resourcePassword, resourcePincode, resources } from "@server/db"; -import {eq} from "drizzle-orm"; +import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; -import {fromError} from "zod-validation-error"; +import { fromError } from "zod-validation-error"; import logger from "@server/logger"; -import {build} from "@server/build"; +import { build } from "@server/build"; const getResourceAuthInfoSchema = z.strictObject({ resourceGuid: z.string() @@ -52,68 +53,68 @@ export async function getResourceAuthInfo( ); } - const {resourceGuid} = parsedParams.data; + const { resourceGuid } = parsedParams.data; const isGuidInteger = /^\d+$/.test(resourceGuid); const [result] = isGuidInteger && build === "saas" ? await db - .select() - .from(resources) - .leftJoin( - resourcePincode, - eq(resourcePincode.resourceId, resources.resourceId) - ) - .leftJoin( - resourcePassword, - eq(resourcePassword.resourceId, resources.resourceId) - ) + .select() + .from(resources) + .leftJoin( + resourcePincode, + eq(resourcePincode.resourceId, resources.resourceId) + ) + .leftJoin( + resourcePassword, + eq(resourcePassword.resourceId, resources.resourceId) + ) - .leftJoin( - resourceHeaderAuth, - eq( - resourceHeaderAuth.resourceId, - resources.resourceId - ) - ) - .leftJoin( - resourceHeaderAuthExtendedCompatibility, - eq( - resourceHeaderAuthExtendedCompatibility.resourceId, - resources.resourceId - ) - ) - .where(eq(resources.resourceId, Number(resourceGuid))) - .limit(1) + .leftJoin( + resourceHeaderAuth, + eq( + resourceHeaderAuth.resourceId, + resources.resourceId + ) + ) + .leftJoin( + resourceHeaderAuthExtendedCompatibility, + eq( + resourceHeaderAuthExtendedCompatibility.resourceId, + resources.resourceId + ) + ) + .where(eq(resources.resourceId, Number(resourceGuid))) + .limit(1) : await db - .select() - .from(resources) - .leftJoin( - resourcePincode, - eq(resourcePincode.resourceId, resources.resourceId) - ) - .leftJoin( - resourcePassword, - eq(resourcePassword.resourceId, resources.resourceId) - ) + .select() + .from(resources) + .leftJoin( + resourcePincode, + eq(resourcePincode.resourceId, resources.resourceId) + ) + .leftJoin( + resourcePassword, + eq(resourcePassword.resourceId, resources.resourceId) + ) - .leftJoin( - resourceHeaderAuth, - eq( - resourceHeaderAuth.resourceId, - resources.resourceId - ) - ) - .leftJoin( - resourceHeaderAuthExtendedCompatibility, - eq( - resourceHeaderAuthExtendedCompatibility.resourceId, - resources.resourceId - ) - ) - .where(eq(resources.resourceGuid, resourceGuid)) - .limit(1); + .leftJoin( + resourceHeaderAuth, + eq( + resourceHeaderAuth.resourceId, + resources.resourceId + ) + ) + .leftJoin( + resourceHeaderAuthExtendedCompatibility, + eq( + resourceHeaderAuthExtendedCompatibility.resourceId, + resources.resourceId + ) + ) + .where(eq(resources.resourceGuid, resourceGuid)) + .limit(1); const resource = result?.resources; if (!resource) { @@ -125,7 +126,8 @@ export async function getResourceAuthInfo( const pincode = result?.resourcePincode; const password = result?.resourcePassword; const headerAuth = result?.resourceHeaderAuth; - const headerAuthExtendedCompatibility = result?.resourceHeaderAuthExtendedCompatibility; + const headerAuthExtendedCompatibility = + result?.resourceHeaderAuthExtendedCompatibility; const url = `${resource.ssl ? "https" : "http"}://${resource.fullDomain}`; @@ -138,7 +140,8 @@ export async function getResourceAuthInfo( password: password !== null, pincode: pincode !== null, headerAuth: headerAuth !== null, - headerAuthExtendedCompatibility: headerAuthExtendedCompatibility !== null, + headerAuthExtendedCompatibility: + headerAuthExtendedCompatibility !== null, sso: resource.sso, blockAccess: resource.blockAccess, url, diff --git a/server/routers/resource/listResources.ts b/server/routers/resource/listResources.ts index da62eec3..c17e65a4 100644 --- a/server/routers/resource/listResources.ts +++ b/server/routers/resource/listResources.ts @@ -1,6 +1,10 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; -import {db, resourceHeaderAuth, resourceHeaderAuthExtendedCompatibility} from "@server/db"; +import { + db, + resourceHeaderAuth, + resourceHeaderAuthExtendedCompatibility +} from "@server/db"; import { resources, userResources, @@ -109,7 +113,8 @@ function queryResources(accessibleResourceIds: number[], orgId: string) { domainId: resources.domainId, niceId: resources.niceId, headerAuthId: resourceHeaderAuth.headerAuthId, - headerAuthExtendedCompatibilityId: resourceHeaderAuthExtendedCompatibility.headerAuthExtendedCompatibilityId, + headerAuthExtendedCompatibilityId: + resourceHeaderAuthExtendedCompatibility.headerAuthExtendedCompatibilityId, targetId: targets.targetId, targetIp: targets.ip, targetPort: targets.port, @@ -133,7 +138,10 @@ function queryResources(accessibleResourceIds: number[], orgId: string) { ) .leftJoin( resourceHeaderAuthExtendedCompatibility, - eq(resourceHeaderAuthExtendedCompatibility.resourceId, resources.resourceId) + eq( + resourceHeaderAuthExtendedCompatibility.resourceId, + resources.resourceId + ) ) .leftJoin(targets, eq(targets.resourceId, resources.resourceId)) .leftJoin( diff --git a/server/routers/resource/setResourceHeaderAuth.ts b/server/routers/resource/setResourceHeaderAuth.ts index 6c866578..edd911cb 100644 --- a/server/routers/resource/setResourceHeaderAuth.ts +++ b/server/routers/resource/setResourceHeaderAuth.ts @@ -1,14 +1,18 @@ -import {Request, Response, NextFunction} from "express"; -import {z} from "zod"; -import {db, resourceHeaderAuth, resourceHeaderAuthExtendedCompatibility} from "@server/db"; -import {eq} from "drizzle-orm"; +import { Request, Response, NextFunction } from "express"; +import { z } from "zod"; +import { + db, + resourceHeaderAuth, + resourceHeaderAuthExtendedCompatibility +} from "@server/db"; +import { eq } from "drizzle-orm"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; -import {fromError} from "zod-validation-error"; -import {response} from "@server/lib/response"; +import { fromError } from "zod-validation-error"; +import { response } from "@server/lib/response"; import logger from "@server/logger"; -import {hashPassword} from "@server/auth/password"; -import {OpenAPITags, registry} from "@server/openApi"; +import { hashPassword } from "@server/auth/password"; +import { OpenAPITags, registry } from "@server/openApi"; const setResourceAuthMethodsParamsSchema = z.object({ resourceId: z.string().transform(Number).pipe(z.int().positive()) @@ -67,29 +71,40 @@ export async function setResourceHeaderAuth( ); } - const {resourceId} = parsedParams.data; - const {user, password, extendedCompatibility} = parsedBody.data; + const { resourceId } = parsedParams.data; + const { user, password, extendedCompatibility } = parsedBody.data; await db.transaction(async (trx) => { await trx .delete(resourceHeaderAuth) .where(eq(resourceHeaderAuth.resourceId, resourceId)); - await trx.delete(resourceHeaderAuthExtendedCompatibility).where(eq(resourceHeaderAuthExtendedCompatibility.resourceId, resourceId)); + await trx + .delete(resourceHeaderAuthExtendedCompatibility) + .where( + eq( + resourceHeaderAuthExtendedCompatibility.resourceId, + resourceId + ) + ); if (user && password && extendedCompatibility !== null) { - const headerAuthHash = await hashPassword(Buffer.from(`${user}:${password}`).toString("base64")); + const headerAuthHash = await hashPassword( + Buffer.from(`${user}:${password}`).toString("base64") + ); await Promise.all([ trx .insert(resourceHeaderAuth) - .values({resourceId, headerAuthHash}), + .values({ resourceId, headerAuthHash }), trx .insert(resourceHeaderAuthExtendedCompatibility) - .values({resourceId, extendedCompatibilityIsActivated: extendedCompatibility}) + .values({ + resourceId, + extendedCompatibilityIsActivated: + extendedCompatibility + }) ]); } - - }); return response(res, { diff --git a/server/routers/resource/types.ts b/server/routers/resource/types.ts index acdfbc60..9dcdcd08 100644 --- a/server/routers/resource/types.ts +++ b/server/routers/resource/types.ts @@ -7,4 +7,4 @@ export type GetMaintenanceInfoResponse = { maintenanceTitle: string | null; maintenanceMessage: string | null; maintenanceEstimatedTime: string | null; -} \ No newline at end of file +}; diff --git a/server/routers/resource/updateResource.ts b/server/routers/resource/updateResource.ts index b25b69cb..80b7a00a 100644 --- a/server/routers/resource/updateResource.ts +++ b/server/routers/resource/updateResource.ts @@ -343,7 +343,9 @@ async function updateHttpResource( const isLicensed = await isLicensedOrSubscribed(resource.orgId); if (build == "enterprise" && !isLicensed) { - logger.warn("Server is not licensed! Clearing set maintenance screen values"); + logger.warn( + "Server is not licensed! Clearing set maintenance screen values" + ); // null the maintenance mode fields if not licensed updateData.maintenanceModeEnabled = undefined; updateData.maintenanceModeType = undefined; diff --git a/server/routers/siteResource/createSiteResource.ts b/server/routers/siteResource/createSiteResource.ts index d2196e87..b6140c27 100644 --- a/server/routers/siteResource/createSiteResource.ts +++ b/server/routers/siteResource/createSiteResource.ts @@ -11,7 +11,11 @@ import { userSiteResources } from "@server/db"; import { getUniqueSiteResourceName } from "@server/db/names"; -import { getNextAvailableAliasAddress, isIpInCidr, portRangeStringSchema } from "@server/lib/ip"; +import { + getNextAvailableAliasAddress, + isIpInCidr, + portRangeStringSchema +} from "@server/lib/ip"; import { rebuildClientAssociationsFromSiteResource } from "@server/lib/rebuildClientAssociations"; import response from "@server/lib/response"; import logger from "@server/logger"; @@ -69,7 +73,10 @@ const createSiteResourceSchema = z const domainRegex = /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/; const isValidDomain = domainRegex.test(data.destination); - const isValidAlias = data.alias !== undefined && data.alias !== null && data.alias.trim() !== ""; + const isValidAlias = + data.alias !== undefined && + data.alias !== null && + data.alias.trim() !== ""; return isValidDomain && isValidAlias; // require the alias to be set in the case of domain } @@ -182,7 +189,9 @@ export async function createSiteResource( .limit(1); if (!org) { - return next(createHttpError(HttpCode.NOT_FOUND, "Organization not found")); + return next( + createHttpError(HttpCode.NOT_FOUND, "Organization not found") + ); } if (!org.subnet || !org.utilitySubnet) { @@ -195,10 +204,13 @@ export async function createSiteResource( } // Only check if destination is an IP address - const isIp = z.union([z.ipv4(), z.ipv6()]).safeParse(destination).success; + const isIp = z + .union([z.ipv4(), z.ipv6()]) + .safeParse(destination).success; if ( isIp && - (isIpInCidr(destination, org.subnet) || isIpInCidr(destination, org.utilitySubnet)) + (isIpInCidr(destination, org.subnet) || + isIpInCidr(destination, org.utilitySubnet)) ) { return next( createHttpError( diff --git a/server/routers/siteResource/deleteSiteResource.ts b/server/routers/siteResource/deleteSiteResource.ts index 0abc7d73..336c5080 100644 --- a/server/routers/siteResource/deleteSiteResource.ts +++ b/server/routers/siteResource/deleteSiteResource.ts @@ -88,9 +88,7 @@ export async function deleteSiteResource( ); }); - logger.info( - `Deleted site resource ${siteResourceId}` - ); + logger.info(`Deleted site resource ${siteResourceId}`); return response(res, { data: { message: "Site resource deleted successfully" }, diff --git a/server/routers/siteResource/updateSiteResource.ts b/server/routers/siteResource/updateSiteResource.ts index c0383616..fd77c74a 100644 --- a/server/routers/siteResource/updateSiteResource.ts +++ b/server/routers/siteResource/updateSiteResource.ts @@ -204,7 +204,9 @@ export async function updateSiteResource( .limit(1); if (!org) { - return next(createHttpError(HttpCode.NOT_FOUND, "Organization not found")); + return next( + createHttpError(HttpCode.NOT_FOUND, "Organization not found") + ); } if (!org.subnet || !org.utilitySubnet) { @@ -217,10 +219,13 @@ export async function updateSiteResource( } // Only check if destination is an IP address - const isIp = z.union([z.ipv4(), z.ipv6()]).safeParse(destination).success; + const isIp = z + .union([z.ipv4(), z.ipv6()]) + .safeParse(destination).success; if ( isIp && - (isIpInCidr(destination!, org.subnet) || isIpInCidr(destination!, org.utilitySubnet)) + (isIpInCidr(destination!, org.subnet) || + isIpInCidr(destination!, org.utilitySubnet)) ) { return next( createHttpError( @@ -295,7 +300,7 @@ export async function updateSiteResource( const [insertedSiteResource] = await trx .insert(siteResources) .values({ - ...existingSiteResource, + ...existingSiteResource }) .returning(); @@ -517,9 +522,14 @@ export async function handleMessagingForUpdatedSiteResource( site: { siteId: number; orgId: string }, trx: Transaction ) { - - logger.debug("handleMessagingForUpdatedSiteResource: existingSiteResource is: ", existingSiteResource); - logger.debug("handleMessagingForUpdatedSiteResource: updatedSiteResource is: ", updatedSiteResource); + logger.debug( + "handleMessagingForUpdatedSiteResource: existingSiteResource is: ", + existingSiteResource + ); + logger.debug( + "handleMessagingForUpdatedSiteResource: updatedSiteResource is: ", + updatedSiteResource + ); const { mergedAllClients } = await rebuildClientAssociationsFromSiteResource( diff --git a/src/app/[orgId]/settings/general/layout.tsx b/src/app/[orgId]/settings/general/layout.tsx index 31c67966..3ed9f0b2 100644 --- a/src/app/[orgId]/settings/general/layout.tsx +++ b/src/app/[orgId]/settings/general/layout.tsx @@ -71,7 +71,9 @@ export default async function GeneralSettingsPage({
- {children} + + {children} +
diff --git a/src/app/[orgId]/settings/resources/client/page.tsx b/src/app/[orgId]/settings/resources/client/page.tsx index dfe61ef7..c87caec3 100644 --- a/src/app/[orgId]/settings/resources/client/page.tsx +++ b/src/app/[orgId]/settings/resources/client/page.tsx @@ -71,7 +71,7 @@ export default async function ClientResourcesPage( niceId: siteResource.niceId, tcpPortRangeString: siteResource.tcpPortRangeString || null, udpPortRangeString: siteResource.udpPortRangeString || null, - disableIcmp: siteResource.disableIcmp || false, + disableIcmp: siteResource.disableIcmp || false }; } ); diff --git a/src/app/[orgId]/settings/resources/proxy/[niceId]/authentication/page.tsx b/src/app/[orgId]/settings/resources/proxy/[niceId]/authentication/page.tsx index 08065dfc..968b2700 100644 --- a/src/app/[orgId]/settings/resources/proxy/[niceId]/authentication/page.tsx +++ b/src/app/[orgId]/settings/resources/proxy/[niceId]/authentication/page.tsx @@ -240,13 +240,7 @@ export default function ResourceAuthenticationPage() { })) ); hasInitializedRef.current = true; - }, [ - pageLoading, - resourceRoles, - resourceUsers, - whitelist, - orgIdps - ]); + }, [pageLoading, resourceRoles, resourceUsers, whitelist, orgIdps]); const [, submitUserRolesForm, loadingSaveUsersRoles] = useActionState( onSubmitUsersRoles, @@ -602,9 +596,7 @@ export default function ResourceAuthenticationPage() { {ssoEnabled && allIdps.length > 0 && (
@@ -654,9 +655,7 @@ export default function ResourceRules(props: { - + No ASN found. Enter a custom ASN below. @@ -665,7 +664,9 @@ export default function ResourceRules(props: { {MAJOR_ASNS.map((asn) => ( { updateRule( row.original.ruleId, @@ -1056,8 +1057,8 @@ export default function ResourceRules(props: { ) : addRuleForm.watch( - "match" - ) === "ASN" ? ( + "match" + ) === "ASN" ? ( - + - No ASN found. Use the custom input below. + No + ASN + found. + Use + the + custom + input + below. {MAJOR_ASNS.map( @@ -1112,7 +1119,9 @@ export default function ResourceRules(props: { asn.code } value={ - asn.name + " " + asn.code + asn.name + + " " + + asn.code } onSelect={() => { field.onChange( @@ -1138,6 +1147,7 @@ export default function ResourceRules(props: { { asn.code } + ) ) @@ -1148,14 +1158,32 @@ export default function ResourceRules(props: {
{ - if (e.key === "Enter") { - const value = e.currentTarget.value - .toUpperCase() - .replace(/^AS/, ""); - if (/^\d+$/.test(value)) { - field.onChange("AS" + value); - setOpenAddRuleAsnSelect(false); + onKeyDown={( + e + ) => { + if ( + e.key === + "Enter" + ) { + const value = + e.currentTarget.value + .toUpperCase() + .replace( + /^AS/, + "" + ); + if ( + /^\d+$/.test( + value + ) + ) { + field.onChange( + "AS" + + value + ); + setOpenAddRuleAsnSelect( + false + ); } } }} diff --git a/src/app/[orgId]/settings/sites/create/page.tsx b/src/app/[orgId]/settings/sites/create/page.tsx index 780b3263..3a1140b3 100644 --- a/src/app/[orgId]/settings/sites/create/page.tsx +++ b/src/app/[orgId]/settings/sites/create/page.tsx @@ -756,7 +756,9 @@ WantedBy=default.target` render={({ field }) => ( - {t("siteAddress")} + {t( + "siteAddress" + )} { }; export default ClientDownloadBanner; - diff --git a/src/components/ClientResourcesTable.tsx b/src/components/ClientResourcesTable.tsx index 4cd02743..51b87427 100644 --- a/src/components/ClientResourcesTable.tsx +++ b/src/components/ClientResourcesTable.tsx @@ -99,14 +99,12 @@ export default function ClientResourcesTable({ siteId: number ) => { try { - await api - .delete(`/site-resource/${resourceId}`) - .then(() => { - startTransition(() => { - router.refresh(); - setIsDeleteModalOpen(false); - }); + await api.delete(`/site-resource/${resourceId}`).then(() => { + startTransition(() => { + router.refresh(); + setIsDeleteModalOpen(false); }); + }); } catch (e) { console.error(t("resourceErrorDelete"), e); toast({ diff --git a/src/components/CreateInternalResourceDialog.tsx b/src/components/CreateInternalResourceDialog.tsx index 74e936f6..2c9efdf5 100644 --- a/src/components/CreateInternalResourceDialog.tsx +++ b/src/components/CreateInternalResourceDialog.tsx @@ -87,7 +87,12 @@ const isValidPortRangeString = (val: string | undefined | null): boolean => { return false; } - if (startPort < 1 || startPort > 65535 || endPort < 1 || endPort > 65535) { + if ( + startPort < 1 || + startPort > 65535 || + endPort < 1 || + endPort > 65535 + ) { return false; } @@ -131,7 +136,10 @@ const getPortModeFromString = (val: string | undefined | null): PortMode => { }; // Helper to get the port string for API from mode and custom value -const getPortStringFromMode = (mode: PortMode, customValue: string): string | undefined => { +const getPortStringFromMode = ( + mode: PortMode, + customValue: string +): string | undefined => { if (mode === "all") return "*"; if (mode === "blocked") return ""; return customValue; @@ -1097,8 +1105,7 @@ export default function CreateInternalResourceDialog({ size="sm" tags={ form.getValues() - .roles || - [] + .roles || [] } setTags={( newRoles @@ -1154,8 +1161,7 @@ export default function CreateInternalResourceDialog({ )} tags={ form.getValues() - .users || - [] + .users || [] } size="sm" setTags={( @@ -1245,9 +1251,7 @@ export default function CreateInternalResourceDialog({ restrictTagsToAutocompleteOptions={ true } - sortTags={ - true - } + sortTags={true} /> diff --git a/src/components/DismissableBanner.tsx b/src/components/DismissableBanner.tsx index 6f49e036..9d8b246e 100644 --- a/src/components/DismissableBanner.tsx +++ b/src/components/DismissableBanner.tsx @@ -95,4 +95,3 @@ export const DismissableBanner = ({ }; export default DismissableBanner; - diff --git a/src/components/EditInternalResourceDialog.tsx b/src/components/EditInternalResourceDialog.tsx index 169f6554..64d29909 100644 --- a/src/components/EditInternalResourceDialog.tsx +++ b/src/components/EditInternalResourceDialog.tsx @@ -501,13 +501,19 @@ export default function EditInternalResourceDialog({ // ]); await queryClient.invalidateQueries( - resourceQueries.siteResourceRoles({ siteResourceId: resource.id }) + resourceQueries.siteResourceRoles({ + siteResourceId: resource.id + }) ); await queryClient.invalidateQueries( - resourceQueries.siteResourceUsers({ siteResourceId: resource.id }) + resourceQueries.siteResourceUsers({ + siteResourceId: resource.id + }) ); await queryClient.invalidateQueries( - resourceQueries.siteResourceClients({ siteResourceId: resource.id }) + resourceQueries.siteResourceClients({ + siteResourceId: resource.id + }) ); toast({ diff --git a/src/components/ExitNodesTable.tsx b/src/components/ExitNodesTable.tsx index 03aa671b..5c39f409 100644 --- a/src/components/ExitNodesTable.tsx +++ b/src/components/ExitNodesTable.tsx @@ -330,7 +330,7 @@ export default function ExitNodesTable({ isRefreshing={isRefreshing} columnVisibility={{ type: false, - address: false, + address: false }} enableColumnVisibility={true} /> diff --git a/src/components/LayoutSidebar.tsx b/src/components/LayoutSidebar.tsx index 00491983..75038d37 100644 --- a/src/components/LayoutSidebar.tsx +++ b/src/components/LayoutSidebar.tsx @@ -116,10 +116,12 @@ export function LayoutSidebar({ isCollapsed={isSidebarCollapsed} />
-
+
{!isAdminPage && user.serverAdmin && ( diff --git a/src/components/LoginForm.tsx b/src/components/LoginForm.tsx index ea6ce2ee..ce1f4dcb 100644 --- a/src/components/LoginForm.tsx +++ b/src/components/LoginForm.tsx @@ -120,7 +120,9 @@ export default function LoginForm({ const focusInput = () => { // Try using the ref first if (otpContainerRef.current) { - const hiddenInput = otpContainerRef.current.querySelector('input') as HTMLInputElement; + const hiddenInput = otpContainerRef.current.querySelector( + "input" + ) as HTMLInputElement; if (hiddenInput) { hiddenInput.focus(); return; @@ -128,17 +130,23 @@ export default function LoginForm({ } // Fallback: query the DOM - const otpContainer = document.querySelector('[data-slot="input-otp"]'); + const otpContainer = document.querySelector( + '[data-slot="input-otp"]' + ); if (!otpContainer) return; - const hiddenInput = otpContainer.querySelector('input') as HTMLInputElement; + const hiddenInput = otpContainer.querySelector( + "input" + ) as HTMLInputElement; if (hiddenInput) { hiddenInput.focus(); return; } // Last resort: click the first slot - const firstSlot = otpContainer.querySelector('[data-slot="input-otp-slot"]') as HTMLElement; + const firstSlot = otpContainer.querySelector( + '[data-slot="input-otp-slot"]' + ) as HTMLElement; if (firstSlot) { firstSlot.click(); } @@ -508,7 +516,10 @@ export default function LoginForm({ render={({ field }) => ( -
+
{ +export const MachineClientsBanner = ({ orgId }: MachineClientsBannerProps) => { const t = useTranslations(); return ( @@ -57,4 +55,3 @@ export const MachineClientsBanner = ({ }; export default MachineClientsBanner; - diff --git a/src/components/OrgInfoCard.tsx b/src/components/OrgInfoCard.tsx index cac8eb3f..f21a42c2 100644 --- a/src/components/OrgInfoCard.tsx +++ b/src/components/OrgInfoCard.tsx @@ -39,4 +39,3 @@ export default function OrgInfoCard({}: OrgInfoCardProps) { ); } - diff --git a/src/components/OrgLoginPage.tsx b/src/components/OrgLoginPage.tsx index 78b831bc..5efb2a04 100644 --- a/src/components/OrgLoginPage.tsx +++ b/src/components/OrgLoginPage.tsx @@ -119,4 +119,3 @@ export default async function OrgLoginPage({
); } - diff --git a/src/components/PrivateResourcesBanner.tsx b/src/components/PrivateResourcesBanner.tsx index 8320178d..935772b3 100644 --- a/src/components/PrivateResourcesBanner.tsx +++ b/src/components/PrivateResourcesBanner.tsx @@ -51,4 +51,3 @@ export const PrivateResourcesBanner = ({ }; export default PrivateResourcesBanner; - diff --git a/src/components/ProductUpdates.tsx b/src/components/ProductUpdates.tsx index 0b519b96..f8c4bf11 100644 --- a/src/components/ProductUpdates.tsx +++ b/src/components/ProductUpdates.tsx @@ -81,10 +81,10 @@ export default function ProductUpdates({ const showNewVersionPopup = Boolean( latestVersion && - valid(latestVersion) && - valid(currentVersion) && - ignoredVersionUpdate !== latestVersion && - gt(latestVersion, currentVersion) + valid(latestVersion) && + valid(currentVersion) && + ignoredVersionUpdate !== latestVersion && + gt(latestVersion, currentVersion) ); const filteredUpdates = data.updates.filter( diff --git a/src/components/ProxyResourcesBanner.tsx b/src/components/ProxyResourcesBanner.tsx index 40616758..4462f5a8 100644 --- a/src/components/ProxyResourcesBanner.tsx +++ b/src/components/ProxyResourcesBanner.tsx @@ -20,4 +20,3 @@ export const ProxyResourcesBanner = () => { }; export default ProxyResourcesBanner; - diff --git a/src/components/SetResourceHeaderAuthForm.tsx b/src/components/SetResourceHeaderAuthForm.tsx index 700509c0..40b5006d 100644 --- a/src/components/SetResourceHeaderAuthForm.tsx +++ b/src/components/SetResourceHeaderAuthForm.tsx @@ -1,6 +1,6 @@ "use client"; -import {Button} from "@app/components/ui/button"; +import { Button } from "@app/components/ui/button"; import { Form, FormControl, @@ -9,12 +9,12 @@ import { FormLabel, FormMessage } from "@app/components/ui/form"; -import {Input} from "@app/components/ui/input"; -import {toast} from "@app/hooks/useToast"; -import {zodResolver} from "@hookform/resolvers/zod"; -import {useEffect, useState} from "react"; -import {useForm} from "react-hook-form"; -import {z} from "zod"; +import { Input } from "@app/components/ui/input"; +import { toast } from "@app/hooks/useToast"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useEffect, useState } from "react"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; import { Credenza, CredenzaBody, @@ -25,14 +25,14 @@ import { CredenzaHeader, CredenzaTitle } from "@app/components/Credenza"; -import {formatAxiosError} from "@app/lib/api"; -import {AxiosResponse} from "axios"; -import {Resource} from "@server/db"; -import {createApiClient} from "@app/lib/api"; -import {useEnvContext} from "@app/hooks/useEnvContext"; -import {useTranslations} from "next-intl"; -import {SwitchInput} from "@/components/SwitchInput"; -import {InfoPopup} from "@/components/ui/info-popup"; +import { formatAxiosError } from "@app/lib/api"; +import { AxiosResponse } from "axios"; +import { Resource } from "@server/db"; +import { createApiClient } from "@app/lib/api"; +import { useEnvContext } from "@app/hooks/useEnvContext"; +import { useTranslations } from "next-intl"; +import { SwitchInput } from "@/components/SwitchInput"; +import { InfoPopup } from "@/components/ui/info-popup"; const setHeaderAuthFormSchema = z.object({ user: z.string().min(4).max(100), @@ -56,11 +56,11 @@ type SetHeaderAuthFormProps = { }; export default function SetResourceHeaderAuthForm({ - open, - setOpen, - resourceId, - onSetHeaderAuth - }: SetHeaderAuthFormProps) { + open, + setOpen, + resourceId, + onSetHeaderAuth +}: SetHeaderAuthFormProps) { const api = createApiClient(useEnvContext()); const t = useTranslations(); @@ -82,11 +82,14 @@ export default function SetResourceHeaderAuthForm({ async function onSubmit(data: SetHeaderAuthFormValues) { setLoading(true); - api.post>(`/resource/${resourceId}/header-auth`, { - user: data.user, - password: data.password, - extendedCompatibility: data.extendedCompatibility - }) + api.post>( + `/resource/${resourceId}/header-auth`, + { + user: data.user, + password: data.password, + extendedCompatibility: data.extendedCompatibility + } + ) .then(() => { toast({ title: t("resourceHeaderAuthSetup"), @@ -100,10 +103,10 @@ export default function SetResourceHeaderAuthForm({ .catch((e) => { toast({ variant: "destructive", - title: t('resourceErrorHeaderAuthSetup'), + title: t("resourceErrorHeaderAuthSetup"), description: formatAxiosError( e, - t('resourceErrorHeaderAuthSetupDescription') + t("resourceErrorHeaderAuthSetupDescription") ) }); }) @@ -139,7 +142,7 @@ export default function SetResourceHeaderAuthForm({ ( + render={({ field }) => ( {t("user")} @@ -149,14 +152,14 @@ export default function SetResourceHeaderAuthForm({ {...field} /> - + )} /> ( + render={({ field }) => ( {t("password")} @@ -168,25 +171,31 @@ export default function SetResourceHeaderAuthForm({ {...field} /> - + )} /> ( + render={({ field }) => ( - + )} /> diff --git a/src/components/SetResourcePasswordForm.tsx b/src/components/SetResourcePasswordForm.tsx index d0720527..68deb12c 100644 --- a/src/components/SetResourcePasswordForm.tsx +++ b/src/components/SetResourcePasswordForm.tsx @@ -91,10 +91,10 @@ export default function SetResourcePasswordForm({ .catch((e) => { toast({ variant: "destructive", - title: t('resourceErrorPasswordSetup'), + title: t("resourceErrorPasswordSetup"), description: formatAxiosError( e, - t('resourceErrorPasswordSetupDescription') + t("resourceErrorPasswordSetupDescription") ) }); }) diff --git a/src/components/SetResourcePincodeForm.tsx b/src/components/SetResourcePincodeForm.tsx index caae42b9..d6826adc 100644 --- a/src/components/SetResourcePincodeForm.tsx +++ b/src/components/SetResourcePincodeForm.tsx @@ -97,10 +97,10 @@ export default function SetResourcePincodeForm({ .catch((e) => { toast({ variant: "destructive", - title: t('resourceErrorPincodeSetup'), + title: t("resourceErrorPincodeSetup"), description: formatAxiosError( e, - t('resourceErrorPincodeSetupDescription') + t("resourceErrorPincodeSetupDescription") ) }); }) diff --git a/src/components/SitesBanner.tsx b/src/components/SitesBanner.tsx index 8ba7a232..9334b65e 100644 --- a/src/components/SitesBanner.tsx +++ b/src/components/SitesBanner.tsx @@ -37,4 +37,3 @@ export const SitesBanner = () => { }; export default SitesBanner; - diff --git a/src/components/SwitchInput.tsx b/src/components/SwitchInput.tsx index e76b5277..25fedb74 100644 --- a/src/components/SwitchInput.tsx +++ b/src/components/SwitchInput.tsx @@ -1,10 +1,14 @@ import React from "react"; -import {Switch} from "./ui/switch"; -import {Label} from "./ui/label"; -import {Button} from "@/components/ui/button"; -import {Info} from "lucide-react"; -import {info} from "winston"; -import {Popover, PopoverContent, PopoverTrigger} from "@/components/ui/popover"; +import { Switch } from "./ui/switch"; +import { Label } from "./ui/label"; +import { Button } from "@/components/ui/button"; +import { Info } from "lucide-react"; +import { info } from "winston"; +import { + Popover, + PopoverContent, + PopoverTrigger +} from "@/components/ui/popover"; interface SwitchComponentProps { id: string; @@ -18,22 +22,22 @@ interface SwitchComponentProps { } export function SwitchInput({ - id, - label, - description, - info, - disabled, - checked, - defaultChecked = false, - onCheckedChange - }: SwitchComponentProps) { + id, + label, + description, + info, + disabled, + checked, + defaultChecked = false, + onCheckedChange +}: SwitchComponentProps) { const defaultTrigger = ( ); @@ -49,18 +53,20 @@ export function SwitchInput({ disabled={disabled} /> {label && } - {info && - - {defaultTrigger} - - - {info && ( -

- {info} -

- )} -
-
} + {info && ( + + + {defaultTrigger} + + + {info && ( +

+ {info} +

+ )} +
+
+ )}
{description && ( diff --git a/src/components/private/AuthPageSettings.tsx b/src/components/private/AuthPageSettings.tsx index bd7c8db6..5d7a4cb2 100644 --- a/src/components/private/AuthPageSettings.tsx +++ b/src/components/private/AuthPageSettings.tsx @@ -276,14 +276,15 @@ function AuthPageSettings({ <> - {t("customDomain")} + + {t("customDomain")} + {t("authPageDescription")} -
diff --git a/src/components/private/IdpLoginButtons.tsx b/src/components/private/IdpLoginButtons.tsx index b855683a..7649bfde 100644 --- a/src/components/private/IdpLoginButtons.tsx +++ b/src/components/private/IdpLoginButtons.tsx @@ -58,12 +58,7 @@ export default function IdpLoginButtons({ let redirectToUrl: string | undefined; try { - console.log( - "generating", - idpId, - redirect || "/", - orgId - ); + console.log("generating", idpId, redirect || "/", orgId); const safeRedirect = cleanRedirect(redirect || "/"); const response = await generateOidcUrlProxy( idpId, diff --git a/src/components/ui/data-table.tsx b/src/components/ui/data-table.tsx index 36dec92b..d6339081 100644 --- a/src/components/ui/data-table.tsx +++ b/src/components/ui/data-table.tsx @@ -288,7 +288,10 @@ export function DataTable({ useEffect(() => { if (persistPageSize && pagination.pageSize !== pageSize) { // Only store if user has actually changed it from initial value - if (hasUserChangedPageSize.current && pagination.pageSize !== initialPageSize.current) { + if ( + hasUserChangedPageSize.current && + pagination.pageSize !== initialPageSize.current + ) { setStoredPageSize(pagination.pageSize, tableId); } setPageSize(pagination.pageSize); @@ -298,7 +301,9 @@ export function DataTable({ useEffect(() => { // Persist column visibility to localStorage when it changes (but not on initial mount) if (shouldPersistColumnVisibility) { - const hasChanged = JSON.stringify(columnVisibility) !== JSON.stringify(initialColumnVisibilityState.current); + const hasChanged = + JSON.stringify(columnVisibility) !== + JSON.stringify(initialColumnVisibilityState.current); if (hasChanged) { // Mark as user-initiated change and persist hasUserChangedColumnVisibility.current = true;