🔒️ use user_id instead of username

This commit is contained in:
swve 2022-08-13 22:40:30 +02:00
parent 3d542b0055
commit 040f91b608
7 changed files with 114 additions and 57 deletions

View file

@ -26,26 +26,34 @@ async def api_get_user_by_username(username: str):
return await get_user(username) return await get_user(username)
@router.get("/user_id/{user_id}")
async def api_get_user_by_userid(user_id: str):
"""
Get single user by user_id
"""
return await get_user_by_userid(user_id)
@router.post("/") @router.post("/")
async def api_create_user(user_object: UserInDB): async def api_create_user(user_object: UserWithPassword):
""" """
Create new user Create new user
""" """
return await create_user(user_object) return await create_user(user_object)
@router.delete("/username/{username}") @router.delete("/user_id/{user_id}")
async def api_delete_user(username: str): async def api_delete_user(user_id: str):
""" """
Delete user by ID Delete user by ID
""" """
return await delete_user(username) return await delete_user(user_id)
@router.put("/username/{username}") @router.put("/user_id/{user_id}")
async def api_update_user(user_object: UserInDB): async def api_update_user(user_object: UserWithPassword, user_id: str):
""" """
Update user by ID Update user by ID
""" """
return await update_user(user_object) return await update_user(user_id, user_object)

View file

@ -23,7 +23,6 @@ class TokenData(BaseModel):
#### Classes #################################################### #### Classes ####################################################
async def authenticate_user(username: str, password: str): async def authenticate_user(username: str, password: str):
user = await security_get_user(username) user = await security_get_user(username)
if not user: if not user:
@ -58,7 +57,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme)):
token_data = TokenData(username=username) token_data = TokenData(username=username)
except JWTError: except JWTError:
raise credentials_exception raise credentials_exception
user = await get_user(username=token_data.username) user = await security_get_user(username=token_data.username)
if user is None: if user is None:
raise credentials_exception raise credentials_exception
return User(**user.dict()) return PublicUser(**user.dict())

View file

@ -78,14 +78,14 @@ async def create_course(course_object: Course, current_user: User):
# generate course_id with uuid4 # generate course_id with uuid4
course_id = str(f"course_{uuid4()}") course_id = str(f"course_{uuid4()}")
hasRoleRights = await verify_user_rights_with_roles("create", current_user.username, course_id) hasRoleRights = await verify_user_rights_with_roles("create", current_user.user_id, course_id)
if not hasRoleRights: if not hasRoleRights:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action") status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action")
course = CourseInDB(course_id=course_id, authors=[ course = CourseInDB(course_id=course_id, authors=[
current_user.username], creationDate=str(datetime.now()), updateDate=str(datetime.now()), **course_object.dict()) current_user.user_id], creationDate=str(datetime.now()), updateDate=str(datetime.now()), **course_object.dict())
course_in_db = courses.insert_one(course.dict()) course_in_db = courses.insert_one(course.dict())
@ -185,7 +185,7 @@ async def create_coursechapter(coursechapter_object: CourseChapter, course_id: s
# generate coursechapter_id with uuid4 # generate coursechapter_id with uuid4
coursechapter_id = str(f"coursechapter_{uuid4()}") coursechapter_id = str(f"coursechapter_{uuid4()}")
hasRoleRights = await verify_user_rights_with_roles("create", current_user.username, coursechapter_id) hasRoleRights = await verify_user_rights_with_roles("create", current_user.user_id, coursechapter_id)
if not hasRoleRights: if not hasRoleRights:
raise HTTPException( raise HTTPException(
@ -278,8 +278,8 @@ async def verify_rights(course_id: str, current_user: User, action: str):
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail=f"Course/CourseChapter does not exist") status_code=status.HTTP_409_CONFLICT, detail=f"Course/CourseChapter does not exist")
hasRoleRights = await verify_user_rights_with_roles(action, current_user.username, course_id) hasRoleRights = await verify_user_rights_with_roles(action, current_user.user_id, course_id)
isAuthor = current_user.username in course["authors"] isAuthor = current_user.user_id in course["authors"]
if not hasRoleRights and not isAuthor: if not hasRoleRights and not isAuthor:
raise HTTPException( raise HTTPException(

View file

@ -34,7 +34,7 @@ async def get_house(house_id: str, current_user: User):
house = houses.find_one({"house_id": house_id}) house = houses.find_one({"house_id": house_id})
# verify house rights # verify house rights
await verify_house_rights(house_id, current_user,"read") await verify_house_rights(house_id, current_user, "read")
if not house: if not house:
raise HTTPException( raise HTTPException(
@ -58,15 +58,15 @@ async def create_house(house_object: House, current_user: User):
# generate house_id with uuid4 # generate house_id with uuid4
house_id = str(f"house_{uuid4()}") house_id = str(f"house_{uuid4()}")
hasRoleRights = await verify_user_rights_with_roles("create", current_user.username, house_id) hasRoleRights = await verify_user_rights_with_roles("create", current_user.user_id, house_id)
if not hasRoleRights: if not hasRoleRights:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action") status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action")
house = HouseInDB(house_id=house_id, owners=[ house = HouseInDB(house_id=house_id, owners=[
current_user.username], admins=[ current_user.user_id], admins=[
current_user.username], **house_object.dict()) current_user.user_id], **house_object.dict())
house_in_db = houses.insert_one(house.dict()) house_in_db = houses.insert_one(house.dict())
@ -81,7 +81,7 @@ async def update_house(house_object: House, house_id: str, current_user: User):
await check_database() await check_database()
# verify house rights # verify house rights
await verify_house_rights(house_id, current_user,"update") await verify_house_rights(house_id, current_user, "update")
houses = learnhouseDB["houses"] houses = learnhouseDB["houses"]
@ -107,7 +107,7 @@ async def delete_house(house_id: str, current_user: User):
await check_database() await check_database()
# verify house rights # verify house rights
await verify_house_rights(house_id, current_user,"delete") await verify_house_rights(house_id, current_user, "delete")
houses = learnhouseDB["houses"] houses = learnhouseDB["houses"]
@ -148,8 +148,8 @@ async def verify_house_rights(house_id: str, current_user: User, action: str):
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="House does not exist") status_code=status.HTTP_409_CONFLICT, detail="House does not exist")
hasRoleRights = await verify_user_rights_with_roles(action, current_user.username, house_id) hasRoleRights = await verify_user_rights_with_roles(action, current_user.user_id, house_id)
isOwner = current_user.username in house["owners"] isOwner = current_user.user_id in house["owners"]
if not hasRoleRights and not isOwner: if not hasRoleRights and not isOwner:
raise HTTPException( raise HTTPException(

View file

@ -55,8 +55,8 @@ async def create_org(org_object: Organization, current_user: User):
org_id = str(f"org_{uuid4()}") org_id = str(f"org_{uuid4()}")
org = OrganizationInDB(org_id=org_id, owners=[ org = OrganizationInDB(org_id=org_id, owners=[
current_user.username], admins=[ current_user.user_id], admins=[
current_user.username], **org_object.dict()) current_user.user_id], **org_object.dict())
org_in_db = orgs.insert_one(org.dict()) org_in_db = orgs.insert_one(org.dict())
@ -128,7 +128,7 @@ async def get_orgs(page: int = 1, limit: int = 10):
#### Security #################################################### #### Security ####################################################
async def verify_org_rights(org_id: str, current_user: User, action:str,): async def verify_org_rights(org_id: str, current_user: User, action: str,):
await check_database() await check_database()
orgs = learnhouseDB["organizations"] orgs = learnhouseDB["organizations"]
@ -138,8 +138,8 @@ async def verify_org_rights(org_id: str, current_user: User, action:str,):
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Organization does not exist") status_code=status.HTTP_409_CONFLICT, detail="Organization does not exist")
isOwner = current_user.username in org["owners"] isOwner = current_user.user_id in org["owners"]
hasRoleRights = await verify_user_rights_with_roles(action,current_user.username,org_id) hasRoleRights = await verify_user_rights_with_roles(action, current_user.user_id, org_id)
if not hasRoleRights and not isOwner: if not hasRoleRights and not isOwner:
raise HTTPException( raise HTTPException(

View file

@ -2,7 +2,7 @@ import json
from typing import List from typing import List
from uuid import uuid4 from uuid import uuid4
from pydantic import BaseModel from pydantic import BaseModel
from src.services.users import User from src.services.users import PublicUser, User
from src.services.database import check_database, learnhouseDB, learnhouseDB from src.services.database import check_database, learnhouseDB, learnhouseDB
from src.services.security import * from src.services.security import *
from src.services.houses import House from src.services.houses import House
@ -25,7 +25,7 @@ class Elements(BaseModel):
houses: List[str] houses: List[str]
collections: List[str] collections: List[str]
organizations: List[str] organizations: List[str]
coursechapters : List[str] coursechapters: List[str]
class Role(BaseModel): class Role(BaseModel):
@ -69,7 +69,7 @@ async def create_role(role_object: Role, current_user: User):
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Role name already exists") status_code=status.HTTP_409_CONFLICT, detail="Role name already exists")
await verify_user_permissions("create", current_user) await verify_user_permissions_on_roles("create", current_user)
# generate house_id with uuid4 # generate house_id with uuid4
role_id = str(f"role_{uuid4()}") role_id = str(f"role_{uuid4()}")
@ -90,7 +90,7 @@ async def update_role(role_object: House, role_id: str, current_user: User):
await check_database() await check_database()
# verify house rights # verify house rights
await verify_user_permissions("update", current_user) await verify_user_permissions_on_roles("update", current_user)
roles = learnhouseDB["roles"] roles = learnhouseDB["roles"]
@ -112,7 +112,7 @@ async def delete_role(role_id: str, current_user: User):
await check_database() await check_database()
# verify house rights # verify house rights
await verify_user_permissions("delete", current_user) await verify_user_permissions_on_roles("delete", current_user)
roles = learnhouseDB["roles"] roles = learnhouseDB["roles"]
@ -143,11 +143,11 @@ async def get_roles(page: int = 1, limit: int = 10):
#### Security #################################################### #### Security ####################################################
async def verify_user_permissions(action: str, current_user: User): async def verify_user_permissions_on_roles(action: str, current_user: PublicUser):
await check_database() await check_database()
users = learnhouseDB["users"] users = learnhouseDB["users"]
user = users.find_one({"username": current_user.username}) user = users.find_one({"user_id": current_user.user_id})
if not user: if not user:
raise HTTPException( raise HTTPException(

View file

@ -1,3 +1,4 @@
from uuid import uuid4
from pydantic import BaseModel from pydantic import BaseModel
from src.services.database import check_database, learnhouseDB, learnhouseDB from src.services.database import check_database, learnhouseDB, learnhouseDB
from src.services.security import * from src.services.security import *
@ -14,18 +15,31 @@ class User(BaseModel):
disabled: bool | None = None disabled: bool | None = None
avatar_url: str | None = None avatar_url: str | None = None
verified: bool verified: bool
created_date: str
user_type: str user_type: str
bio: str | None = None bio: str | None = None
class UserInDB(User): class UserWithPassword(User):
password: str password: str
class PublicUser(User):
user_id: str
creationDate: str
updateDate: str
class UserInDB(UserWithPassword):
user_id: str
password: str
creationDate: str
updateDate: str
#### Classes #################################################### #### Classes ####################################################
# TODO : user actions security # TODO : user actions security
async def get_user(username: str): async def get_user(username: str):
check_database() check_database()
users = learnhouseDB["users"] users = learnhouseDB["users"]
@ -40,6 +54,20 @@ async def get_user(username: str):
return user return user
async def get_user_by_userid(user_id: str):
check_database()
users = learnhouseDB["users"]
user = users.find_one({"user_id": user_id})
if not user:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="User does not exist")
user = User(**user)
return user
async def security_get_user(username: str): async def security_get_user(username: str):
check_database() check_database()
users = learnhouseDB["users"] users = learnhouseDB["users"]
@ -53,40 +81,58 @@ async def security_get_user(username: str):
return UserInDB(**user) return UserInDB(**user)
async def update_user(user_object: UserInDB): async def get_userid_by_username(username: str):
check_database() check_database()
users = learnhouseDB["users"] users = learnhouseDB["users"]
isUserAvailable = users.find_one({"username": user_object.username}) user = users.find_one({"username": username})
if not isUserAvailable: if not user:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="User does not exist") status_code=status.HTTP_409_CONFLICT, detail="User does not exist")
return user["user_id"]
async def update_user(user_id: str, user_object: UserWithPassword):
check_database()
users = learnhouseDB["users"]
isUserExists = users.find_one({"user_id": user_id})
isUsernameAvailable = users.find_one({"username": user_object.username})
if not isUserExists:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="User does not exist")
if isUsernameAvailable:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Username already used")
user_object.password = await security_hash_password(user_object.password) user_object.password = await security_hash_password(user_object.password)
updated_user = {"$set": user_object.dict()} updated_user = {"$set": user_object.dict()}
users.update_one({"username": user_object.username}, updated_user) users.update_one({"user_id": user_id}, updated_user)
return User(**user_object.dict()) return User(**user_object.dict())
async def delete_user(username: str): async def delete_user(user_id: str):
check_database() check_database()
users = learnhouseDB["users"] users = learnhouseDB["users"]
isUserAvailable = users.find_one({"username": username}) isUserAvailable = users.find_one({"user_id": user_id})
if not isUserAvailable: if not isUserAvailable:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="User does not exist") status_code=status.HTTP_409_CONFLICT, detail="User does not exist")
users.delete_one({"username": username}) users.delete_one({"user_id": user_id})
return {"detail": "User deleted"} return {"detail": "User deleted"}
async def create_user(user_object: UserInDB): async def create_user(user_object: UserWithPassword):
check_database() check_database()
users = learnhouseDB["users"] users = learnhouseDB["users"]
@ -94,15 +140,19 @@ async def create_user(user_object: UserInDB):
if isUserAvailable: if isUserAvailable:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="User already exists") status_code=status.HTTP_409_CONFLICT, detail="Username already exists")
# generate house_id with uuid4
user_id = str(f"user_{uuid4()}")
# lowercase username # lowercase username
user_object.username = user_object.username.lower() user_object.username = user_object.username.lower()
user_object.created_date = str(datetime.now())
user_object.password = await security_hash_password(user_object.password) user_object.password = await security_hash_password(user_object.password)
users.insert_one(user_object.dict()) user = UserInDB(user_id=user_id, creationDate=str(datetime.now()),
updateDate=str(datetime.now()), **user_object.dict())
return User(**user_object.dict()) user_in_db = users.insert_one(user.dict())
return User(**user.dict())