From 0b53bbaa70ab4fdf5315af97b1d8974566718f83 Mon Sep 17 00:00:00 2001 From: coolneng Date: Thu, 8 Oct 2020 20:47:10 +0200 Subject: [PATCH] Implement forgot password --- app/routes.py | 9 +++++++ app/schemas.py | 16 +++++++++++ database/crud.py | 20 ++++++++++++++ database/models.py | 4 ++- .../f8ef6bad794a_add_forgot_password_field.py | 27 +++++++++++++++++++ tests/requests_test.py | 17 +++++++----- 6 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 migrations/versions/f8ef6bad794a_add_forgot_password_field.py diff --git a/app/routes.py b/app/routes.py index a3f966a..824198d 100644 --- a/app/routes.py +++ b/app/routes.py @@ -32,3 +32,12 @@ def deliver_otp(data: OTPResend, db: Session = Depends(get_db)): update_otp(data=data, db=db) response = resend_otp(data=data, db=db) return response + + +@router.post("/forgot_password", response_model=ForgotPasswordResponse) +def forgot_password(data: ForgotPassword, db: Session = Depends(get_db)): + mark_password_reset(data=data, db=db) + response = resend_otp(data=data, db=db) + return response + + diff --git a/app/schemas.py b/app/schemas.py index 24a76ed..3e374ae 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -122,6 +122,22 @@ class OTPResendResponse(UserCreateResponse): orm_mode = True +class ForgotPassword(BaseModel): + email: EmailStr + + class Config: + orm_mode = True + + +class ForgotPasswordResponse(BaseModel): + otp: int + mobile: str = Query(None, min_length=8, max_length=13) + message: str = "The OTP has been sent to you via SMS" + + class Config: + orm_mode = True + + access_key: str otp: int = Query(None, ge=6, le=6) diff --git a/database/crud.py b/database/crud.py index 3796b65..ae02ff9 100644 --- a/database/crud.py +++ b/database/crud.py @@ -113,6 +113,14 @@ def activate_account(user, db): db.refresh(user) +def deactivate_account(user, db): + db.query(Users).filter(Users.email == user.email).update( + {Users.status: 0, Users.forgot_password: 1} + ) + db.commit() + db.refresh(user) + + def verify_otp(data: OTPVerify, db): user = fetch_user_by_key(data=data, db=db) matching_otp = user.otp == data.otp @@ -123,3 +131,15 @@ def verify_otp(data: OTPVerify, db): return user else: raise HTTPException(status_code=400, detail="The OTP is not correct") + + +def mark_password_reset(data, db): + user = fetch_user_by_email(data=data, db=db) + if user.social_id: + raise HTTPException( + status_code=400, + detail="You logged in with Facebook/Google. You can't reset the password", + ) + deactivate_account(user=user, db=db) + + diff --git a/database/models.py b/database/models.py index 040f078..2fc0054 100644 --- a/database/models.py +++ b/database/models.py @@ -1,4 +1,5 @@ -from sqlalchemy import Column, DateTime, Enum, ForeignKey, Integer, String, Text, text +from sqlalchemy import Column, ForeignKey, text +from sqlalchemy.types import * from sqlalchemy.sql import func from database import Base @@ -27,6 +28,7 @@ class Users(Base): admin_status = Column(Integer, server_default=text("0")) device_id = Column(Text) device_type = Column(Integer) + forgot_password = Column(Integer, server_default=text("0")) created = Column(DateTime, nullable=False, server_default=func.now()) updated = Column(DateTime, nullable=True, onupdate=func.now()) diff --git a/migrations/versions/f8ef6bad794a_add_forgot_password_field.py b/migrations/versions/f8ef6bad794a_add_forgot_password_field.py new file mode 100644 index 0000000..053b5b5 --- /dev/null +++ b/migrations/versions/f8ef6bad794a_add_forgot_password_field.py @@ -0,0 +1,27 @@ +"""add forgot_password field + +Revision ID: f8ef6bad794a +Revises: d994081ed483 +Create Date: 2020-10-08 18:04:08.204841 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "f8ef6bad794a" +down_revision = "d994081ed483" +branch_labels = None +depends_on = None + + +def upgrade(): + with op.batch_alter_table("users") as batch_op: + batch_op.add_column( + sa.Column("forgot_password", sa.Integer, server_default=sa.text("0")), + ) + + +def downgrade(): + pass diff --git a/tests/requests_test.py b/tests/requests_test.py index b138610..07c4dff 100644 --- a/tests/requests_test.py +++ b/tests/requests_test.py @@ -25,10 +25,7 @@ def test_registration(): def test_otp_verification(get_test_db): user = get_test_db.query(Users).filter(Users.email == "oyvey@hotmail.com").first() - data = { - "access_key": user.access_key, - "otp": user.otp, - } + data = {"access_key": user.access_key, "otp": user.otp} response = client.post("/otpVerification", json=data) assert response.status_code == 200 @@ -46,8 +43,14 @@ def test_login(): def test_resend_otp(): - data = { - "email": "testorganizer@odyfo.com", - } + data = {"email": "testorganizer@odyfo.com"} response = client.post("/resendOTP", json=data) assert response.status_code == 200 + + +def test_forgot_password(): + data = {"email": "oyvey@hotmail.com"} + response = client.post("/forgot_password", json=data) + assert response.status_code == 200 + +