From 792c26f98790260f0ffa826083f6681a7790c955 Mon Sep 17 00:00:00 2001 From: Tnix Date: Wed, 11 Sep 2024 00:31:03 +1200 Subject: [PATCH] add the ability to remove email addresses --- rest_api/v0/me.py | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/rest_api/v0/me.py b/rest_api/v0/me.py index ae78be9..8e7b0e9 100644 --- a/rest_api/v0/me.py +++ b/rest_api/v0/me.py @@ -51,9 +51,12 @@ class Config: class UpdateEmailBody(BaseModel): password: str = Field(min_length=1, max_length=255) # change in API v1 - email: Optional[str] = Field(default=None, max_length=255, pattern=security.EMAIL_REGEX) + email: str = Field(max_length=255, pattern=security.EMAIL_REGEX) captcha: Optional[str] = Field(default="", max_length=2000) +class RemoveEmailBody(BaseModel): + password: str = Field(min_length=1, max_length=255) # change in API v1 + class ChangePasswordBody(BaseModel): old: str = Field(min_length=1, max_length=255) # change in API v1 new: str = Field(min_length=8, max_length=72) @@ -260,6 +263,41 @@ async def update_email(data: UpdateEmailBody): return {"error": False}, 200 +@me_bp.delete("/email") +@validate_request(RemoveEmailBody) +async def remove_email(data: RemoveEmailBody): + # Check authorization + if not request.user: + abort(401) + + # Check ratelimits + if security.ratelimited(f"login:u:{request.user}"): + abort(429) + + # Check password + account = db.usersv0.find_one({"_id": request.user}, projection={"email": 1, "pswd": 1}) + if not security.check_password_hash(data.password, account["pswd"]): + security.ratelimit(f"login:u:{request.user}", 5, 60) + return {"error": True, "type": "invalidCredentials"}, 401 + + # Log action + security.log_security_action("email_changed", account["_id"], { + "old_email_hash": security.get_normalized_email_hash(account["email"]) if account.get("email") else None, + "new_email_hash": None, + "ip": request.ip, + "user_agent": request.headers.get("User-Agent") + }) + + # Update user's email address + db.usersv0.update_one({"_id": account["_id"]}, {"$set": { + "email": "", + "normalized_email_hash": "" + }}) + app.cl.send_event("update_config", {"email": ""}, usernames=[account["_id"]]) + + return {"error": False}, 200 + + @me_bp.patch("/password") @validate_request(ChangePasswordBody) async def change_password(data: ChangePasswordBody):