diff --git a/alembic/versions/0011_add_password_reset_tokens.py b/alembic/versions/0011_add_password_reset_tokens.py new file mode 100644 index 0000000..02fee2b --- /dev/null +++ b/alembic/versions/0011_add_password_reset_tokens.py @@ -0,0 +1,25 @@ +"""Add password_reset_tokens table.""" + +from alembic import op + +revision = "0011" +down_revision = "0010" + + +def upgrade() -> None: + op.execute(""" + CREATE TABLE password_reset_tokens ( + id SERIAL PRIMARY KEY, + user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, + token_hash TEXT NOT NULL UNIQUE, + expires_at TIMESTAMPTZ NOT NULL, + used BOOLEAN NOT NULL DEFAULT FALSE, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() + ) + """) + op.execute("CREATE INDEX ix_password_reset_tokens_token_hash ON password_reset_tokens (token_hash)") + op.execute("CREATE INDEX ix_password_reset_tokens_user_id ON password_reset_tokens (user_id)") + + +def downgrade() -> None: + op.execute("DROP TABLE IF EXISTS password_reset_tokens") diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index 1b895ed..e76f7b8 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -22,6 +22,18 @@ const router = createRouter({ component: () => import("@/views/RegisterView.vue"), meta: { public: true }, }, + { + path: "/forgot-password", + name: "forgot-password", + component: () => import("@/views/ForgotPasswordView.vue"), + meta: { public: true }, + }, + { + path: "/reset-password", + name: "reset-password", + component: () => import("@/views/ResetPasswordView.vue"), + meta: { public: true }, + }, { path: "/notes", name: "notes", diff --git a/frontend/src/views/ForgotPasswordView.vue b/frontend/src/views/ForgotPasswordView.vue new file mode 100644 index 0000000..2a69590 --- /dev/null +++ b/frontend/src/views/ForgotPasswordView.vue @@ -0,0 +1,167 @@ + + + + + diff --git a/frontend/src/views/LoginView.vue b/frontend/src/views/LoginView.vue index 732307d..620b96e 100644 --- a/frontend/src/views/LoginView.vue +++ b/frontend/src/views/LoginView.vue @@ -69,6 +69,9 @@ async function handleSubmit() { class="input" /> +

{{ error }}