From fe934a3b2298526de79ec8d1f7bd48e4802dfe22 Mon Sep 17 00:00:00 2001 From: morecleverer Date: Sun, 19 Jan 2025 12:59:30 +0900 Subject: [PATCH 1/4] =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=ED=99=95=EC=9E=A5?= =?UTF-8?q?=EC=9E=90=20png,=20jpg,=20jpeg=EC=9C=BC=EB=A1=9C=20=EC=A0=9C?= =?UTF-8?q?=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- snuvote/app/vote/errors.py | 6 +++++- snuvote/app/vote/views.py | 11 ++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/snuvote/app/vote/errors.py b/snuvote/app/vote/errors.py index e745b81..7195a4e 100644 --- a/snuvote/app/vote/errors.py +++ b/snuvote/app/vote/errors.py @@ -63,4 +63,8 @@ def __init__(self) -> None: class CommentNotInThisVoteError(HTTPException): def __init__(self) -> None: - super().__init__(HTTP_404_NOT_FOUND, "Comment not in this vote") \ No newline at end of file + super().__init__(HTTP_404_NOT_FOUND, "Comment not in this vote") + +class InvalidFileExtensionError(HTTPException): + def __init__(self) -> None: + super().__init__(HTTP_400_BAD_REQUEST, "Invalid file extension") \ No newline at end of file diff --git a/snuvote/app/vote/views.py b/snuvote/app/vote/views.py index 582cca5..e3d1f97 100644 --- a/snuvote/app/vote/views.py +++ b/snuvote/app/vote/views.py @@ -7,7 +7,7 @@ from snuvote.app.vote.dto.requests import CreateVoteRequest, ParticipateVoteRequest, CommentRequest from snuvote.app.vote.dto.responses import OnGoingVotesListResponse, VotesListInfoResponse, VoteDetailResponse, ChoiceDetailResponse, CommentDetailResponse -from snuvote.app.vote.errors import VoteNotFoundError, MultipleChoicesError, ChoiceNotFoundError, CommentNotFoundError +from snuvote.app.vote.errors import VoteNotFoundError, InvalidFileExtensionError, ChoiceNotFoundError, CommentNotFoundError from datetime import datetime, timedelta, timezone from snuvote.database.models import User @@ -19,6 +19,8 @@ security = HTTPBearer() +ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg"} + #create vote @vote_router.post("/create", status_code=HTTP_201_CREATED) def create_vote( @@ -27,6 +29,13 @@ def create_vote( images: List[UploadFile]|None = File(None), create_vote_json = Form(media_type="multipart/form-data", json_schema_extra=CreateVoteRequest.model_json_schema()) ): + if images: + for image in images: + filename = image.filename + extension = filename.split(".")[-1].lower() # 확장자 추출 및 소문자로 변환 + if extension not in ALLOWED_EXTENSIONS: + raise InvalidFileExtensionError + create_vote_request = CreateVoteRequest.model_validate_json(create_vote_json) From 7608450b370591b6a8c22d02ceae265a8d921ff5 Mon Sep 17 00:00:00 2001 From: morecleverer Date: Sun, 19 Jan 2025 13:20:56 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=ED=88=AC=ED=91=9C=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8,=20=ED=88=AC=ED=91=9C=20=EC=84=B8=EB=B6=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=EC=97=90=20=EC=B0=B8=EC=97=AC=EC=9E=90=EC=88=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- snuvote/app/vote/dto/responses.py | 26 ++++++++++++++++++++++++-- snuvote/app/vote/views.py | 4 +++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/snuvote/app/vote/dto/responses.py b/snuvote/app/vote/dto/responses.py index f7b9282..bef4a77 100644 --- a/snuvote/app/vote/dto/responses.py +++ b/snuvote/app/vote/dto/responses.py @@ -31,18 +31,26 @@ class VotesListInfoResponse(BaseModel): create_datetime: Annotated[datetime, AfterValidator(convert_utc_to_ktc_naive)] # UTC 시간대를 KST 시간대로 변환한 뒤 offset-naive로 변환 end_datetime: Annotated[datetime, AfterValidator(convert_utc_to_ktc_naive)] # UTC 시간대를 KST 시간대로 변환한 뒤 offset-naive로 변환 participated: bool + participant_count: int image: str| None @staticmethod def from_vote_user(vote: Vote, user: User) -> "VotesListInfoResponse": - # 해당 유저의 참여 여부도 포함시켜야 함 + # 해당 유저의 참여 여부, 전체 참여자 수 계산 participated = False + participant_set = set() for choice in vote.choices: for choice_participation in choice.choice_participations: + + #해당 유저가 참여했는지 여부 if choice_participation.user_id == user.id: participated = True - break + + #참여자를 집합에 넣기(중복 미포함) + participant_set.add(choice_participation.user_id) + + return VotesListInfoResponse( id=vote.id, @@ -51,6 +59,7 @@ def from_vote_user(vote: Vote, user: User) -> "VotesListInfoResponse": create_datetime=vote.create_datetime, end_datetime=vote.end_datetime, participated = participated, + participant_count= len(participant_set), image= vote.images[0].src if vote.images else None ) @@ -149,4 +158,17 @@ class VoteDetailResponse(BaseModel): choices: List[ChoiceDetailResponse] comments: List[CommentDetailResponse] images: List[str] + participant_count: int + + #Vote를 받아 참여자 수를 계산함 + @staticmethod + def from_vote(vote: Vote) -> int: + + participant_set = set() + for choice in vote.choices: + for choice_participation in choice.choice_participations: + #참여자를 집합에 넣기(중복 미포함) + participant_set.add(choice_participation.user_id) + + return len(participant_set) diff --git a/snuvote/app/vote/views.py b/snuvote/app/vote/views.py index e3d1f97..88da599 100644 --- a/snuvote/app/vote/views.py +++ b/snuvote/app/vote/views.py @@ -29,6 +29,7 @@ def create_vote( images: List[UploadFile]|None = File(None), create_vote_json = Form(media_type="multipart/form-data", json_schema_extra=CreateVoteRequest.model_json_schema()) ): + #파일 확장자가 안맞으면 오류 if images: for image in images: filename = image.filename @@ -102,7 +103,8 @@ def get_vote( end_datetime = vote.end_datetime, choices= [ChoiceDetailResponse.from_choice(choice, user, vote.annonymous_choice, vote.realtime_result) for choice in vote.choices], comments = [CommentDetailResponse.from_comment_user(comment, user) for comment in vote.comments if comment.is_deleted==False], - images = [image.src for image in vote.images] + images = [image.src for image in vote.images], + particiapant_count = VoteDetailResponse.from_vote(vote) ) From 921b3b147ba4d472918b04ca8a5daab9111d7ce3 Mon Sep 17 00:00:00 2001 From: odumag99 Date: Sun, 19 Jan 2025 19:08:03 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=ED=99=95=EC=9E=A5?= =?UTF-8?q?=EC=9E=90=20=EC=A0=9C=ED=95=9C=20=EB=A1=9C=EC=A7=81=20service?= =?UTF-8?q?=20layer=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- snuvote/app/vote/service.py | 11 ++++++++++- snuvote/app/vote/views.py | 12 ++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/snuvote/app/vote/service.py b/snuvote/app/vote/service.py index fa52c91..ed62a1b 100644 --- a/snuvote/app/vote/service.py +++ b/snuvote/app/vote/service.py @@ -3,7 +3,7 @@ from fastapi import Depends, UploadFile from snuvote.database.models import Vote, User, Choice, ChoiceParticipation, Comment from snuvote.app.vote.store import VoteStore -from snuvote.app.vote.errors import ChoiceNotFoundError, InvalidFieldFormatError, MultipleChoicesError, ParticipationCodeError, ParticipationCodeNotProvidedError, WrongParticipationCodeError, EndedVoteError, CommentNotYoursError, CommentNotInThisVoteError +from snuvote.app.vote.errors import ChoiceNotFoundError, InvalidFieldFormatError, MultipleChoicesError, ParticipationCodeError, ParticipationCodeNotProvidedError, WrongParticipationCodeError, EndedVoteError, CommentNotYoursError, CommentNotInThisVoteError, InvalidFileExtensionError from snuvote.app.vote.dto.requests import ParticipateVoteRequest, CommentRequest from datetime import datetime, timedelta, timezone @@ -12,6 +12,9 @@ import os import boto3 + +ALLOWED_EXTENSIONS = {"jpg", "jpeg", "png", "gif"} + class VoteService: def __init__(self, vote_store: Annotated[VoteStore, Depends()]) -> None: self.vote_store = vote_store @@ -71,6 +74,12 @@ def add_vote(self, # 이미지 업로드 if images: + # 확장자가 안 맞으면 오류 + for image in images: + filename = image.filename + extension = filename.split(".")[-1].lower() # 확장자 추출 및 소문자로 변환 + if extension not in ALLOWED_EXTENSIONS: + raise InvalidFileExtensionError self.upload_vote_images(vote, images) return self.vote_store.get_vote_by_vote_id(vote_id=vote.id) diff --git a/snuvote/app/vote/views.py b/snuvote/app/vote/views.py index 88da599..5e79f2b 100644 --- a/snuvote/app/vote/views.py +++ b/snuvote/app/vote/views.py @@ -7,7 +7,7 @@ from snuvote.app.vote.dto.requests import CreateVoteRequest, ParticipateVoteRequest, CommentRequest from snuvote.app.vote.dto.responses import OnGoingVotesListResponse, VotesListInfoResponse, VoteDetailResponse, ChoiceDetailResponse, CommentDetailResponse -from snuvote.app.vote.errors import VoteNotFoundError, InvalidFileExtensionError, ChoiceNotFoundError, CommentNotFoundError +from snuvote.app.vote.errors import VoteNotFoundError, ChoiceNotFoundError, CommentNotFoundError from datetime import datetime, timedelta, timezone from snuvote.database.models import User @@ -19,7 +19,6 @@ security = HTTPBearer() -ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg"} #create vote @vote_router.post("/create", status_code=HTTP_201_CREATED) @@ -29,14 +28,7 @@ def create_vote( images: List[UploadFile]|None = File(None), create_vote_json = Form(media_type="multipart/form-data", json_schema_extra=CreateVoteRequest.model_json_schema()) ): - #파일 확장자가 안맞으면 오류 - if images: - for image in images: - filename = image.filename - extension = filename.split(".")[-1].lower() # 확장자 추출 및 소문자로 변환 - if extension not in ALLOWED_EXTENSIONS: - raise InvalidFileExtensionError - + create_vote_request = CreateVoteRequest.model_validate_json(create_vote_json) From 003a5955ae55aad9c0d0720a78ad68c0efaafd55 Mon Sep 17 00:00:00 2001 From: odumag99 Date: Sun, 19 Jan 2025 19:08:54 +0900 Subject: [PATCH 4/4] =?UTF-8?q?get=5Fparitipant=5Fcount=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=9D=B4=EB=A6=84=20=EB=B0=8F=20=EC=98=A4?= =?UTF-8?q?=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- snuvote/app/vote/dto/responses.py | 2 +- snuvote/app/vote/views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/snuvote/app/vote/dto/responses.py b/snuvote/app/vote/dto/responses.py index bef4a77..478a4b5 100644 --- a/snuvote/app/vote/dto/responses.py +++ b/snuvote/app/vote/dto/responses.py @@ -162,7 +162,7 @@ class VoteDetailResponse(BaseModel): #Vote를 받아 참여자 수를 계산함 @staticmethod - def from_vote(vote: Vote) -> int: + def get_participant_count_from_vote(vote: Vote) -> int: participant_set = set() for choice in vote.choices: diff --git a/snuvote/app/vote/views.py b/snuvote/app/vote/views.py index 5e79f2b..d9e124f 100644 --- a/snuvote/app/vote/views.py +++ b/snuvote/app/vote/views.py @@ -96,7 +96,7 @@ def get_vote( choices= [ChoiceDetailResponse.from_choice(choice, user, vote.annonymous_choice, vote.realtime_result) for choice in vote.choices], comments = [CommentDetailResponse.from_comment_user(comment, user) for comment in vote.comments if comment.is_deleted==False], images = [image.src for image in vote.images], - particiapant_count = VoteDetailResponse.from_vote(vote) + participant_count = VoteDetailResponse.get_participant_count_from_vote(vote) )