From 3c9b87d0d727143d36e57157ba0279ebed65e108 Mon Sep 17 00:00:00 2001 From: Wu Chengyu <54303040+7086cmd@users.noreply.github.com> Date: Wed, 24 Apr 2024 23:09:03 +0800 Subject: [PATCH 1/3] fix: use history --- routers/activities_router.py | 50 +++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/routers/activities_router.py b/routers/activities_router.py index e22a1e9..4439abe 100755 --- a/routers/activities_router.py +++ b/routers/activities_router.py @@ -172,6 +172,10 @@ async def change_activity_status( target_activity = await db.zvms.activities.find_one( {"_id": validate_object_id(activity_oid)} ) + + if not target_activity: + raise HTTPException(status_code=404, detail="Activity not found") + # Check user permission if ( "secretary" not in user["per"] @@ -335,6 +339,9 @@ async def user_activity_signup( {"_id": validate_object_id(activity_oid)} ) + if not activity: + raise HTTPException(status_code=404, detail="Activity not found") + # Check available if user doesn't have any other permission _flag = False if ( @@ -414,10 +421,12 @@ async def read_user_history( and user["id"] != str(validate_object_id(uid)) ): raise HTTPException(status_code=403, detail="Permission denined.") - activity = await db.zvms.activities.find( + activity = await db.zvms.activities.find_one( {"_id": validate_object_id(activity_oid), "members._id": uid}, {"members.$": 1, "_id": 0}, ) + if not activity: + raise HTTPException(status_code=404, detail="Activity not found") return {"status": "ok", "code": 200, "data": activity["members"][0]["history"]} @@ -434,6 +443,9 @@ async def user_activity_signoff( {"_id": validate_object_id(activity_oid)} ) + if not activity: + raise HTTPException(status_code=404, detail="Activity not found") + _flag = False for member in activity["members"]: if member["_id"] == uid: @@ -483,6 +495,9 @@ async def user_impression_edit( {"_id": validate_object_id(activity_oid)} ) + if not activity: + raise HTTPException(status_code=404, detail="Activity not found") + # Check if user is in activity _flag = False for member in activity["members"]: @@ -506,7 +521,12 @@ async def user_impression_edit( user_activity = await db.zvms.activities.find_one( {"_id": validate_object_id(activity_oid), "members._id": id} - )['members'][0] + ) + + if user_activity is None: + raise HTTPException(status_code=404, detail="User not found in activity") + + user_activity = user_activity['members'][0] history = ActivityMemberHistory(impression=user_activity['impression'], duration=user_activity['duration'], @@ -546,6 +566,9 @@ async def user_status_edit( {"_id": validate_object_id(activity_oid)} ) + if not activity: + raise HTTPException(status_code=404, detail="Activity not found") + # Check if user is in activity _flag = False for member in activity["members"]: @@ -570,6 +593,9 @@ async def user_status_edit( {"_id": validate_object_id(activity_oid)} ) + if activity is None: + raise HTTPException(status_code=404, detail="Activity not found") + member = None for i in activity["members"]: @@ -597,7 +623,12 @@ async def user_status_edit( user_activity = await db.zvms.activities.find_one( {"_id": validate_object_id(activity_oid), "members._id": user_oid} - )['members'][0] + ) + + if user_activity is None: + raise HTTPException(status_code=404, detail="User not found in activity") + + user_activity = user_activity['members'][0] history = ActivityMemberHistory(impression=user_activity['impression'], duration=user_activity['duration'], @@ -637,6 +668,9 @@ async def user_duration_edit( {"_id": validate_object_id(activity_oid)} ) + if activity is None: + raise HTTPException(status_code=404, detail="Activity not found") + # Check if user is in activity _flag = False for member in activity["members"]: @@ -661,6 +695,9 @@ async def user_duration_edit( member = None + if activity is None: + raise HTTPException(status_code=404, detail="Activity not found") + for i in activity["members"]: if i["_id"] == user_oid: member = i @@ -678,7 +715,12 @@ async def user_duration_edit( user_activity = await db.zvms.activities.find_one( {"_id": validate_object_id(activity_oid), "members._id": user_oid} - )['members'][0] + ) + + if user_activity is None: + raise HTTPException(status_code=404, detail="User not found in activity") + + user_activity = user_activity['members'][0] history = ActivityMemberHistory(impression=user_activity['impression'], duration=user_activity['duration'], From 1d5b933c28c8ae39ebb96f07c933ce8fa19d9530 Mon Sep 17 00:00:00 2001 From: Wu Chengyu <54303040+7086cmd@users.noreply.github.com> Date: Thu, 2 May 2024 19:00:50 +0800 Subject: [PATCH 2/3] feat: sort with status for audit --- routers/activities_router.py | 202 ++++++++++++++++++++++++++++------- routers/groups_router.py | 9 +- 2 files changed, 172 insertions(+), 39 deletions(-) diff --git a/routers/activities_router.py b/routers/activities_router.py index 4439abe..c987787 100755 --- a/routers/activities_router.py +++ b/routers/activities_router.py @@ -255,7 +255,12 @@ async def read_activities( "as": "member", "cond": { "$or": [ - {"$eq": ["$$member.status", "" if not audit else "pending"]}, + { + "$eq": [ + "$$member.status", + "" if not audit else "pending", + ] + }, ] }, } @@ -273,7 +278,20 @@ async def read_activities( "members.status": True, } }, - {"$sort": {"_id": -1}}, + { + "$addFields": { + "pendingCount": { + "$size": { + "$filter": { + "input": "$members", + "as": "member", + "cond": {"$eq": ["$$member.status", "pending"]}, + } + } + } + } + }, + {"$sort": {"pendingCount": -1, "_id": -1}}, {"$skip": 0 if page == -1 else (page - 1) * perpage}, {"$limit": 0 if page == -1 else perpage}, ] @@ -308,13 +326,117 @@ async def read_activity(activity_oid: str, user=Depends(get_current_user)): Return activity """ # Read activity - activity = await db.zvms.activities.find_one( - {"_id": validate_object_id(activity_oid)}, + pipeline = [ { - "members.impression": False, - "members.history": False, + "$match": { + "_id": validate_object_id(activity_oid), + } }, - ) + { + "$addFields": { + "members": { + "$map": { + "input": "$members", + "as": "member", + "in": { + "$mergeObjects": [ + "$$member", + { + "sortKey": { + "$switch": { + "branches": [ + { + "case": { + "$eq": [ + "$$member.status", + "pending", + ] + }, + "then": 0, + }, + { + "case": { + "$eq": [ + "$$member.status", + "rejected", + ] + }, + "then": 1, + }, + { + "case": { + "$eq": [ + "$$member.status", + "refused", + ] + }, + "then": 2, + }, + { + "case": { + "$eq": [ + "$$member.status", + "effective", + ] + }, + "then": 3, + }, + { + "case": { + "$eq": [ + "$$member.status", + "draft", + ] + }, + "then": 4, + }, + ], + "default": 5, # handle unexpected statuses + } + } + }, + ] + }, + } + } + } + }, + { + "$set": { + "members": { + "$sortArray": {"input": "$members", "sortBy": {"sortKey": 1}} + } + } + }, + { + "$project": { + "members": { + "$map": { + "input": "$members", + "as": "member", + "in": { + "_id": "$$member._id", + "status": "$$member.status", + "duration": "$$member.duration", + "mode": "$$member.mode", + }, + } + }, + "name": True, + "description": True, + "status": True, + "date": True, + "type": True, + "special": True, + "creator": True, + "updatedAt": True, + "registration": True, + } + }, + ] + activity = await db.zvms.activities.aggregate(pipeline).to_list(None) + activity = activity[0] + if not activity: raise HTTPException(status_code=404, detail="Activity not found") @@ -362,7 +484,6 @@ async def user_activity_signup( detail="Permission denied, cannot be appended to this activity.", ) elif "department" in user["per"] or "admin" in user["per"]: - print("this one") status = ( MemberActivityStatus.effective if activity["type"] == ActivityType.special @@ -526,18 +647,20 @@ async def user_impression_edit( if user_activity is None: raise HTTPException(status_code=404, detail="User not found in activity") - user_activity = user_activity['members'][0] + user_activity = user_activity["members"][0] - history = ActivityMemberHistory(impression=user_activity['impression'], - duration=user_activity['duration'], - action=user_activity['status'], - # ISO-8601 - time=datetime.now().isoformat(), - actioner=user['id']) + history = ActivityMemberHistory( + impression=user_activity["impression"], + duration=user_activity["duration"], + action=user_activity["status"], + # ISO-8601 + time=datetime.now().isoformat(), + actioner=user["id"], + ) await db.zvms.activities.update_one( {"_id": validate_object_id(activity_oid), "members._id": id}, - {"$push": {"members.$.history": history.model_dump()}} + {"$push": {"members.$.history": history.model_dump()}}, ) return { @@ -628,18 +751,20 @@ async def user_status_edit( if user_activity is None: raise HTTPException(status_code=404, detail="User not found in activity") - user_activity = user_activity['members'][0] + user_activity = user_activity["members"][0] - history = ActivityMemberHistory(impression=user_activity['impression'], - duration=user_activity['duration'], - action=user_activity['status'], - # ISO-8601 - time=datetime.now().isoformat(), - actioner=user['id']) + history = ActivityMemberHistory( + impression=user_activity["impression"], + duration=user_activity["duration"], + action=user_activity["status"], + # ISO-8601 + time=datetime.now().isoformat(), + actioner=user["id"], + ) await db.zvms.activities.update_one( {"_id": validate_object_id(activity_oid), "members._id": user_oid}, - {"$push": {"members.$.history": history.model_dump()}} + {"$push": {"members.$.history": history.model_dump()}}, ) return { @@ -654,7 +779,10 @@ class PutDuration(BaseModel): @router.put("/{activity_oid}/member/{user_oid}/duration") async def user_duration_edit( - activity_oid: str, user_oid: str, payload: PutDuration, user=Depends(get_current_user) + activity_oid: str, + user_oid: str, + payload: PutDuration, + user=Depends(get_current_user), ): """ User modify activity status @@ -681,10 +809,7 @@ async def user_duration_edit( raise HTTPException(status_code=400, detail="User not in activity") # Check user status - if ( - "auditor" not in user["per"] - and "admin" not in user["per"] - ): + if "auditor" not in user["per"] and "admin" not in user["per"]: raise HTTPException( status_code=403, detail="Permission denied, not enough permission" ) @@ -706,7 +831,6 @@ async def user_duration_edit( if member is None: raise HTTPException(status_code=400, detail="User not in activity") - # Modify user duration await db.zvms.activities.update_one( {"_id": validate_object_id(activity_oid), "members._id": user_oid}, @@ -720,18 +844,20 @@ async def user_duration_edit( if user_activity is None: raise HTTPException(status_code=404, detail="User not found in activity") - user_activity = user_activity['members'][0] + user_activity = user_activity["members"][0] - history = ActivityMemberHistory(impression=user_activity['impression'], - duration=user_activity['duration'], - action=user_activity['status'], - # ISO-8601 - time=datetime.now().isoformat(), - actioner=user['id']) + history = ActivityMemberHistory( + impression=user_activity["impression"], + duration=user_activity["duration"], + action=user_activity["status"], + # ISO-8601 + time=datetime.now().isoformat(), + actioner=user["id"], + ) await db.zvms.activities.update_one( {"_id": validate_object_id(activity_oid), "members._id": user_oid}, - {"$push": {"members.$.history": history.model_dump()}} + {"$push": {"members.$.history": history.model_dump()}}, ) return { diff --git a/routers/groups_router.py b/routers/groups_router.py index dcf4981..04c9c81 100644 --- a/routers/groups_router.py +++ b/routers/groups_router.py @@ -41,7 +41,7 @@ async def get_groups(page: int = -1, perpage: int = 10, user=Depends(get_current if len(user["per"]) == 0: raise HTTPException(status_code=403, detail="Permission denied") - count = await db.zvms.groups.count_documents() + count = await db.zvms.groups.count_documents({}) pipeline = [ {"$sort": {"name": 1}}, @@ -70,6 +70,9 @@ async def get_group(group_id: str): result = await db.zvms.groups.find_one({"_id": ObjectId(group_id)}) + if result is None: + raise HTTPException(status_code=404, detail="Group not found") + result["_id"] = str(result["_id"]) return { @@ -133,9 +136,13 @@ async def get_users_in_class(group_id: str, page: int = -1, perpage: int = 10, q same_class = False if 'secretary' in user['per']: user = await db.zvms.users.find_one({'_id': ObjectId(user['_id'])}) + if user is None: + raise HTTPException(status_code=404, detail='User not found') classid = user['group'] if classid == group_id: same_class = True + if user is None: + raise HTTPException(status_code=404, detail='User not found') if not 'admin' in user['per'] and not 'auditor' in user['per'] and not 'department' in user['per'] and (not 'secretary' in user['per'] or not same_class): raise HTTPException(status_code=403, detail='Permission denied') count = await db.zvms.users.count_documents({'group': group_id}) From 664dc9e4a1a81d1469e5754534156d363bf86693 Mon Sep 17 00:00:00 2001 From: Wu Chengyu <54303040+7086cmd@users.noreply.github.com> Date: Thu, 2 May 2024 23:42:59 +0800 Subject: [PATCH 3/3] feat: add support for group actions --- routers/groups_router.py | 94 ++++++++++++++++++++++----------- routers/images_router.py | 7 +-- routers/notifications_router.py | 19 +++++-- routers/trophies_router.py | 14 +++++ routers/users_router.py | 93 ++++++++++++++++---------------- 5 files changed, 144 insertions(+), 83 deletions(-) diff --git a/routers/groups_router.py b/routers/groups_router.py index 04c9c81..dd256a3 100644 --- a/routers/groups_router.py +++ b/routers/groups_router.py @@ -5,7 +5,7 @@ from pydantic import BaseModel from util.get_class import get_activities_related_to_user -from utils import compulsory_temporary_token, get_current_user +from utils import compulsory_temporary_token, get_current_user, validate_object_id router = APIRouter() @@ -33,7 +33,13 @@ async def create_group(payload: Group, user=Depends(get_current_user)): @router.get("") -async def get_groups(page: int = -1, perpage: int = 10, user=Depends(get_current_user)): +async def get_groups( + page: int = 1, + perpage: int = 10, + type="all", + search="", + user=Depends(get_current_user), +): """ Get all groups """ @@ -41,17 +47,34 @@ async def get_groups(page: int = -1, perpage: int = 10, user=Depends(get_current if len(user["per"]) == 0: raise HTTPException(status_code=403, detail="Permission denied") - count = await db.zvms.groups.count_documents({}) + if type == "all": + target = ["permission", "class"] + elif type == "permission": + target = ["permission"] + elif type == "class": + target = ["class"] + else: + raise HTTPException(status_code=400, detail="Invalid type") + + count = await db.zvms.groups.count_documents( + {"name": {"$regex": search, "$options": "i"}} + ) pipeline = [ + { + "$match": { + "type": {"$in": target}, + "name": {"$regex": search, "$options": "i"}, + }, + }, + {"$project": {"description": 0}}, {"$sort": {"name": 1}}, - {"$skip": (page - 1) * perpage}, - {"$limit": perpage}, + {"$skip": 0 if page < 1 else (page - 1) * perpage}, + {"$limit": count if page < 1 else perpage}, ] result = await db.zvms.groups.aggregate(pipeline).to_list(None) - for group in result: group["_id"] = str(group["_id"]) @@ -59,6 +82,7 @@ async def get_groups(page: int = -1, perpage: int = 10, user=Depends(get_current "status": "ok", "code": 200, "data": result, + "metadata": {"size": count}, } @@ -98,7 +122,7 @@ async def update_group_name( raise HTTPException(status_code=403, detail="Permission denied") await db.zvms.groups.update_one( - {"_id": ObjectId(group_id)}, {"$set": {"name": payload.name}} + {"_id": validate_object_id(group_id)}, {"$set": {"name": payload.name}} ) return { @@ -110,10 +134,11 @@ async def update_group_name( @router.get("/{group_id}/activity") async def get_class_activities( group_id: str, - page: int = -1, + page: int = 1, perpage: int = 10, query: str = "", - user=Depends(get_current_user)): + user=Depends(get_current_user), +): """ Get activities related to a group """ @@ -128,39 +153,48 @@ async def get_class_activities( } -@router.get('/{group_id}/user') -async def get_users_in_class(group_id: str, page: int = -1, perpage: int = 10, query: str = '', user=Depends(get_current_user)): - ''' +@router.get("/{group_id}/user") +async def get_users_in_class( + group_id: str, + page: int = 1, + perpage: int = 10, + search: str = "", + user=Depends(get_current_user), +): + """ Get users in a class - ''' + """ same_class = False - if 'secretary' in user['per']: - user = await db.zvms.users.find_one({'_id': ObjectId(user['_id'])}) + if "secretary" in user["per"]: + user = await db.zvms.users.find_one({"_id": ObjectId(user["_id"])}) if user is None: - raise HTTPException(status_code=404, detail='User not found') - classid = user['group'] + raise HTTPException(status_code=404, detail="User not found") + classid = user["group"] if classid == group_id: same_class = True if user is None: - raise HTTPException(status_code=404, detail='User not found') - if not 'admin' in user['per'] and not 'auditor' in user['per'] and not 'department' in user['per'] and (not 'secretary' in user['per'] or not same_class): - raise HTTPException(status_code=403, detail='Permission denied') - count = await db.zvms.users.count_documents({'group': group_id}) + raise HTTPException(status_code=404, detail="User not found") + if ( + not "admin" in user["per"] + and not "auditor" in user["per"] + and not "department" in user["per"] + and (not "secretary" in user["per"] or not same_class) + ): + raise HTTPException(status_code=403, detail="Permission denied") + count = await db.zvms.users.count_documents( + {"group": group_id, "name": {"$regex": search, "$options": "i"}} + ) pipeline = [ - {"$match": {"group": group_id}}, - {"$sort": {"name": 1}}, + {"$match": {"group": group_id, "name": {"$regex": search, "$options": "i"}}}, + {"$sort": {"id": 1}}, {"$skip": (page - 1) * perpage}, {"$limit": perpage}, ] result = await db.zvms.users.aggregate(pipeline).to_list(None) for user in result: - user['_id'] = str(user['_id']) - return { - 'status': 'ok', - 'code': 200, - 'data': result, - 'metadata': {'size': count} - } + user["_id"] = str(user["_id"]) + return {"status": "ok", "code": 200, "data": result, "metadata": {"size": count}} + class PutGroupDescription(BaseModel): description: str diff --git a/routers/images_router.py b/routers/images_router.py index 96e3034..ea14b2d 100644 --- a/routers/images_router.py +++ b/routers/images_router.py @@ -43,6 +43,8 @@ async def upload_image(file: UploadFile, user=Depends(get_current_user)): @router.get("/{image_id}/data") async def get_image(image_id: str): data = await db.zvms.images.find_one({"_id": validate_object_id(image_id)}) + if data is None: + raise HTTPException(status_code=404, detail="Image not found") image = image_storage.getBBImage(data['id']) if image.status_code != 200: raise HTTPException(status_code=image.status_code, detail=image.text) @@ -57,10 +59,9 @@ def generate(): @router.delete("/{image_id}") async def delete_image(image_id: str, user=Depends(compulsory_temporary_token)): - image = db.zvms.images.find_one({"id": image_id}) - if not image: - raise HTTPException(status_code=404, detail="Image not found") image = await db.zvms.images.find_one({"_id": validate_object_id(image_id)}) + if image is None: + raise HTTPException(status_code=404, detail="Image not found") image_storage.remove(image['id']) await db.zvms.images.delete_one({"_id": validate_object_id(image["_id"])}) return {"status": "ok", "code": 200} diff --git a/routers/notifications_router.py b/routers/notifications_router.py index 963e536..ac777e5 100755 --- a/routers/notifications_router.py +++ b/routers/notifications_router.py @@ -1,3 +1,4 @@ +from datetime import datetime from fastapi import APIRouter, HTTPException, Depends, Request from typings.notification import Notification from utils import compulsory_temporary_token, get_current_user, validate_object_id @@ -99,12 +100,20 @@ async def update_notification_content( item = await db.zvms.notifications.find_one( {"_id": validate_object_id(notification_oid)} ) - if user["id"] != item["publisher"] and "admin" not in user["per"]: + if item is None: + raise HTTPException(status_code=404, detail="Notification not found") + if user["id"] != item["publisher"] or "admin" not in user["per"]: + raise HTTPException(status_code=403, detail="Permission denied") + actioner = await db.zvms.users.find_one({"_id": item["publisher"]}) + if actioner is None: + raise HTTPException(status_code=404, detail="User not found") + msg = f"{actioner['name']} modified notification at {datetime.now()}" + if user["id"] != item["publisher"] or "admin" not in user["per"]: raise HTTPException(status_code=403, detail="Permission denied") # Update notification content await db.zvms.notifications.update_one( {"_id": validate_object_id(notification_oid)}, - {"$set": {"content": request.content}}, + {"$set": {"content": request.content + "\n" + msg}}, ) @@ -118,7 +127,9 @@ async def update_notification_title( item = await db.zvms.notifications.find_one( {"_id": validate_object_id(notification_oid)} ) - if user["id"] != item["publisher"] and "admin" not in user["per"]: + if item is None: + raise HTTPException(status_code=404, detail="Notification not found") + if user["id"] != item["publisher"] or "admin" not in user["per"]: raise HTTPException(status_code=403, detail="Permission denied") # Update notification title await db.zvms.notifications.update_one( @@ -137,6 +148,8 @@ async def delete_notification( item = await db.zvms.notifications.find_one( {"_id": validate_object_id(notification_oid)} ) + if item is None: + raise HTTPException(status_code=404, detail="Notification not found") if user["id"] != item["publisher"] and "admin" not in user["per"]: raise HTTPException(status_code=403, detail="Permission denied") # Remove notification diff --git a/routers/trophies_router.py b/routers/trophies_router.py index 86558fb..a045065 100644 --- a/routers/trophies_router.py +++ b/routers/trophies_router.py @@ -69,6 +69,8 @@ async def get_trophy(trophy_oid: str, user=Depends(get_current_user)): """ # Get trophy result = await db.zvms.trophies.find_one({"_id": validate_object_id(trophy_oid)}) + if result is None: + raise HTTPException(status_code=404, detail="Not Found") result["_id"] = str(result["_id"]) return { "status": "ok", @@ -125,6 +127,8 @@ async def delete_trophy(trophy_oid: str, user=Depends(compulsory_temporary_token Delete Trophy """ trophy = await db.zvms.trophies.find_one({"_id": validate_object_id(trophy_oid)}) + if trophy is None: + raise HTTPException(status_code=404, detail="Not Found") if "admin" not in user["per"] and user["id"] != trophy["creator"]: raise HTTPException(status_code=403, detail="Permission denied") # Delete trophy @@ -177,6 +181,8 @@ async def update_trophy_member_status( Update Trophy Member Status """ trophy = await db.zvms.trophies.find_one({"_id": validate_object_id(trophy_oid)}) + if trophy is None: + raise HTTPException(status_code=404, detail="Not Found") if "admin" in user["per"]: pass elif "department" in user["per"] and user["id"] == trophy["create"]: @@ -223,6 +229,8 @@ async def delete_trophy_member( Delete Trophy Member """ trophy = await db.zvms.trophies.find_one({"_id": validate_object_id(trophy_oid)}) + if trophy is None: + raise HTTPException(status_code=404, detail="Not Found") if ( "admin" not in user["per"] and not ("department" in user["per"] and user["id"] == trophy["creator"]) @@ -248,6 +256,8 @@ async def add_trophy_award( Add Trophy Award """ trophy = await db.zvms.trophies.find_one({"_id": validate_object_id(trophy_oid)}) + if trophy is None: + raise HTTPException(status_code=404, detail="Not Found") if "admin" not in user["per"] and user["id"] != trophy["creator"]: raise HTTPException(status_code=403, detail="Permission denied") # Add trophy award @@ -266,6 +276,8 @@ async def delete_trophy_award( Delete Trophy Award """ trophy = await db.zvms.trophies.find_one({"_id": validate_object_id(trophy_oid)}) + if trophy is None: + raise HTTPException(status_code=404, detail="Not Found") if "admin" not in user["per"] and user["id"] != trophy["creator"]: raise HTTPException(status_code=403, detail="Permission denied") # Delete trophy award @@ -293,6 +305,8 @@ async def update_trophy_award_duration( Update Trophy Award Duration """ trophy = await db.zvms.trophies.find_one({"_id": validate_object_id(trophy_oid)}) + if trophy is None: + raise HTTPException(status_code=404, detail="Not Found") if "admin" not in user["per"] and user["id"] != trophy["creator"]: raise HTTPException(status_code=403, detail="Permission denied") # Update trophy award duration diff --git a/routers/users_router.py b/routers/users_router.py index f7ed430..ff54f3a 100755 --- a/routers/users_router.py +++ b/routers/users_router.py @@ -1,30 +1,15 @@ -import time -from fastapi import UploadFile -from fastapi import APIRouter, HTTPException, Depends, Form, Request -from typing import List, Optional -from fastapi.responses import StreamingResponse +from fastapi import APIRouter, HTTPException, Depends from pydantic import BaseModel -from util import image_process, image_storage from util.calculate import calculate_time -from util.cases import kebab_case_to_camel_case from util.group import is_in_a_same_class from utils import ( compulsory_temporary_token, get_current_user, - timestamp_change, validate_object_id, - get_img_token, - randomString, ) -from datetime import datetime, timedelta -from jose import JWTError, jwt from database import db -from bson import ObjectId -import settings from util.cert import get_hashed_password_by_cert, validate_by_cert -import os -import config router = APIRouter() @@ -61,9 +46,17 @@ async def change_password( user_oid: str, credential: PutPassword, user=Depends(compulsory_temporary_token) ): # Validate user's permission - secretary = "secretary" in user["per"] and (is_in_a_same_class(user["id"], user_oid)) - modification = user['id'] == user_oid and user['scope'] == 'temporary_token' - if "admin" not in user["per"] and (not modification) and "department" not in user["per"] and "auditor" not in user["per"] and (not secretary): + secretary = "secretary" in user["per"] and ( + is_in_a_same_class(user["id"], user_oid) + ) + modification = user["id"] == user_oid and user["scope"] == "temporary_token" + if ( + "admin" not in user["per"] + and (not modification) + and "department" not in user["per"] + and "auditor" not in user["per"] + and (not secretary) + ): raise HTTPException(status_code=403, detail="Permission denied") password = await get_hashed_password_by_cert(credential.credential) @@ -121,6 +114,9 @@ async def read_user(user_oid: str): # Read user's information user = await db.zvms.users.find_one({"_id": validate_object_id(user_oid)}) + if user is None: + raise HTTPException(status_code=404, detail="User not found") + user["_id"] = str(user["_id"]) del user["password"] return { @@ -129,6 +125,36 @@ async def read_user(user_oid: str): "data": user, } +class PutUser(BaseModel): + name: str + id: str + groups: list[str] + +@router.put("/{user_oid}") +async def update_user(user_oid: str, user_struct: PutUser, user=Depends(compulsory_temporary_token)): + """ + Update user's information + """ + # Check user's permission + if "admin" not in user["per"]: + raise HTTPException(status_code=403, detail="Permission denied") + + # Update user's information + await db.zvms.users.update_one( + {"_id": validate_object_id(user_oid)}, + { + "$set": { + "name": user_struct.name, + "id": user_struct.id, + "group": user_struct.groups, + } + }, + ) + + return { + "status": "ok", + "code": 200, + } @router.post("/{user_oid}/group") async def add_user_to_group( @@ -161,7 +187,6 @@ async def remove_user_from_group( @router.get("/{user_oid}/activity") async def read_user_activity( user_oid: str, - registration: bool = False, # 是否返回报名的义工, parameters user=Depends(get_current_user), page: int = -1, perpage: int = 10, @@ -263,7 +288,7 @@ async def read_notifications( "$or": [ {"receivers": str(user_oid)}, {"global": True}, - {"publisher": str(user_oid)} + {"publisher": str(user_oid)}, ], } ) @@ -286,29 +311,3 @@ async def read_notifications( "size": count, }, } - - -@router.get("/{user_oid}/image") -async def read_images( - user_oid: str, - user=Depends(get_current_user), - page: int = 1, - perpage: int = 10, -): - if user["id"] != user_oid and "admin" not in user["per"]: - raise HTTPException(status_code=403, detail="Permission denied") - user = ( - await db.zvms.images.find( - { - "uploader": user_oid, - } - ) - .skip(0 if page == -1 else (page - 1) * perpage) - .limit(0 if page == -1 else perpage) - .to_list(None if page == -1 else perpage) - ) - return { - "status": "ok", - "code": 200, - "data": user["images"], - }