schema.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. import { InferSelectModel } from "drizzle-orm";
  2. import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
  3. export const orgs = sqliteTable("orgs", {
  4. orgId: text("orgId").primaryKey(),
  5. name: text("name").notNull(),
  6. domain: text("domain").notNull()
  7. });
  8. export const sites = sqliteTable("sites", {
  9. siteId: integer("siteId").primaryKey({ autoIncrement: true }),
  10. orgId: text("orgId")
  11. .references(() => orgs.orgId, {
  12. onDelete: "cascade"
  13. })
  14. .notNull(),
  15. niceId: text("niceId").notNull(),
  16. exitNodeId: integer("exitNode").references(() => exitNodes.exitNodeId, {
  17. onDelete: "set null"
  18. }),
  19. name: text("name").notNull(),
  20. pubKey: text("pubKey"),
  21. subnet: text("subnet").notNull(),
  22. megabytesIn: integer("bytesIn"),
  23. megabytesOut: integer("bytesOut"),
  24. lastBandwidthUpdate: text("lastBandwidthUpdate"),
  25. type: text("type").notNull(), // "newt" or "wireguard"
  26. online: integer("online", { mode: "boolean" }).notNull().default(false),
  27. // exit node stuff that is how to connect to the site when it has a gerbil
  28. address: text("address"), // this is the address of the wireguard interface in gerbil
  29. endpoint: text("endpoint"), // this is how to reach gerbil externally - gets put into the wireguard config
  30. publicKey: text("pubicKey"),
  31. listenPort: integer("listenPort")
  32. });
  33. export const resources = sqliteTable("resources", {
  34. resourceId: integer("resourceId").primaryKey({ autoIncrement: true }),
  35. siteId: integer("siteId")
  36. .references(() => sites.siteId, {
  37. onDelete: "cascade"
  38. })
  39. .notNull(),
  40. orgId: text("orgId")
  41. .references(() => orgs.orgId, {
  42. onDelete: "cascade"
  43. })
  44. .notNull(),
  45. name: text("name").notNull(),
  46. subdomain: text("subdomain"),
  47. fullDomain: text("fullDomain"),
  48. ssl: integer("ssl", { mode: "boolean" }).notNull().default(false),
  49. blockAccess: integer("blockAccess", { mode: "boolean" })
  50. .notNull()
  51. .default(false),
  52. sso: integer("sso", { mode: "boolean" }).notNull().default(true),
  53. http: integer("http", { mode: "boolean" }).notNull().default(true),
  54. protocol: text("protocol").notNull(),
  55. proxyPort: integer("proxyPort"),
  56. emailWhitelistEnabled: integer("emailWhitelistEnabled", { mode: "boolean" })
  57. .notNull()
  58. .default(false),
  59. isBaseDomain: integer("isBaseDomain", { mode: "boolean" }),
  60. applyRules: integer("applyRules", { mode: "boolean" }).notNull().default(false)
  61. });
  62. export const targets = sqliteTable("targets", {
  63. targetId: integer("targetId").primaryKey({ autoIncrement: true }),
  64. resourceId: integer("resourceId")
  65. .references(() => resources.resourceId, {
  66. onDelete: "cascade"
  67. })
  68. .notNull(),
  69. ip: text("ip").notNull(),
  70. method: text("method"),
  71. port: integer("port").notNull(),
  72. internalPort: integer("internalPort"),
  73. enabled: integer("enabled", { mode: "boolean" }).notNull().default(true)
  74. });
  75. export const exitNodes = sqliteTable("exitNodes", {
  76. exitNodeId: integer("exitNodeId").primaryKey({ autoIncrement: true }),
  77. name: text("name").notNull(),
  78. address: text("address").notNull(), // this is the address of the wireguard interface in gerbil
  79. endpoint: text("endpoint").notNull(), // this is how to reach gerbil externally - gets put into the wireguard config
  80. publicKey: text("pubicKey").notNull(),
  81. listenPort: integer("listenPort").notNull(),
  82. reachableAt: text("reachableAt") // this is the internal address of the gerbil http server for command control
  83. });
  84. export const users = sqliteTable("user", {
  85. userId: text("id").primaryKey(),
  86. email: text("email").notNull().unique(),
  87. passwordHash: text("passwordHash").notNull(),
  88. twoFactorEnabled: integer("twoFactorEnabled", { mode: "boolean" })
  89. .notNull()
  90. .default(false),
  91. twoFactorSecret: text("twoFactorSecret"),
  92. emailVerified: integer("emailVerified", { mode: "boolean" })
  93. .notNull()
  94. .default(false),
  95. dateCreated: text("dateCreated").notNull(),
  96. serverAdmin: integer("serverAdmin", { mode: "boolean" })
  97. .notNull()
  98. .default(false)
  99. });
  100. export const newts = sqliteTable("newt", {
  101. newtId: text("id").primaryKey(),
  102. secretHash: text("secretHash").notNull(),
  103. dateCreated: text("dateCreated").notNull(),
  104. siteId: integer("siteId").references(() => sites.siteId, {
  105. onDelete: "cascade"
  106. })
  107. });
  108. export const olms = sqliteTable("olms", {
  109. olmId: text("id").primaryKey(),
  110. secretHash: text("secretHash").notNull(),
  111. dateCreated: text("dateCreated").notNull(),
  112. siteId: integer("siteId").references(() => sites.siteId, {
  113. onDelete: "cascade"
  114. }),
  115. // wgstuff
  116. pubKey: text("pubKey"),
  117. subnet: text("subnet").notNull(),
  118. megabytesIn: integer("bytesIn"),
  119. megabytesOut: integer("bytesOut"),
  120. lastBandwidthUpdate: text("lastBandwidthUpdate"),
  121. type: text("type").notNull(), // "newt" or "wireguard"
  122. online: integer("online", { mode: "boolean" }).notNull().default(false),
  123. });
  124. export const twoFactorBackupCodes = sqliteTable("twoFactorBackupCodes", {
  125. codeId: integer("id").primaryKey({ autoIncrement: true }),
  126. userId: text("userId")
  127. .notNull()
  128. .references(() => users.userId, { onDelete: "cascade" }),
  129. codeHash: text("codeHash").notNull()
  130. });
  131. export const sessions = sqliteTable("session", {
  132. sessionId: text("id").primaryKey(),
  133. userId: text("userId")
  134. .notNull()
  135. .references(() => users.userId, { onDelete: "cascade" }),
  136. expiresAt: integer("expiresAt").notNull()
  137. });
  138. export const newtSessions = sqliteTable("newtSession", {
  139. sessionId: text("id").primaryKey(),
  140. newtId: text("newtId")
  141. .notNull()
  142. .references(() => newts.newtId, { onDelete: "cascade" }),
  143. expiresAt: integer("expiresAt").notNull()
  144. });
  145. export const olmSessions = sqliteTable("clientSession", {
  146. sessionId: text("id").primaryKey(),
  147. olmId: text("olmId")
  148. .notNull()
  149. .references(() => newts.newtId, { onDelete: "cascade" }),
  150. expiresAt: integer("expiresAt").notNull()
  151. });
  152. export const userOrgs = sqliteTable("userOrgs", {
  153. userId: text("userId")
  154. .notNull()
  155. .references(() => users.userId, { onDelete: "cascade" }),
  156. orgId: text("orgId")
  157. .references(() => orgs.orgId, {
  158. onDelete: "cascade"
  159. })
  160. .notNull(),
  161. roleId: integer("roleId")
  162. .notNull()
  163. .references(() => roles.roleId),
  164. isOwner: integer("isOwner", { mode: "boolean" }).notNull().default(false)
  165. });
  166. export const emailVerificationCodes = sqliteTable("emailVerificationCodes", {
  167. codeId: integer("id").primaryKey({ autoIncrement: true }),
  168. userId: text("userId")
  169. .notNull()
  170. .references(() => users.userId, { onDelete: "cascade" }),
  171. email: text("email").notNull(),
  172. code: text("code").notNull(),
  173. expiresAt: integer("expiresAt").notNull()
  174. });
  175. export const passwordResetTokens = sqliteTable("passwordResetTokens", {
  176. tokenId: integer("id").primaryKey({ autoIncrement: true }),
  177. email: text("email").notNull(),
  178. userId: text("userId")
  179. .notNull()
  180. .references(() => users.userId, { onDelete: "cascade" }),
  181. tokenHash: text("tokenHash").notNull(),
  182. expiresAt: integer("expiresAt").notNull()
  183. });
  184. export const actions = sqliteTable("actions", {
  185. actionId: text("actionId").primaryKey(),
  186. name: text("name"),
  187. description: text("description")
  188. });
  189. export const roles = sqliteTable("roles", {
  190. roleId: integer("roleId").primaryKey({ autoIncrement: true }),
  191. orgId: text("orgId")
  192. .references(() => orgs.orgId, {
  193. onDelete: "cascade"
  194. })
  195. .notNull(),
  196. isAdmin: integer("isAdmin", { mode: "boolean" }),
  197. name: text("name").notNull(),
  198. description: text("description")
  199. });
  200. export const roleActions = sqliteTable("roleActions", {
  201. roleId: integer("roleId")
  202. .notNull()
  203. .references(() => roles.roleId, { onDelete: "cascade" }),
  204. actionId: text("actionId")
  205. .notNull()
  206. .references(() => actions.actionId, { onDelete: "cascade" }),
  207. orgId: text("orgId")
  208. .notNull()
  209. .references(() => orgs.orgId, { onDelete: "cascade" })
  210. });
  211. export const userActions = sqliteTable("userActions", {
  212. userId: text("userId")
  213. .notNull()
  214. .references(() => users.userId, { onDelete: "cascade" }),
  215. actionId: text("actionId")
  216. .notNull()
  217. .references(() => actions.actionId, { onDelete: "cascade" }),
  218. orgId: text("orgId")
  219. .notNull()
  220. .references(() => orgs.orgId, { onDelete: "cascade" })
  221. });
  222. export const roleSites = sqliteTable("roleSites", {
  223. roleId: integer("roleId")
  224. .notNull()
  225. .references(() => roles.roleId, { onDelete: "cascade" }),
  226. siteId: integer("siteId")
  227. .notNull()
  228. .references(() => sites.siteId, { onDelete: "cascade" })
  229. });
  230. export const userSites = sqliteTable("userSites", {
  231. userId: text("userId")
  232. .notNull()
  233. .references(() => users.userId, { onDelete: "cascade" }),
  234. siteId: integer("siteId")
  235. .notNull()
  236. .references(() => sites.siteId, { onDelete: "cascade" })
  237. });
  238. export const roleResources = sqliteTable("roleResources", {
  239. roleId: integer("roleId")
  240. .notNull()
  241. .references(() => roles.roleId, { onDelete: "cascade" }),
  242. resourceId: integer("resourceId")
  243. .notNull()
  244. .references(() => resources.resourceId, { onDelete: "cascade" })
  245. });
  246. export const userResources = sqliteTable("userResources", {
  247. userId: text("userId")
  248. .notNull()
  249. .references(() => users.userId, { onDelete: "cascade" }),
  250. resourceId: integer("resourceId")
  251. .notNull()
  252. .references(() => resources.resourceId, { onDelete: "cascade" })
  253. });
  254. export const limitsTable = sqliteTable("limits", {
  255. limitId: integer("limitId").primaryKey({ autoIncrement: true }),
  256. orgId: text("orgId")
  257. .references(() => orgs.orgId, {
  258. onDelete: "cascade"
  259. })
  260. .notNull(),
  261. name: text("name").notNull(),
  262. value: integer("value").notNull(),
  263. description: text("description")
  264. });
  265. export const userInvites = sqliteTable("userInvites", {
  266. inviteId: text("inviteId").primaryKey(),
  267. orgId: text("orgId")
  268. .notNull()
  269. .references(() => orgs.orgId, { onDelete: "cascade" }),
  270. email: text("email").notNull(),
  271. expiresAt: integer("expiresAt").notNull(),
  272. tokenHash: text("token").notNull(),
  273. roleId: integer("roleId")
  274. .notNull()
  275. .references(() => roles.roleId, { onDelete: "cascade" })
  276. });
  277. export const resourcePincode = sqliteTable("resourcePincode", {
  278. pincodeId: integer("pincodeId").primaryKey({
  279. autoIncrement: true
  280. }),
  281. resourceId: integer("resourceId")
  282. .notNull()
  283. .references(() => resources.resourceId, { onDelete: "cascade" }),
  284. pincodeHash: text("pincodeHash").notNull(),
  285. digitLength: integer("digitLength").notNull()
  286. });
  287. export const resourcePassword = sqliteTable("resourcePassword", {
  288. passwordId: integer("passwordId").primaryKey({
  289. autoIncrement: true
  290. }),
  291. resourceId: integer("resourceId")
  292. .notNull()
  293. .references(() => resources.resourceId, { onDelete: "cascade" }),
  294. passwordHash: text("passwordHash").notNull()
  295. });
  296. export const resourceAccessToken = sqliteTable("resourceAccessToken", {
  297. accessTokenId: text("accessTokenId").primaryKey(),
  298. orgId: text("orgId")
  299. .notNull()
  300. .references(() => orgs.orgId, { onDelete: "cascade" }),
  301. resourceId: integer("resourceId")
  302. .notNull()
  303. .references(() => resources.resourceId, { onDelete: "cascade" }),
  304. tokenHash: text("tokenHash").notNull(),
  305. sessionLength: integer("sessionLength").notNull(),
  306. expiresAt: integer("expiresAt"),
  307. title: text("title"),
  308. description: text("description"),
  309. createdAt: integer("createdAt").notNull()
  310. });
  311. export const resourceSessions = sqliteTable("resourceSessions", {
  312. sessionId: text("id").primaryKey(),
  313. resourceId: integer("resourceId")
  314. .notNull()
  315. .references(() => resources.resourceId, { onDelete: "cascade" }),
  316. expiresAt: integer("expiresAt").notNull(),
  317. sessionLength: integer("sessionLength").notNull(),
  318. doNotExtend: integer("doNotExtend", { mode: "boolean" })
  319. .notNull()
  320. .default(false),
  321. isRequestToken: integer("isRequestToken", { mode: "boolean" }),
  322. userSessionId: text("userSessionId").references(() => sessions.sessionId, {
  323. onDelete: "cascade"
  324. }),
  325. passwordId: integer("passwordId").references(
  326. () => resourcePassword.passwordId,
  327. {
  328. onDelete: "cascade"
  329. }
  330. ),
  331. pincodeId: integer("pincodeId").references(
  332. () => resourcePincode.pincodeId,
  333. {
  334. onDelete: "cascade"
  335. }
  336. ),
  337. whitelistId: integer("whitelistId").references(
  338. () => resourceWhitelist.whitelistId,
  339. {
  340. onDelete: "cascade"
  341. }
  342. ),
  343. accessTokenId: text("accessTokenId").references(
  344. () => resourceAccessToken.accessTokenId,
  345. {
  346. onDelete: "cascade"
  347. }
  348. )
  349. });
  350. export const resourceWhitelist = sqliteTable("resourceWhitelist", {
  351. whitelistId: integer("id").primaryKey({ autoIncrement: true }),
  352. email: text("email").notNull(),
  353. resourceId: integer("resourceId")
  354. .notNull()
  355. .references(() => resources.resourceId, { onDelete: "cascade" })
  356. });
  357. export const resourceOtp = sqliteTable("resourceOtp", {
  358. otpId: integer("otpId").primaryKey({
  359. autoIncrement: true
  360. }),
  361. resourceId: integer("resourceId")
  362. .notNull()
  363. .references(() => resources.resourceId, { onDelete: "cascade" }),
  364. email: text("email").notNull(),
  365. otpHash: text("otpHash").notNull(),
  366. expiresAt: integer("expiresAt").notNull()
  367. });
  368. export const versionMigrations = sqliteTable("versionMigrations", {
  369. version: text("version").primaryKey(),
  370. executedAt: integer("executedAt").notNull()
  371. });
  372. export const resourceRules = sqliteTable("resourceRules", {
  373. ruleId: integer("ruleId").primaryKey({ autoIncrement: true }),
  374. resourceId: integer("resourceId")
  375. .notNull()
  376. .references(() => resources.resourceId, { onDelete: "cascade" }),
  377. enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
  378. priority: integer("priority").notNull(),
  379. action: text("action").notNull(), // ACCEPT, DROP
  380. match: text("match").notNull(), // CIDR, PATH, IP
  381. value: text("value").notNull()
  382. });
  383. export type Org = InferSelectModel<typeof orgs>;
  384. export type User = InferSelectModel<typeof users>;
  385. export type Site = InferSelectModel<typeof sites>;
  386. export type Resource = InferSelectModel<typeof resources>;
  387. export type ExitNode = InferSelectModel<typeof exitNodes>;
  388. export type Target = InferSelectModel<typeof targets>;
  389. export type Session = InferSelectModel<typeof sessions>;
  390. export type Newt = InferSelectModel<typeof newts>;
  391. export type NewtSession = InferSelectModel<typeof newtSessions>;
  392. export type Olm = InferSelectModel<typeof olms>;
  393. export type OlmSession = InferSelectModel<typeof olmSessions>;
  394. export type EmailVerificationCode = InferSelectModel<
  395. typeof emailVerificationCodes
  396. >;
  397. export type TwoFactorBackupCode = InferSelectModel<typeof twoFactorBackupCodes>;
  398. export type PasswordResetToken = InferSelectModel<typeof passwordResetTokens>;
  399. export type Role = InferSelectModel<typeof roles>;
  400. export type Action = InferSelectModel<typeof actions>;
  401. export type RoleAction = InferSelectModel<typeof roleActions>;
  402. export type UserAction = InferSelectModel<typeof userActions>;
  403. export type RoleSite = InferSelectModel<typeof roleSites>;
  404. export type UserSite = InferSelectModel<typeof userSites>;
  405. export type RoleResource = InferSelectModel<typeof roleResources>;
  406. export type UserResource = InferSelectModel<typeof userResources>;
  407. export type Limit = InferSelectModel<typeof limitsTable>;
  408. export type UserInvite = InferSelectModel<typeof userInvites>;
  409. export type UserOrg = InferSelectModel<typeof userOrgs>;
  410. export type ResourceSession = InferSelectModel<typeof resourceSessions>;
  411. export type ResourcePincode = InferSelectModel<typeof resourcePincode>;
  412. export type ResourcePassword = InferSelectModel<typeof resourcePassword>;
  413. export type ResourceOtp = InferSelectModel<typeof resourceOtp>;
  414. export type ResourceAccessToken = InferSelectModel<typeof resourceAccessToken>;
  415. export type ResourceWhitelist = InferSelectModel<typeof resourceWhitelist>;
  416. export type VersionMigration = InferSelectModel<typeof versionMigrations>;
  417. export type ResourceRule = InferSelectModel<typeof resourceRules>;