Spaces:
Sleeping
Sleeping
feat:removed device token
Browse files- src/notifications/router.py +25 -0
- src/profile/router.py +70 -0
src/notifications/router.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
|
|
| 1 |
from src.profile.models import Leave
|
|
|
|
| 2 |
from requests.api import delete
|
| 3 |
from src.notifications.schemas import RegisterDeviceRequest
|
| 4 |
from src.notifications.service import register_device
|
|
@@ -44,6 +46,27 @@ async def mark_notification_read(
|
|
| 44 |
return {"message": "Marked as read"}
|
| 45 |
|
| 46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
@router.post("/mark-all-read")
|
| 48 |
async def mark_all_read(
|
| 49 |
session: AsyncSession = Depends(get_async_session),
|
|
@@ -62,3 +85,5 @@ async def mark_all_read(
|
|
| 62 |
await session.commit()
|
| 63 |
|
| 64 |
return {"message": "All notifications cleared"}
|
|
|
|
|
|
|
|
|
| 1 |
+
from src.profile.models import UserDevices
|
| 2 |
from src.profile.models import Leave
|
| 3 |
+
from sqlmodel import select
|
| 4 |
from requests.api import delete
|
| 5 |
from src.notifications.schemas import RegisterDeviceRequest
|
| 6 |
from src.notifications.service import register_device
|
|
|
|
| 46 |
return {"message": "Marked as read"}
|
| 47 |
|
| 48 |
|
| 49 |
+
@router.post("/logout")
|
| 50 |
+
async def logout(
|
| 51 |
+
body: RegisterDeviceRequest,
|
| 52 |
+
session: AsyncSession = Depends(get_async_session),
|
| 53 |
+
user_id: str = Depends(get_current_user),
|
| 54 |
+
):
|
| 55 |
+
stmt = select(UserDevices).where(
|
| 56 |
+
UserDevices.user_id == user_id, UserDevices.device_token == body.device_token
|
| 57 |
+
)
|
| 58 |
+
result = await session.execute(stmt)
|
| 59 |
+
device = result.scalar_one_or_none()
|
| 60 |
+
|
| 61 |
+
if not device:
|
| 62 |
+
return {"message": "Device already removed"}
|
| 63 |
+
|
| 64 |
+
await session.delete(device)
|
| 65 |
+
await session.commit()
|
| 66 |
+
|
| 67 |
+
return {"message": "Logged out — device token removed"}
|
| 68 |
+
|
| 69 |
+
|
| 70 |
@router.post("/mark-all-read")
|
| 71 |
async def mark_all_read(
|
| 72 |
session: AsyncSession = Depends(get_async_session),
|
|
|
|
| 85 |
await session.commit()
|
| 86 |
|
| 87 |
return {"message": "All notifications cleared"}
|
| 88 |
+
|
| 89 |
+
|
src/profile/router.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
from uuid import UUID
|
| 2 |
from src.core.models import Assets
|
| 3 |
from src.profile.schemas import AssetResponse
|
|
@@ -611,3 +612,72 @@ async def get_profile(
|
|
| 611 |
"assets": assets_dto,
|
| 612 |
},
|
| 613 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from src.profile.schemas import UpdateProfileRequest
|
| 2 |
from uuid import UUID
|
| 3 |
from src.core.models import Assets
|
| 4 |
from src.profile.schemas import AssetResponse
|
|
|
|
| 612 |
"assets": assets_dto,
|
| 613 |
},
|
| 614 |
)
|
| 615 |
+
|
| 616 |
+
|
| 617 |
+
@router.put("/update-profile", response_model=BaseResponse)
|
| 618 |
+
async def update_profile(
|
| 619 |
+
body: UpdateProfileRequest,
|
| 620 |
+
session: AsyncSession = Depends(get_async_session),
|
| 621 |
+
user_id: str = Depends(get_current_user),
|
| 622 |
+
):
|
| 623 |
+
# Get logged-in user
|
| 624 |
+
user = await session.get(Users, user_id)
|
| 625 |
+
if not user:
|
| 626 |
+
raise HTTPException(status_code=404, detail="User not found")
|
| 627 |
+
|
| 628 |
+
# --- Update basic profile fields ---
|
| 629 |
+
if body.name is not None:
|
| 630 |
+
user.user_name = body.name
|
| 631 |
+
|
| 632 |
+
if body.email is not None:
|
| 633 |
+
user.email_id = body.email
|
| 634 |
+
|
| 635 |
+
if body.dob is not None:
|
| 636 |
+
dob_str = body.dob.replace(".", "-") # convert dots to dashes
|
| 637 |
+
try:
|
| 638 |
+
user.dob = datetime.strptime(dob_str, "%Y-%m-%d").date()
|
| 639 |
+
except ValueError:
|
| 640 |
+
raise HTTPException(
|
| 641 |
+
status_code=400, detail="DOB must be YYYY-MM-DD or YYYY.MM.DD"
|
| 642 |
+
)
|
| 643 |
+
|
| 644 |
+
if body.address is not None:
|
| 645 |
+
user.address = body.address # ensure DB has this column
|
| 646 |
+
|
| 647 |
+
# --- Handle password update ---
|
| 648 |
+
if body.current_password and body.new_password:
|
| 649 |
+
# Check current password matches
|
| 650 |
+
from src.auth.utils import verify_password, hash_password
|
| 651 |
+
|
| 652 |
+
if not verify_password(body.current_password, user.password):
|
| 653 |
+
raise HTTPException(
|
| 654 |
+
status_code=400,
|
| 655 |
+
detail="Current password is incorrect",
|
| 656 |
+
)
|
| 657 |
+
|
| 658 |
+
# update password
|
| 659 |
+
user.password = hash_password(body.new_password)
|
| 660 |
+
|
| 661 |
+
elif body.new_password and not body.current_password:
|
| 662 |
+
raise HTTPException(
|
| 663 |
+
status_code=400,
|
| 664 |
+
detail="Current password is required to set new password",
|
| 665 |
+
)
|
| 666 |
+
|
| 667 |
+
# Save
|
| 668 |
+
await session.commit()
|
| 669 |
+
await session.refresh(user)
|
| 670 |
+
|
| 671 |
+
# Response matches frontend expectation
|
| 672 |
+
return BaseResponse(
|
| 673 |
+
code=200,
|
| 674 |
+
data={
|
| 675 |
+
"user": {
|
| 676 |
+
"id": str(user.id),
|
| 677 |
+
"name": user.user_name,
|
| 678 |
+
"email": user.email_id,
|
| 679 |
+
"dob": getattr(user, "dob", None),
|
| 680 |
+
"address": getattr(user, "address", None),
|
| 681 |
+
}
|
| 682 |
+
},
|
| 683 |
+
)
|