From d8f71efdd5ffac353c69627a92595c637f7acbc8 Mon Sep 17 00:00:00 2001 From: Mahdi Date: Mon, 11 May 2026 14:17:20 +0330 Subject: [PATCH] add auth otp migration --- .env.example | 6 ++++ .../1789039400000-CreateAuthOtps.ts | 29 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/database/migrations/1789039400000-CreateAuthOtps.ts diff --git a/.env.example b/.env.example index ff28930..07f3d1f 100644 --- a/.env.example +++ b/.env.example @@ -5,3 +5,9 @@ POSTGRES_PASSWORD=change_me POSTGRES_DB=montime # Dev only: auto-sync schema from entities (do not use true in production) DB_SYNC=true + +JWT_SECRET=change_me_to_a_long_random_secret +OTP_HASH_SECRET=change_me_to_a_long_random_secret +SUPER_ADMIN_MOBILE=09123456789 +# Dev/test only: returns OTP code in API response instead of sending SMS +AUTH_RETURN_OTP=true diff --git a/src/database/migrations/1789039400000-CreateAuthOtps.ts b/src/database/migrations/1789039400000-CreateAuthOtps.ts new file mode 100644 index 0000000..8e461a5 --- /dev/null +++ b/src/database/migrations/1789039400000-CreateAuthOtps.ts @@ -0,0 +1,29 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class CreateAuthOtps1789039400000 implements MigrationInterface { + name = 'CreateAuthOtps1789039400000'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query('CREATE EXTENSION IF NOT EXISTS "pgcrypto"'); + await queryRunner.query(` + CREATE TABLE IF NOT EXISTS "auth_otps" ( + "id" uuid NOT NULL DEFAULT gen_random_uuid(), + "mobile" character varying(20) NOT NULL, + "codeHash" character varying(128) NOT NULL, + "expiresAt" TIMESTAMP WITH TIME ZONE NOT NULL, + "consumedAt" TIMESTAMP WITH TIME ZONE, + "attempts" integer NOT NULL DEFAULT 0, + "createdAt" TIMESTAMP NOT NULL DEFAULT now(), + CONSTRAINT "PK_auth_otps_id" PRIMARY KEY ("id") + ) + `); + await queryRunner.query( + 'CREATE INDEX IF NOT EXISTS "IDX_auth_otps_mobile" ON "auth_otps" ("mobile")', + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query('DROP INDEX IF EXISTS "IDX_auth_otps_mobile"'); + await queryRunner.query('DROP TABLE IF EXISTS "auth_otps"'); + } +}