diff --git a/.env b/.env index 37a3948..6ff9514 100644 --- a/.env +++ b/.env @@ -1,9 +1,9 @@ # Domain # This would be set to the production domain with an env var on deployment -DOMAIN=philip-cat.com +DOMAIN=localhost # Environment: local, staging, production -ENVIRONMENT=staging +ENVIRONMENT=local PROJECT_NAME="All & One" STACK_NAME=allandonecms diff --git a/backend/app/api/routes/aboutUs.py b/backend/app/api/routes/aboutUs.py index f1c8009..ce7d3bf 100644 --- a/backend/app/api/routes/aboutUs.py +++ b/backend/app/api/routes/aboutUs.py @@ -32,7 +32,7 @@ async def create_aboutUs( Create new about us. """ validate_file_size_type(image) - imageUrl = await save_picture(file=image, folderName="tmp") + imageUrl = await save_picture(file=image, folder_name="tmp") # aboutus_in.image = imageUrl aboutUs_in = AboutUsCreate(description=description, image=imageUrl, index=index ,title=title) aboutUs = AboutUs.from_orm(aboutUs_in) @@ -57,7 +57,7 @@ async def edit_aboutUs( if image is not None: validate_file_size_type(image) - imageUrl = await save_picture(file=image, folderName="tmp") + imageUrl = await save_picture(file=image, folder_name="tmp") await del_picture(aboutUs.image) aboutUs_in = AboutsUpdate(description=description, image=imageUrl, index=index, title=title) else : diff --git a/backend/app/api/routes/image.py b/backend/app/api/routes/image.py index 9d57df4..bb13c6b 100644 --- a/backend/app/api/routes/image.py +++ b/backend/app/api/routes/image.py @@ -26,7 +26,7 @@ async def create_image( Create new image. """ validate_file_size_type(image) - imageUrl = await save_picture(file=image, folderName="tmp") + imageUrl = await save_picture(file=image, folder_name="tmp") image_in = ImageCreate(image=imageUrl, index=index, course_id=course_id) image = Image.from_orm(image_in) session.add(image) diff --git a/backend/app/api/routes/info_image.py b/backend/app/api/routes/info_image.py index 66aee4c..a29fea2 100644 --- a/backend/app/api/routes/info_image.py +++ b/backend/app/api/routes/info_image.py @@ -26,7 +26,7 @@ async def create_info_image( Create new image. """ validate_file_size_type(image) - imageUrl = await save_picture(file=image, folderName="tmp") + imageUrl = await save_picture(file=image, folder_name="tmp") info_image_in = Info_ImageCreate(image=imageUrl, index=index, course_id=course_id) info_image = Info_Image.from_orm(info_image_in) session.add(info_image) diff --git a/backend/app/utils.py b/backend/app/utils.py index 7446184..faad110 100644 --- a/backend/app/utils.py +++ b/backend/app/utils.py @@ -7,6 +7,7 @@ from datetime import datetime, timedelta, timezone from pathlib import Path from typing import Any from uuid import uuid4 +from botocore.exceptions import ClientError from PIL import Image, ImageTk import emails # type: ignore import jwt @@ -15,7 +16,9 @@ from jwt.exceptions import InvalidTokenError import filetype from app.core.config import settings -static = 'static' +static = "static" + + @dataclass class EmailData: html_content: str @@ -119,18 +122,30 @@ def verify_password_reset_token(token: str) -> str | None: return str(decoded_token["sub"]) except InvalidTokenError: return None - + + from fastapi import HTTPException, status from typing import IO import filetype def validate_file_size_type(file: IO): - FILE_SIZE = 5097152 # 2MB + FILE_SIZE = 5097152 # 2MB - accepted_file_types = ["image/png", "image/jpeg", "image/jpg", "image/heic", "image/heif", "image/heics", "png", - "jpeg", "jpg", "heic", "heif", "heics" - ] + accepted_file_types = [ + "image/png", + "image/jpeg", + "image/jpg", + "image/heic", + "image/heif", + "image/heics", + "png", + "jpeg", + "jpg", + "heic", + "heif", + "heics", + ] file_info = filetype.guess(file.file) if file_info is None: raise HTTPException( @@ -153,34 +168,55 @@ def validate_file_size_type(file: IO): for chunk in file.file: real_file_size += len(chunk) if real_file_size > FILE_SIZE: - raise HTTPException(status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, detail="Too large") - + raise HTTPException( + status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, detail="Too large" + ) + + # async def save_picture(file, folderName: str = '', fileName: str = None): # randon_uid = str(uuid4()) # _, f_ext = os.path.splitext(file.filename) - -# picture_name = (randon_uid if fileName==None else fileName.lower().replace(' ', '')) + f_ext + +# picture_name = (randon_uid if fileName==None else fileName.lower().replace(' ', '')) + f_ext # path = os.path.join(static,folderName) # if not os.path.exists(path): # os.makedirs(path) - + # picture_path = os.path.join(path,picture_name) # #output_size = (125,125) # img = Image.open(file.file) - + # #img.thumbnail(output_size) # img.save(picture_path) - + # return f'{static}/{folderName}/{picture_name}' -async def save_picture(file, folderName: str = "", fileName: str = None): - random_uid = str(uuid4()) - _, f_ext = os.path.splitext(file.filename) - picture_name = (fileName.lower().replace(" ", "") if fileName else random_uid) + f_ext +async def upload_file(file_name, bucket_name, object_name=None): + ConnectionUrl = f"https://{settings.AccountID}.r2.cloudflarestorage.com" + r2 = boto3.client( + "s3", + endpoint_url=ConnectionUrl, + aws_access_key_id=settings.access_key_id, + aws_secret_access_key=settings.secret_access_key, + ) + + if object_name is None: + object_name = file_name + + try: + r2.upload_file(file_name, bucket_name, object_name) + except ClientError as e: + print(f"An error occurred: {e}") + return False + return True + +async def save_picture(file, folder_name: str = "", file_name: str = None): + import io + r2 = boto3.client( "s3", endpoint_url=f"https://{settings.AccountID}.r2.cloudflarestorage.com", @@ -188,21 +224,42 @@ async def save_picture(file, folderName: str = "", fileName: str = None): aws_secret_access_key=settings.secret_access_key, ) + randon_uid = str(uuid4()) + _, f_ext = os.path.splitext(file.filename) + + picture_name = ( + randon_uid if file_name is None else file_name.lower().replace(" ", "") + ) + f_ext + + path = os.path.join(static, folder_name) + if not os.path.exists(path): + os.makedirs(path) + + picture_path = os.path.join(path, picture_name) + + # output_size = (125,125) img = Image.open(file.file) - img_byte_arr = io.BytesIO() - img.save(img_byte_arr, format='PNG') - img_byte_arr = img_byte_arr.getvalue() - - r2.put_object(Bucket=settings.bucket_name, Key=f"{folderName}/{picture_name}", Body=img_byte_arr) - - r2_url = f"https://{settings.AccountID}.r2.cloudflarestorage.com/{settings.bucket_name}/{folderName}/{picture_name}" - return r2_url + # img.thumbnail(output_size) + img.save(picture_path) + ConnectionUrl = f"https://{settings.AccountID}.r2.cloudflarestorage.com" + S3Connect = boto3.client( + "s3", + endpoint_url=ConnectionUrl, + aws_access_key_id=settings.access_key_id, + aws_secret_access_key=settings.secret_access_key, + ) + if upload_file(picture_path, "images"): + print(f"File {picture_path} uploaded successfully to images") + else: + print(f"File upload failed") + + return f"{static}/{folder_name}/{picture_name}" async def del_picture(picture_path): try: os.remove(picture_path) except Exception as e: - print('Error: ', e) + print("Error: ", e) return False - return True \ No newline at end of file + return True diff --git a/backend/static/tmp/3b3c4810-8e2a-4cbc-875e-14e442fd8492.png b/backend/static/tmp/3b3c4810-8e2a-4cbc-875e-14e442fd8492.png new file mode 100644 index 0000000..14d7a06 Binary files /dev/null and b/backend/static/tmp/3b3c4810-8e2a-4cbc-875e-14e442fd8492.png differ diff --git a/backend/static/tmp/79edea05-9d89-4831-9268-85a8bfc68ddc.png b/backend/static/tmp/79edea05-9d89-4831-9268-85a8bfc68ddc.png new file mode 100644 index 0000000..14d7a06 Binary files /dev/null and b/backend/static/tmp/79edea05-9d89-4831-9268-85a8bfc68ddc.png differ diff --git a/backend/static/tmp/99f8bf8f-2a85-40e9-8b24-5ddcf18eb410.png b/backend/static/tmp/99f8bf8f-2a85-40e9-8b24-5ddcf18eb410.png new file mode 100644 index 0000000..3231d04 Binary files /dev/null and b/backend/static/tmp/99f8bf8f-2a85-40e9-8b24-5ddcf18eb410.png differ diff --git a/backend/static/tmp/ea22ca62-af90-493b-b182-24456ff2bb43.png b/backend/static/tmp/ea22ca62-af90-493b-b182-24456ff2bb43.png new file mode 100644 index 0000000..3231d04 Binary files /dev/null and b/backend/static/tmp/ea22ca62-af90-493b-b182-24456ff2bb43.png differ diff --git a/backend/static/tmp/f8c29979-2c40-41d3-857b-6b07eecf1ce7.png b/backend/static/tmp/f8c29979-2c40-41d3-857b-6b07eecf1ce7.png new file mode 100644 index 0000000..3231d04 Binary files /dev/null and b/backend/static/tmp/f8c29979-2c40-41d3-857b-6b07eecf1ce7.png differ diff --git a/backend/static/tmp/ff2a7f71-6b76-4cb3-9f7a-2b290a2e2051.png b/backend/static/tmp/ff2a7f71-6b76-4cb3-9f7a-2b290a2e2051.png new file mode 100644 index 0000000..3231d04 Binary files /dev/null and b/backend/static/tmp/ff2a7f71-6b76-4cb3-9f7a-2b290a2e2051.png differ diff --git a/frontend/.env b/frontend/.env index 5be1e92..f829bd1 100644 --- a/frontend/.env +++ b/frontend/.env @@ -1 +1 @@ -VITE_API_URL=https://localhost +VITE_API_URL=http://localhost diff --git a/frontend/src/client/core/request.ts b/frontend/src/client/core/request.ts index ad2389e..6abb0e8 100644 --- a/frontend/src/client/core/request.ts +++ b/frontend/src/client/core/request.ts @@ -80,8 +80,7 @@ const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { return substring }) - let url = config.BASE + path - url = url.replace(/^http:\/\//i, 'https://') + const url = config.BASE + path return options.query ? url + getQueryString(options.query) : url }