-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Automated flow for GDPR/CCPA deletion requests (#7)
* Draft: Work towards improved GDPR/CCPA compliance * ac assoc repos * todo * txn and logs * 204 resp * lastfm flags * redis conn * dep * reformat some code * add routing * wipe notes and add dt's * peppy:ban pubsub * error resp * fixes & wipe more user data * type fixes * note * reduce map * typo * take over prod
- Loading branch information
Showing
25 changed files
with
683 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
from fastapi import APIRouter | ||
|
||
from app.api.internal.v1 import users | ||
|
||
v1_router = APIRouter() | ||
|
||
v1_router.include_router(users.router) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import logging | ||
|
||
from fastapi import APIRouter | ||
from fastapi import Response | ||
from fastapi import status | ||
|
||
from app.api.responses import JSONResponse | ||
from app.errors import Error | ||
from app.errors import ErrorCode | ||
from app.usecases import users | ||
|
||
router = APIRouter(tags=["(Internal) Users API"]) | ||
|
||
|
||
def map_error_code_to_http_status_code(error_code: ErrorCode) -> int: | ||
status_code = _error_code_to_http_status_code_map.get(error_code) | ||
if status_code is None: | ||
logging.warning( | ||
"No HTTP status code mapping found for error code: %s", | ||
error_code, | ||
extra={"error_code": error_code}, | ||
) | ||
return 500 | ||
return status_code | ||
|
||
|
||
_error_code_to_http_status_code_map: dict[ErrorCode, int] = { | ||
ErrorCode.INTERNAL_SERVER_ERROR: 500, | ||
} | ||
|
||
|
||
@router.delete("/api/v1/users/{user_id}") | ||
async def delete_user(user_id: int) -> Response: | ||
response = await users.delete_one_by_user_id(user_id) | ||
if isinstance(response, Error): | ||
return JSONResponse( | ||
content=response.model_dump(), | ||
status_code=map_error_code_to_http_status_code(response.error_code), | ||
) | ||
|
||
# TODO: check if response body is b"none" | ||
return Response(status_code=status.HTTP_204_NO_CONTENT) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
from enum import IntEnum | ||
|
||
from pydantic import BaseModel | ||
|
||
import app.state | ||
|
||
|
||
class ClanStatus(IntEnum): | ||
CLOSED = 0 | ||
OPEN_FOR_ALL = 1 | ||
INVITE_ONLY = 2 | ||
REQUEST_TO_JOIN = 3 | ||
|
||
|
||
class Clan(BaseModel): | ||
id: int | ||
name: str | ||
tag: str | ||
description: str | ||
icon: str | ||
background: str | ||
owner: int | ||
invite: str | ||
status: ClanStatus | ||
|
||
|
||
READ_PARAMS = """\ | ||
id, name, tag, description, icon, background, owner, invite, status | ||
""" | ||
|
||
|
||
async def fetch_one_by_clan_id(clan_id: int, /) -> Clan | None: | ||
query = f"""\ | ||
SELECT {READ_PARAMS} | ||
FROM clans | ||
WHERE id = :clan_id | ||
""" | ||
params = {"clan_id": clan_id} | ||
|
||
clan = await app.state.database.fetch_one(query, params) | ||
if clan is None: | ||
return None | ||
|
||
return Clan( | ||
id=clan["id"], | ||
name=clan["name"], | ||
tag=clan["tag"], | ||
description=clan["description"], | ||
icon=clan["icon"], | ||
background=clan["background"], | ||
owner=clan["owner"], | ||
invite=clan["invite"], | ||
status=ClanStatus(clan["status"]), | ||
) | ||
|
||
|
||
async def update_owner(clan_id: int, new_owner: int) -> None: | ||
query = """\ | ||
UPDATE clans | ||
SET owner = :new_owner | ||
WHERE id = :clan_id | ||
""" | ||
params = {"new_owner": new_owner, "clan_id": clan_id} | ||
|
||
await app.state.database.execute(query, params) | ||
|
||
|
||
async def delete_one_by_clan_id(clan_id: int, /) -> None: | ||
query = """\ | ||
DELETE FROM clans | ||
WHERE id = :clan_id | ||
""" | ||
params = {"clan_id": clan_id} | ||
|
||
await app.state.database.execute(query, params) |
Oops, something went wrong.