From 65d35336be66a351194c291bb08bbfe4dada0f5e Mon Sep 17 00:00:00 2001 From: haeunia <peanutanna@ewhain.net> Date: Wed, 8 Jan 2025 20:52:38 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=EC=8B=A0=EA=B3=A0=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- market/models.py | 14 ++++++ .../market_serializers/market_serializer.py | 8 ++++ .../report_serializer/ReporterSerialzer.py | 7 +++ .../serializers/report_serializer/__init__.py | 0 market/urls.py | 5 +- market/views/report_views.py | 48 +++++++++++++++++++ 6 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 market/serializers/report_serializer/ReporterSerialzer.py create mode 100644 market/serializers/report_serializer/__init__.py create mode 100644 market/views/report_views.py diff --git a/market/models.py b/market/models.py index 5f81b83..a2238db 100644 --- a/market/models.py +++ b/market/models.py @@ -6,6 +6,8 @@ from market.managers import MarketManager, ServiceManager, ServiceMaterialManager from users.models.reformer import Reformer +from django.db import models +from django.contrib.auth.models import User def get_market_thumbnail_upload_path(instance, filename): email_name = instance.reformer.user.email.split("@")[0] @@ -154,3 +156,15 @@ class ServiceOptionImage(TimeStampedModel): class Meta: db_table = "market_service_option_image" + +class Report(models.Model): + reported_user = models.ForeignKey(User, related_name="reports_received", on_delete=models.CASCADE) + reporter_user = models.ForeignKey(User, related_name="reports_made", on_delete=models.CASCADE) + reason = models.CharField(max_length=255) + details = models.TextField(blank=True, null=True) + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return f"Report against {self.reported_user.username} by {self.reporter_user.username}" + + diff --git a/market/serializers/market_serializers/market_serializer.py b/market/serializers/market_serializers/market_serializer.py index c78c850..fcfd609 100644 --- a/market/serializers/market_serializers/market_serializer.py +++ b/market/serializers/market_serializers/market_serializer.py @@ -2,6 +2,14 @@ from market.models import Market +from rest_framework import serializers +from market.models import Report + +class ReportSerializer(serializers.ModelSerializer): + class Meta: + model = Report + fields = ['reported_user', 'reporter_user', 'reason', 'details'] + class MarketSerializer(serializers.ModelSerializer): market_uuid = serializers.UUIDField(read_only=True) diff --git a/market/serializers/report_serializer/ReporterSerialzer.py b/market/serializers/report_serializer/ReporterSerialzer.py new file mode 100644 index 0000000..19e0e4c --- /dev/null +++ b/market/serializers/report_serializer/ReporterSerialzer.py @@ -0,0 +1,7 @@ +from rest_framework import serializers +from market.models import Report + +class ReportSerializer(serializers.ModelSerializer): + class Meta: + model = Report + fields = ['reported_user', 'reporter_user', 'reason', 'details'] diff --git a/market/serializers/report_serializer/__init__.py b/market/serializers/report_serializer/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/market/urls.py b/market/urls.py index 5f86e39..178575c 100644 --- a/market/urls.py +++ b/market/urls.py @@ -24,7 +24,7 @@ ServiceStyleCreateListView, ServiceStyleView, ) - +from market.views.report_views import ReportUserView urlpatterns = [ path("", MarketCreateListView.as_view(), name="market_create_list"), path( @@ -83,4 +83,7 @@ ServiceOptionImageUploadView.as_view(), name="market_service_option_image_upload", ), + path('report/', ReportUserView.as_view(), name='report_user'), + ] + diff --git a/market/views/report_views.py b/market/views/report_views.py new file mode 100644 index 0000000..c451d80 --- /dev/null +++ b/market/views/report_views.py @@ -0,0 +1,48 @@ +# market/views/report_views.py + +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework import status +from django.contrib.auth.models import User +from market.models import Report +from market.serializers.report_serializer.ReporterSerializer import ReportSerializer + + +class ReportUserView(APIView): + def post(self, request): + data = request.data + try: + reported_user = User.objects.get(id=data['reported_user_id']) + reporter_user = User.objects.get(id=data['reporter_user_id']) + + + report = Report.objects.create( + reported_user=reported_user, + reporter_user=reporter_user, + reason=data['reason'], + details=data.get('details', '') + ) + + + report_count = Report.objects.filter(reported_user=reported_user).count() + + + if report_count >= 5: + reported_user.is_active = False + reported_user.save() + + return Response({ + "status": "success", + "message": "신고가 접수되었으며, 해당 사용자의 서비스가 중단됩니다." + }, status=status.HTTP_200_OK) + + return Response({ + "status": "success", + "message": "신고가 접수되었습니다." + }, status=status.HTTP_201_CREATED) + + except User.DoesNotExist: + return Response({ + "status": "error", + "message": "사용자를 찾을 수 없습니다." + }, status=status.HTTP_404_NOT_FOUND) From 760a609262889bbcd1dd6adcc7edd5e128afeba2 Mon Sep 17 00:00:00 2001 From: haeunia <peanutanna@ewhain.net> Date: Sat, 11 Jan 2025 16:10:55 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EC=8B=A0=EA=B3=A0=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- market/migrations/0004_report.py | 49 +++++++++++++++++++ market/migrations/0005_alter_report_table.py | 17 +++++++ market/models.py | 19 ++++--- .../market_serializers/market_serializer.py | 8 --- ...terSerialzer.py => reporter_serializer.py} | 4 +- market/tests.py | 15 ++++++ market/urls.py | 7 ++- market/views/report_views.py | 47 +++++++++--------- 8 files changed, 121 insertions(+), 45 deletions(-) create mode 100644 market/migrations/0004_report.py create mode 100644 market/migrations/0005_alter_report_table.py rename market/serializers/report_serializer/{ReporterSerialzer.py => reporter_serializer.py} (68%) diff --git a/market/migrations/0004_report.py b/market/migrations/0004_report.py new file mode 100644 index 0000000..13ef5c9 --- /dev/null +++ b/market/migrations/0004_report.py @@ -0,0 +1,49 @@ +# Generated by Django 5.1.1 on 2025-01-11 07:01 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("market", "0003_service_suspended"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="Report", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("reason", models.CharField(max_length=255)), + ("details", models.TextField(blank=True, null=True)), + ("created_at", models.DateTimeField(auto_now_add=True)), + ( + "reported_user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="reports_received", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "reporter_user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="reports_made", + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + ] diff --git a/market/migrations/0005_alter_report_table.py b/market/migrations/0005_alter_report_table.py new file mode 100644 index 0000000..6351600 --- /dev/null +++ b/market/migrations/0005_alter_report_table.py @@ -0,0 +1,17 @@ +# Generated by Django 5.1.1 on 2025-01-11 07:03 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("market", "0004_report"), + ] + + operations = [ + migrations.AlterModelTable( + name="report", + table="report", + ), + ] diff --git a/market/models.py b/market/models.py index a2238db..b064a82 100644 --- a/market/models.py +++ b/market/models.py @@ -1,13 +1,13 @@ import uuid +from django.conf import settings +from django.contrib.auth.models import User from django.db import models from core.models import TimeStampedModel from market.managers import MarketManager, ServiceManager, ServiceMaterialManager from users.models.reformer import Reformer -from django.db import models -from django.contrib.auth.models import User def get_market_thumbnail_upload_path(instance, filename): email_name = instance.reformer.user.email.split("@")[0] @@ -157,14 +157,17 @@ class ServiceOptionImage(TimeStampedModel): class Meta: db_table = "market_service_option_image" + class Report(models.Model): - reported_user = models.ForeignKey(User, related_name="reports_received", on_delete=models.CASCADE) - reporter_user = models.ForeignKey(User, related_name="reports_made", on_delete=models.CASCADE) + reported_user = models.ForeignKey( + "users.User", related_name="reports_received", on_delete=models.CASCADE + ) + reporter_user = models.ForeignKey( + "users.User", related_name="reports_made", on_delete=models.CASCADE + ) reason = models.CharField(max_length=255) details = models.TextField(blank=True, null=True) created_at = models.DateTimeField(auto_now_add=True) - def __str__(self): - return f"Report against {self.reported_user.username} by {self.reporter_user.username}" - - + class Meta: + db_table = "report" diff --git a/market/serializers/market_serializers/market_serializer.py b/market/serializers/market_serializers/market_serializer.py index fcfd609..c78c850 100644 --- a/market/serializers/market_serializers/market_serializer.py +++ b/market/serializers/market_serializers/market_serializer.py @@ -2,14 +2,6 @@ from market.models import Market -from rest_framework import serializers -from market.models import Report - -class ReportSerializer(serializers.ModelSerializer): - class Meta: - model = Report - fields = ['reported_user', 'reporter_user', 'reason', 'details'] - class MarketSerializer(serializers.ModelSerializer): market_uuid = serializers.UUIDField(read_only=True) diff --git a/market/serializers/report_serializer/ReporterSerialzer.py b/market/serializers/report_serializer/reporter_serializer.py similarity index 68% rename from market/serializers/report_serializer/ReporterSerialzer.py rename to market/serializers/report_serializer/reporter_serializer.py index 19e0e4c..d90625d 100644 --- a/market/serializers/report_serializer/ReporterSerialzer.py +++ b/market/serializers/report_serializer/reporter_serializer.py @@ -1,7 +1,9 @@ from rest_framework import serializers + from market.models import Report + class ReportSerializer(serializers.ModelSerializer): class Meta: model = Report - fields = ['reported_user', 'reporter_user', 'reason', 'details'] + fields = ["reported_user", "reporter_user", "reason", "details"] diff --git a/market/tests.py b/market/tests.py index aef58a3..c76ea99 100644 --- a/market/tests.py +++ b/market/tests.py @@ -253,6 +253,21 @@ def test_delete_market_info(self, mock_boto3_client: MagicMock): # 마켓 정보가 삭제 되었는지 확인 self.assertEqual(Market.objects.filter(market_uuid=market_uuid).count(), 0) + def test_report_market(self): + # 마켓 신고가 정상적으로 작동하는 것 + response = self.client.post( + path="/api/market/report", + data={ + "reported_user_id": self.test_user.id, + "reason": "허위 정보 게시", + "details": "잘못된 정보를 포함한 마켓 설명", + }, + format="json", + ) + self.assertEqual(response.status_code, 201) + self.assertEqual(response.data["reported_user"], self.test_user.id) + self.assertEqual(response.data["reason"], "허위 정보 게시") + def tearDown(self): Market.objects.all().delete() Reformer.objects.all().delete() diff --git a/market/urls.py b/market/urls.py index 178575c..e4ba15f 100644 --- a/market/urls.py +++ b/market/urls.py @@ -7,6 +7,7 @@ ) from market.views.market_view.market_create_list_view import MarketCreateListView from market.views.market_view.market_crud_view import MarketCrudView +from market.views.report_views import ReportUserView from market.views.service_view.service_create_list_view import ( GetAllServiceView, MarketServiceCreateListView, @@ -24,7 +25,7 @@ ServiceStyleCreateListView, ServiceStyleView, ) -from market.views.report_views import ReportUserView + urlpatterns = [ path("", MarketCreateListView.as_view(), name="market_create_list"), path( @@ -83,7 +84,5 @@ ServiceOptionImageUploadView.as_view(), name="market_service_option_image_upload", ), - path('report/', ReportUserView.as_view(), name='report_user'), - + path("/report", ReportUserView.as_view(), name="report_user"), ] - diff --git a/market/views/report_views.py b/market/views/report_views.py index c451d80..5459f65 100644 --- a/market/views/report_views.py +++ b/market/views/report_views.py @@ -1,48 +1,47 @@ # market/views/report_views.py -from rest_framework.views import APIView -from rest_framework.response import Response from rest_framework import status -from django.contrib.auth.models import User +from rest_framework.response import Response +from rest_framework.views import APIView + from market.models import Report -from market.serializers.report_serializer.ReporterSerializer import ReportSerializer +from market.serializers.report_serializer.reporter_serializer import ReportSerializer +from users.models.user import User class ReportUserView(APIView): def post(self, request): data = request.data try: - reported_user = User.objects.get(id=data['reported_user_id']) - reporter_user = User.objects.get(id=data['reporter_user_id']) + reported_user = User.objects.get(id=data["reported_user_id"]) + reporter_user = User.objects.get(id=request.user.id) - - report = Report.objects.create( + report: Report = Report.objects.create( reported_user=reported_user, reporter_user=reporter_user, - reason=data['reason'], - details=data.get('details', '') + reason=data["reason"], + details=data.get("details", ""), ) - + serializer = ReportSerializer(instance=report) report_count = Report.objects.filter(reported_user=reported_user).count() + serializer.data["report_count"] = report_count - if report_count >= 5: reported_user.is_active = False reported_user.save() - return Response({ - "status": "success", - "message": "신고가 접수되었으며, 해당 사용자의 서비스가 중단됩니다." - }, status=status.HTTP_200_OK) + return Response(data=serializer.data, status=status.HTTP_200_OK) - return Response({ - "status": "success", - "message": "신고가 접수되었습니다." - }, status=status.HTTP_201_CREATED) + return Response(data=serializer.data, status=status.HTTP_201_CREATED) except User.DoesNotExist: - return Response({ - "status": "error", - "message": "사용자를 찾을 수 없습니다." - }, status=status.HTTP_404_NOT_FOUND) + return Response( + {"status": "error", "message": "사용자를 찾을 수 없습니다."}, + status=status.HTTP_404_NOT_FOUND, + ) + except Exception as e: + return Response( + data={"status": "error", "details": str(e)}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR, + )