setupServerAdmin.ts 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import { generateId, invalidateAllSessions } from "@server/auth";
  2. import { hashPassword, verifyPassword } from "@server/auth/password";
  3. import { passwordSchema } from "@server/auth/passwordSchema";
  4. import config from "@server/config";
  5. import db from "@server/db";
  6. import { users } from "@server/db/schema";
  7. import logger from "@server/logger";
  8. import { eq } from "drizzle-orm";
  9. import moment from "moment";
  10. import { fromError } from "zod-validation-error";
  11. export async function setupServerAdmin() {
  12. const {
  13. server_admin: { email, password }
  14. } = config.users;
  15. const parsed = passwordSchema.safeParse(password);
  16. if (!parsed.success) {
  17. throw Error(
  18. `Invalid server admin password: ${fromError(parsed.error).toString()}`
  19. );
  20. }
  21. const passwordHash = await hashPassword(password);
  22. await db.transaction(async (trx) => {
  23. try {
  24. const [existing] = await trx
  25. .select()
  26. .from(users)
  27. .where(eq(users.email, email));
  28. if (existing) {
  29. const passwordChanged = !(await verifyPassword(
  30. password,
  31. existing.passwordHash
  32. ));
  33. if (passwordChanged) {
  34. await trx
  35. .update(users)
  36. .set({ passwordHash })
  37. .where(eq(users.email, email));
  38. // this isn't using the transaction, but it's probably fine
  39. await invalidateAllSessions(existing.userId);
  40. logger.info(`Server admin (${email}) password updated`);
  41. }
  42. if (existing.serverAdmin) {
  43. return;
  44. }
  45. await trx.update(users).set({ serverAdmin: false });
  46. await trx
  47. .update(users)
  48. .set({
  49. serverAdmin: true
  50. })
  51. .where(eq(users.email, email));
  52. logger.info(`Server admin (${email}) updated`);
  53. return;
  54. }
  55. const userId = generateId(15);
  56. await db.insert(users).values({
  57. userId: userId,
  58. email: email,
  59. passwordHash,
  60. dateCreated: moment().toISOString(),
  61. serverAdmin: true,
  62. emailVerified: true
  63. });
  64. logger.info(`Server admin (${email}) created`);
  65. } catch (e) {
  66. logger.error(e);
  67. trx.rollback();
  68. }
  69. });
  70. }