Implement forgot password
This commit is contained in:
parent
3be567c8ac
commit
0b53bbaa70
|
@ -32,3 +32,12 @@ def deliver_otp(data: OTPResend, db: Session = Depends(get_db)):
|
||||||
update_otp(data=data, db=db)
|
update_otp(data=data, db=db)
|
||||||
response = resend_otp(data=data, db=db)
|
response = resend_otp(data=data, db=db)
|
||||||
return response
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,22 @@ class OTPResendResponse(UserCreateResponse):
|
||||||
orm_mode = True
|
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
|
access_key: str
|
||||||
otp: int = Query(None, ge=6, le=6)
|
otp: int = Query(None, ge=6, le=6)
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,14 @@ def activate_account(user, db):
|
||||||
db.refresh(user)
|
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):
|
def verify_otp(data: OTPVerify, db):
|
||||||
user = fetch_user_by_key(data=data, db=db)
|
user = fetch_user_by_key(data=data, db=db)
|
||||||
matching_otp = user.otp == data.otp
|
matching_otp = user.otp == data.otp
|
||||||
|
@ -123,3 +131,15 @@ def verify_otp(data: OTPVerify, db):
|
||||||
return user
|
return user
|
||||||
else:
|
else:
|
||||||
raise HTTPException(status_code=400, detail="The OTP is not correct")
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 sqlalchemy.sql import func
|
||||||
|
|
||||||
from database import Base
|
from database import Base
|
||||||
|
@ -27,6 +28,7 @@ class Users(Base):
|
||||||
admin_status = Column(Integer, server_default=text("0"))
|
admin_status = Column(Integer, server_default=text("0"))
|
||||||
device_id = Column(Text)
|
device_id = Column(Text)
|
||||||
device_type = Column(Integer)
|
device_type = Column(Integer)
|
||||||
|
forgot_password = Column(Integer, server_default=text("0"))
|
||||||
created = Column(DateTime, nullable=False, server_default=func.now())
|
created = Column(DateTime, nullable=False, server_default=func.now())
|
||||||
updated = Column(DateTime, nullable=True, onupdate=func.now())
|
updated = Column(DateTime, nullable=True, onupdate=func.now())
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -25,10 +25,7 @@ def test_registration():
|
||||||
|
|
||||||
def test_otp_verification(get_test_db):
|
def test_otp_verification(get_test_db):
|
||||||
user = get_test_db.query(Users).filter(Users.email == "oyvey@hotmail.com").first()
|
user = get_test_db.query(Users).filter(Users.email == "oyvey@hotmail.com").first()
|
||||||
data = {
|
data = {"access_key": user.access_key, "otp": user.otp}
|
||||||
"access_key": user.access_key,
|
|
||||||
"otp": user.otp,
|
|
||||||
}
|
|
||||||
response = client.post("/otpVerification", json=data)
|
response = client.post("/otpVerification", json=data)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
@ -46,8 +43,14 @@ def test_login():
|
||||||
|
|
||||||
|
|
||||||
def test_resend_otp():
|
def test_resend_otp():
|
||||||
data = {
|
data = {"email": "testorganizer@odyfo.com"}
|
||||||
"email": "testorganizer@odyfo.com",
|
|
||||||
}
|
|
||||||
response = client.post("/resendOTP", json=data)
|
response = client.post("/resendOTP", json=data)
|
||||||
assert response.status_code == 200
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue