feat: implement backend avatar update

This commit is contained in:
swve 2024-01-20 00:41:37 +01:00
parent cec178c479
commit a51a128fcb
11 changed files with 103 additions and 19 deletions

View file

@ -1,5 +1,5 @@
from typing import Literal
from fastapi import APIRouter, Depends, Request
from fastapi import APIRouter, Depends, Request, UploadFile
from sqlmodel import Session
from src.security.auth import get_current_user
from src.core.events.database import get_db_session
@ -22,6 +22,7 @@ from src.services.users.users import (
read_user_by_id,
read_user_by_uuid,
update_user,
update_user_avatar,
update_user_password,
)
@ -137,6 +138,20 @@ async def api_update_user(
return await update_user(request, db_session, user_id, current_user, user_object)
@router.put("/update_avatar/{user_id}", response_model=UserRead, tags=["users"])
async def api_update_avatar_user(
*,
request: Request,
db_session: Session = Depends(get_db_session),
current_user: PublicUser = Depends(get_current_user),
avatar_file: UploadFile | None = None,
) -> UserRead:
"""
Update User
"""
return await update_user_avatar(request, db_session, current_user, avatar_file)
@router.put("/change_password/{user_id}", response_model=UserRead, tags=["users"])
async def api_update_user_password(
*,

View file

@ -50,7 +50,8 @@ async def upload_file_and_return_file_object(
await upload_content(
f"courses/{course_uuid}/activities/{activity_uuid}/dynamic/blocks/{type_of_block}/{block_id}",
org_uuid=org_uuid,
type_of_dir='orgs',
uuid=org_uuid,
file_binary=file_binary,
file_and_format=f"{file_id}.{file_format}",
)

View file

@ -8,6 +8,7 @@ async def upload_pdf(pdf_file, activity_uuid, org_uuid, course_uuid):
try:
await upload_content(
f"courses/{course_uuid}/activities/{activity_uuid}/documentpdf",
"orgs",
org_uuid,
contents,
f"documentpdf.{pdf_format}",

View file

@ -10,6 +10,7 @@ async def upload_video(video_file, activity_uuid, org_uuid, course_uuid):
await upload_content(
f"courses/{course_uuid}/activities/{activity_uuid}/video",
org_uuid,
org_uuid,
contents,
f"video.{video_format}",
)

View file

@ -213,7 +213,7 @@ async def update_course_thumbnail(
if thumbnail_file and thumbnail_file.filename:
name_in_disk = f"{course_uuid}_thumbnail_{uuid4()}.{thumbnail_file.filename.split('.')[-1]}"
await upload_thumbnail(
thumbnail_file, name_in_disk, org.org_uuid, course.course_uuid
thumbnail_file, name_in_disk, 'users', course.course_uuid
)
# Update course

View file

@ -1,13 +1,13 @@
from src.services.utils.upload_content import upload_content
async def upload_thumbnail(thumbnail_file, name_in_disk, org_id, course_id):
async def upload_thumbnail(thumbnail_file, name_in_disk, org_uuid, course_id):
contents = thumbnail_file.file.read()
try:
await upload_content(
f"courses/{course_id}/thumbnails",
org_id,
"orgs",
org_uuid,
contents,
f"{name_in_disk}",
)

View file

@ -10,6 +10,7 @@ async def upload_org_logo(logo_file, org_uuid):
await upload_content(
"logos",
org_uuid,
org_uuid,
contents,
name_in_disk,
)

View file

@ -0,0 +1,16 @@
from src.services.utils.upload_content import upload_content
async def upload_avatar(avatar_file, name_in_disk, user_uuid):
contents = avatar_file.file.read()
try:
await upload_content(
f"avatars",
"users",
user_uuid,
contents,
f"{name_in_disk}",
)
except Exception:
return {"message": "There was an error uploading the file"}

View file

@ -1,13 +1,14 @@
from datetime import datetime
from typing import Literal
from uuid import uuid4
from fastapi import HTTPException, Request, status
from fastapi import HTTPException, Request, UploadFile, status
from sqlmodel import Session, select
from src.services.users.avatars import upload_avatar
from src.db.roles import Role, RoleRead
from src.security.rbac.rbac import (
authorization_verify_based_on_roles_and_authorship,
authorization_verify_if_user_is_anon,
)
)
from src.db.organizations import Organization, OrganizationRead
from src.db.users import (
AnonymousUser,
@ -195,6 +196,49 @@ async def update_user(
return user
async def update_user_avatar(
request: Request,
db_session: Session,
current_user: PublicUser | AnonymousUser,
avatar_file: UploadFile | None = None,
):
# Get user
statement = select(User).where(User.id == current_user.id)
user = db_session.exec(statement).first()
if not user:
raise HTTPException(
status_code=400,
detail="User does not exist",
)
# RBAC check
await rbac_check(request, current_user, "update", user.user_uuid, db_session)
# Upload thumbnail
if avatar_file and avatar_file.filename:
name_in_disk = f"{user.user_uuid}_avatar_{uuid4()}.{avatar_file.filename.split('.')[-1]}"
await upload_avatar(avatar_file, name_in_disk, user.user_uuid)
# Update course
if name_in_disk:
user.avatar_image = name_in_disk
else:
raise HTTPException(
status_code=500,
detail="Issue with Avatar upload",
)
# Update user in database
db_session.add(user)
db_session.commit()
db_session.refresh(user)
user = UserRead.from_orm(user)
return user
async def update_user_password(
request: Request,
db_session: Session,

View file

@ -1,3 +1,4 @@
from typing import Literal
import boto3
from botocore.exceptions import ClientError
import os
@ -6,7 +7,11 @@ from config.config import get_learnhouse_config
async def upload_content(
directory: str, org_uuid: str, file_binary: bytes, file_and_format: str
directory: str,
type_of_dir: Literal["orgs", "users"],
uuid: str, # org_uuid or user_uuid
file_binary: bytes,
file_and_format: str,
):
# Get Learnhouse Config
learnhouse_config = get_learnhouse_config()
@ -16,12 +21,12 @@ async def upload_content(
if content_delivery == "filesystem":
# create folder for activity
if not os.path.exists(f"content/{org_uuid}/{directory}"):
if not os.path.exists(f"content/{type_of_dir}/{uuid}/{directory}"):
# create folder for activity
os.makedirs(f"content/{org_uuid}/{directory}")
os.makedirs(f"content/{type_of_dir}/{uuid}/{directory}")
# upload file to server
with open(
f"content/{org_uuid}/{directory}/{file_and_format}",
f"content/{type_of_dir}/{uuid}/{directory}/{file_and_format}",
"wb",
) as f:
f.write(file_binary)
@ -37,13 +42,13 @@ async def upload_content(
)
# Create folder for activity
if not os.path.exists(f"content/{org_uuid}/{directory}"):
if not os.path.exists(f"content/{type_of_dir}/{uuid}/{directory}"):
# create folder for activity
os.makedirs(f"content/{org_uuid}/{directory}")
os.makedirs(f"content/{type_of_dir}/{uuid}/{directory}")
# Upload file to server
with open(
f"content/{org_uuid}/{directory}/{file_and_format}",
f"content/{type_of_dir}/{uuid}/{directory}/{file_and_format}",
"wb",
) as f:
f.write(file_binary)
@ -52,9 +57,9 @@ async def upload_content(
print("Uploading to s3 using boto3...")
try:
s3.upload_file(
f"content/{org_uuid}/{directory}/{file_and_format}",
f"content/{type_of_dir}/{uuid}/{directory}/{file_and_format}",
"learnhouse-media",
f"content/{org_uuid}/{directory}/{file_and_format}",
f"content/{type_of_dir}/{uuid}/{directory}/{file_and_format}",
)
except ClientError as e:
print(e)
@ -63,7 +68,7 @@ async def upload_content(
try:
s3.head_object(
Bucket="learnhouse-media",
Key=f"content/{org_uuid}/{directory}/{file_and_format}",
Key=f"content/{type_of_dir}/{uuid}/{directory}/{file_and_format}",
)
print("File upload successful!")
except Exception as e: