diff --git a/backend/backend/settings.py b/backend/backend/settings.py index 605747d..cff8ebe 100644 --- a/backend/backend/settings.py +++ b/backend/backend/settings.py @@ -23,7 +23,7 @@ # SECURITY WARNING: don't run with debug turned on in production! DEBUG = env('DEBUG') -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = ['*'] # Application definition @@ -39,6 +39,7 @@ # local apps 'rebikeuser', 'rebiketrash', + 'corsheaders', ] MIDDLEWARE = [ @@ -49,8 +50,12 @@ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'corsheaders.middleware.CorsMiddleware', ] +CORS_ORIGIN_WHITELIST = ['http://127.0.0.1:3000', 'http://localhost:3000'] +CORS_ALLOW_CREDENTIALS = True + ROOT_URLCONF = 'backend.urls' TEMPLATES = [ @@ -116,3 +121,65 @@ # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +# ================로깅 테스트=================== +# 로깅설정 +# LOGGING = { +# 'version': 1, +# 'disable_existing_loggers': False, +# 'filters': { +# 'require_debug_false': { +# '()': 'django.utils.log.RequireDebugFalse', +# }, +# 'require_debug_true': { +# '()': 'django.utils.log.RequireDebugTrue', +# }, +# }, +# 'formatters': { +# 'django.server': { +# '()': 'django.utils.log.ServerFormatter', +# 'format': '[{server_time}] {message}', +# 'style': '{', +# }, +# 'standard': { +# 'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s' +# }, +# }, +# 'handlers': { +# 'console': { +# 'level': 'INFO', +# 'filters': ['require_debug_true'], +# 'class': 'logging.StreamHandler', +# }, +# 'django.server': { +# 'level': 'INFO', +# 'class': 'logging.StreamHandler', +# 'formatter': 'django.server', +# }, +# 'mail_admins': { +# 'level': 'ERROR', +# 'filters': ['require_debug_false'], +# 'class': 'django.utils.log.AdminEmailHandler' +# }, +# 'file': { +# 'level': 'INFO', +# 'filters': ['require_debug_false'], +# 'class': 'logging.handlers.RotatingFileHandler', +# 'filename': BASE_DIR / 'logs/mylog.log', +# 'maxBytes': 1024*1024*5, # 5 MB +# 'backupCount': 5, +# 'formatter': 'standard', +# }, +# }, +# 'loggers': { +# 'django': { +# 'handlers': ['console', 'mail_admins', 'file'], +# 'level': 'INFO', +# }, +# 'django.server': { +# 'handlers': ['django.server'], +# 'level': 'INFO', +# 'propagate': False, +# }, +# } +# } diff --git a/backend/backend/urls.py b/backend/backend/urls.py index b27f250..32eb384 100644 --- a/backend/backend/urls.py +++ b/backend/backend/urls.py @@ -1,9 +1,18 @@ from django.contrib import admin from django.urls import path, include +from django.contrib import admin +from django.urls import path, include +from rest_framework.permissions import AllowAny +from django.contrib import admin +from django.urls import path, include +from rest_framework import permissions +from django.urls import include, re_path +from rest_framework.permissions import AllowAny + urlpatterns = [ path('admin/', admin.site.urls), - path('users/', include('rebikeuser.urls')), - path('trashs/', include('rebiketrash.urls')), + path('user/', include('rebikeuser.urls')), + path('trash/', include('rebiketrash.urls')), ] diff --git a/backend/dockerfile b/backend/dockerfile index ce42828..bc5eee3 100644 --- a/backend/dockerfile +++ b/backend/dockerfile @@ -6,4 +6,4 @@ COPY ./ ./ EXPOSE 8080 -RUN pip install -r requirements.txt +RUN pip install -r requirements.txt \ No newline at end of file diff --git a/backend/rebiketrash/admin.py b/backend/rebiketrash/admin.py new file mode 100644 index 0000000..8d6d0fd --- /dev/null +++ b/backend/rebiketrash/admin.py @@ -0,0 +1,14 @@ +from django.contrib import admin + +from .models import trash_kind, uploaded_trash_image + +@admin.register(trash_kind) +class TrashkindAdmin(admin.ModelAdmin): + list_display = ['kind', 'way'] + search_fields = ['kind'] + +@admin.register(uploaded_trash_image) +class UploadedtrashimageAdmin(admin.ModelAdmin): + list_display = ['uploaded_trash_image_id', 'img', 'created_at', 'updated_at','user_id', 'trash_kind'] + search_fields = ['uploaded_trash_image_id'] + diff --git a/backend/rebiketrash/migrations/__init__.py b/backend/rebiketrash/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/backend/rebiketrash/models.py b/backend/rebiketrash/models.py index 8246bf4..63530d8 100644 --- a/backend/rebiketrash/models.py +++ b/backend/rebiketrash/models.py @@ -5,6 +5,8 @@ class trash_kind(models.Model): kind = models.CharField(primary_key=True, max_length=30) way = models.CharField(max_length=200) + created_at = models.DateTimeField() + updated_at = models.DateTimeField() class Meta: managed = False @@ -13,6 +15,7 @@ class Meta: class uploaded_trash_image(models.Model): uploaded_trash_image_id = models.AutoField(primary_key=True) + active = models.IntegerField(default=1) img = models.CharField(max_length=200) created_at = models.DateTimeField() updated_at = models.DateTimeField() @@ -21,4 +24,4 @@ class uploaded_trash_image(models.Model): class Meta: managed = False - db_table = 'uploaded_trash_image' \ No newline at end of file + db_table = 'uploaded_trash_image' diff --git a/backend/rebiketrash/serializers.py b/backend/rebiketrash/serializers.py new file mode 100644 index 0000000..b414992 --- /dev/null +++ b/backend/rebiketrash/serializers.py @@ -0,0 +1,13 @@ +from rest_framework import serializers +from .models import trash_kind, uploaded_trash_image + +class TrashkindSerializer(serializers.ModelSerializer) : + class Meta : + model = trash_kind # product 모델 사용 + fields = '__all__' # 모든 필드 포함 + + +class UploadedtrashimageSerializer(serializers.ModelSerializer) : + class Meta : + model = uploaded_trash_image # product 모델 사용 + fields = '__all__' # 모든 필드 포함 \ No newline at end of file diff --git a/backend/rebiketrash/urls.py b/backend/rebiketrash/urls.py index 79b2c23..196cc12 100644 --- a/backend/rebiketrash/urls.py +++ b/backend/rebiketrash/urls.py @@ -1,7 +1,21 @@ -from django.urls import path +from django.urls import path, re_path from . import views +from django.contrib import admin +from django.urls import include, path, re_path -urlpatterns = [ + +urlpatterns =[ + path('mainpage/trashkind/',views.TrashkindListAPI.as_view()), + path('mypage//image/',views.histories, name='histories'), + path('mypage//image//',views.UploadedtrashimageListAPI.as_view()), + #path('mypage//statistics/',views.statistics, name='statistics'), ] + + +### 유저 페이지 진입 시 액티브된 계정인지(있는지 없는지 확인) +### 통계페이지 (액티브 상관 없이 받아오기!) +### 자주 쓰이는 코드 유틸화 trashUtils.py + +### swagger, postman 확인 -> 성빈님 diff --git a/backend/rebiketrash/views.py b/backend/rebiketrash/views.py index 91ea44a..f97d799 100644 --- a/backend/rebiketrash/views.py +++ b/backend/rebiketrash/views.py @@ -1,3 +1,43 @@ -from django.shortcuts import render +from audioop import reverse +from django.shortcuts import render, HttpResponse +from django.db.models import Count + +from .models import trash_kind, uploaded_trash_image +from rebikeuser.models import user + +from rest_framework import status +from rest_framework.response import Response +from rest_framework.views import APIView +from rest_framework.decorators import api_view +from .serializers import TrashkindSerializer, UploadedtrashimageSerializer # Create your views here. +class TrashkindListAPI(APIView): + def get(self, request): + queryset = trash_kind.objects.all() + print(queryset) + serializer = TrashkindSerializer(queryset, many=True) + return Response(serializer.data) + +@api_view(['GET']) +def histories(request,user_id): + uploadedTrashs = uploaded_trash_image.objects.filter(user_id=user_id, active=1) + serializer = UploadedtrashimageSerializer(uploadedTrashs, many=True) + return Response(serializer.data) + +class UploadedtrashimageListAPI(APIView): + def get(self, request, user_id, uploaded_trash_image_id): + uploadedTrashs = uploaded_trash_image.objects.filter(user_id=user_id, active=1, uploaded_trash_image_id = int(uploaded_trash_image_id)) + serializer = UploadedtrashimageSerializer(uploadedTrashs, many=True) + return Response(serializer.data) + + def delete(self, request, user_id, uploaded_trash_image_id): + uploadedTrashs = uploaded_trash_image.objects.filter(user_id=user_id, active=1, uploaded_trash_image_id = int(uploaded_trash_image_id)) + uploadedTrashs.delete() + return Response(status=status.HTTP_204_NO_CONTENT) + +@api_view(['GET']) +def statistics(request,user_id): + uploadedTrashs = uploaded_trash_image.objects.filter(user_id=user_id).values('trash_kind') + serializer = UploadedtrashimageSerializer(uploadedTrashs, many=True) + return Response(serializer.data) \ No newline at end of file diff --git a/backend/rebikeuser/admin.py b/backend/rebikeuser/admin.py new file mode 100644 index 0000000..946c252 --- /dev/null +++ b/backend/rebikeuser/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin +from .models import user + +@admin.register(user) +class UserAdmin(admin.ModelAdmin): + list_display = ['id', 'name', 'alias', 'pw', 'salt', 'email'] diff --git a/backend/rebikeuser/migrations/0002_alter_user_table.py b/backend/rebikeuser/migrations/0002_alter_user_table.py index abc8500..e629f05 100644 --- a/backend/rebikeuser/migrations/0002_alter_user_table.py +++ b/backend/rebikeuser/migrations/0002_alter_user_table.py @@ -1,4 +1,5 @@ -# Generated by Django 4.0.6 on 2022-07-14 19:46 + +# Generated by Django 4.0.6 on 2022-07-14 18:12 from django.db import migrations diff --git a/backend/rebikeuser/models.py b/backend/rebikeuser/models.py index 3a78860..fdcd4e5 100644 --- a/backend/rebikeuser/models.py +++ b/backend/rebikeuser/models.py @@ -1,15 +1,19 @@ from django.db import models import uuid - class user(models.Model): - id = models.UUIDField(primary_key=True, editable=False) - name = models.CharField(unique=True, max_length=20) + id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + name = models.CharField(unique=True, max_length=20, null=True, blank=True) alias = models.CharField(unique=True, max_length=20) pw = models.BinaryField(max_length=60) salt = models.BinaryField(max_length=29) email = models.CharField(unique=True, max_length=50) + active = models.IntegerField(default=1) + created_at = models.DateTimeField() + updated_at = models.DateTimeField() class Meta: managed = False db_table = 'user' +#, default=str(uuid.uuid4()) + diff --git a/backend/rebikeuser/serializers.py b/backend/rebikeuser/serializers.py index 1611836..d4fd2eb 100644 --- a/backend/rebikeuser/serializers.py +++ b/backend/rebikeuser/serializers.py @@ -4,6 +4,29 @@ class UserSerializer(serializers.ModelSerializer): + name = serializers.CharField(max_length=20) + alias = serializers.CharField(max_length=20) + email = serializers.CharField(max_length=50) + + class Meta: + model = user + fields = ['name', 'alias', 'email'] # Front에 3필드만 + + +# rebikeuser/serializers.py +class UserSignupResponse(serializers.ModelSerializer): + class Meta: + model = user + fields = ['id'] # 프론트에주는 값 + + +class SignupInput(serializers.ModelSerializer): + # 검증부 + email = serializers.EmailField() + pw = serializers.CharField(max_length=60) + alias = serializers.CharField(max_length=20) + name = serializers.CharField(max_length=20) + class Meta: model = user - fields = ['name', 'alias', 'email'] #Front에 3필드만 + fields = ['name', 'pw', 'alias', 'email'] # 실제 response할 필드 diff --git a/backend/rebikeuser/urls.py b/backend/rebikeuser/urls.py index 1cfcb60..59af8c7 100644 --- a/backend/rebikeuser/urls.py +++ b/backend/rebikeuser/urls.py @@ -1,10 +1,11 @@ from django.urls import path from . import views +from .views import UserSignupAPI - +#rebikeuser/urls.py urlpatterns = [ path('login/', views.user_login), - path('signup/', views.user_signup), + path('signup/', views.UserSignupAPI.as_view()), path('changepw/', views.user_pw_change), path('changealias/', views.user_alias_change), -] \ No newline at end of file +] diff --git a/backend/rebikeuser/userUtil.py b/backend/rebikeuser/userUtil.py index cba25df..b8a3d61 100644 --- a/backend/rebikeuser/userUtil.py +++ b/backend/rebikeuser/userUtil.py @@ -3,16 +3,18 @@ from .models import user + # def user_change_alias(user, alias): if user and alias: - if user_find_by_alias(alias): # 해당 alias를 가진 user가 있으면 - return 'this alias is overlapped' + if user_find_by_alias(alias): # 해당 alias를 가진 user가 있으면 + return False user.alias = alias user.save() return True return False + # def user_change_pw(user, pw): if user and pw: @@ -23,29 +25,31 @@ def user_change_pw(user, pw): return True return False -#비밀번호 해시 + +# Password Hashing def user_hash_pw(pw): - pw = pw.encode('utf-8') + pw = str(pw).encode('utf-8') salt = bcrypt.gensalt() hash_pw = bcrypt.hashpw(pw, salt) return hash_pw, salt + # -def user_create_client(user_id, email, pw, alias): - if user_find_by_name(user_id): - return 'this id is overlapped' +def user_create_client(name, email, pw, alias): + if user_find_by_name(name): + return 'this id is duplicated' if user_find_by_alias(alias): - return 'this alias is overlapped' - + return 'this alias is duplicated' hash_pw, salt = user_hash_pw(pw) - user.objects.create(id=uuid.uuid4(), name=user_id, alias=alias, pw=hash_pw, salt=salt, email=email) - return True + return user.objects.create(name=name, alias=alias, pw=hash_pw, salt=salt, email=email) + # return user.objects.all() + # def user_find_by_name(name): qs = user.objects.all() - result = qs.filter(name=name) - return result + return qs.filter(name=name) + # def user_find_by_alias(alias): @@ -53,21 +57,24 @@ def user_find_by_alias(alias): result = qs.filter(alias=alias) return result + # def user_user_search_by_name(name): qs = user.objects.all() result = qs.filter(name__icontains=name) return result + # def user_user_search_by_alias(alias): qs = user.objects.all() result = qs.filter(alias__icontains=alias) return result + # def user_compPW(pw, user): - pw = pw.encode('utf-8') + pw = str(pw).encode('utf-8') salt = user.salt hash_pw = bcrypt.hashpw(pw, salt) return hash_pw == user.pw diff --git a/backend/rebikeuser/views.py b/backend/rebikeuser/views.py index 8c51bfa..050e9b5 100644 --- a/backend/rebikeuser/views.py +++ b/backend/rebikeuser/views.py @@ -1,63 +1,110 @@ from django.http import HttpResponse, JsonResponse + +from django.shortcuts import redirect +from rest_framework.decorators import api_view + from django.core import serializers -from .serializers import UserSerializer +from .serializers import UserSerializer, UserSignupResponse, SignupInput from .userUtil import user_find_by_name, user_compPW, user_create_client, user_change_pw, user_change_alias +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework.renderers import JSONRenderer + +from django.http import HttpResponse +from .models import user + -# 로그인 +@api_view(['POST']) def user_login(request): - input_id = request.GET.get('id', '') - input_pw = request.GET.get('pw', '') + input_name = request.data['name'] + input_pw = request.data['pw'] + is_login = False + + data = None user_data = None is_login = False - if input_pw != '' and input_id != '': - user = user_find_by_name(input_id).first() + if input_pw and input_name: + user = user_find_by_name(input_name).first() if user: - is_login = user_compPW(input_pw, user) - if is_login: - user_data = UserSerializer(user) + if user_compPW(input_pw, user): + user_data = UserSerializer(data={'name': user.name, 'alias': user.alias, 'email': user.email}) + if user_data.is_valid(): + data = { + "user": user_data.data, + "is_login": is_login + } + return JsonResponse(data) - result = { - 'user': user_data.data, - 'is_login': is_login, - } - return JsonResponse(result) +# rebikeuser/views.py +class UserSignupAPI(APIView): + def post(self, request): + name = request.data['name'] # dict로 되있음 + pw = request.data['pw'] # 바디 읽는 법 + alias = request.data['alias'] + email = request.data['email'] + serializer = SignupInput(data={'email': email, 'pw': pw, 'alias': alias, 'name': name}) + if serializer.is_valid(): + str = user_create_client(name, email, pw, alias) + serializer2 = UserSignupResponse(str, many=False) + return Response(serializer2.data) # Only name + return redirect('/user/login/') -# 회원가입 -def user_signup(request): - user_id = request.GET.get('id') - alias = request.GET.get('alias') - email = request.GET.get('email') - pw = request.GET.get('pw') - result = user_create_client(user_id, email, pw, alias) +# get으로 회원가입 폼 화면 가져오기 +# def get(self, request): +# return HttpResponse('회원가입 폼 페이지 연결') - return HttpResponse(result) -# 비밀번호변경 +@api_view(['POST']) def user_pw_change(request): - input_id = request.GET.get('id', '') - input_pw = request.GET.get('pw', '') - result = False + input_name = request.data['name'] + input_pw = request.data['pw'] # 새 비밀번호 + input_past_pw = request.data['pastpw'] # 이전 비밀번호 - if input_pw and input_id: - user = user_find_by_name(input_id).first() - if user: - result = user_change_pw(user, input_pw) + if input_name and input_pw and input_past_pw: + finduser = user_find_by_name(input_name).first() + if finduser.pw == input_past_pw: # 예전 pw와 name으로 찾은 user의 pw 일치여부 + user_change_pw(finduser, input_pw) + return HttpResponse("성공") + # user_change_pw(finduser, input_pw) + else: + return HttpResponse('이전 비밀번호가 일치 하지 않습니다.') + else: + return HttpResponse('실패') - return HttpResponse(result) #변경완료 시 True -# +@api_view(['POST']) def user_alias_change(request): - input_id = request.GET.get('id', '') - input_alias = request.GET.get('alias', '') - result = False + input_name = request.data['name'] + input_alias = request.data['alias'] + + if input_alias and input_name: + finduser = user_find_by_name(input_name).first() + if finduser: + user_change_alias(finduser, input_alias) # True : 변경됨, False : 변경실패 + return HttpResponse('성공') + return False - if input_alias and input_id: - user = user_find_by_name(input_id).first() - if user: - result = user_change_alias(user, input_alias) - return HttpResponse(result) #변경완료 시 True +@api_view(['GET']) +def on_login(request): + qs = user.objects.all() + username = request.GET.get('username', '') + if username: + qs = qs.filter(user_name=username) + return HttpResponse(qs) +# +# def user_pw_change(request): +# input_id = request.GET.get('id', '') +# input_pw = request.GET.get('pw', '') +# result = False +# +# if input_pw and input_id: +# user = user_find_by_name(input_id).first() +# if user: +# result = user_change_pw(user, input_pw) +# +# return HttpResponse(result) #변경완료 시 True diff --git a/backend/requirements.txt b/backend/requirements.txt index 66156f9..095cb56 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -5,6 +5,9 @@ PyMySQL==1.0.2 mysql-connector-python==8.0.23 setuptools==58.1.0 mysqlclient==2.1.1 +djangorestframework==3.13.1 +#django-filter==22.1 +#django-rest-swagger==2.2.0 bcrypt==3.2.2 -djangorestframework -pygments \ No newline at end of file +pygments +django-cors-headers==3.13.0 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 4d76a8f..c28a22e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,10 +8,10 @@ services: - 8080:8080 volumes: - ./backend:/app -# frontend: -# build: ./frontend -# command: ["npm", "start"] -# ports: -# - 3000:3000 -# volumes: -# - ./frontend:/app + frontend: + build: ./frontend + command: ["npm", "start"] + ports: + - 3000:3000 + volumes: + - ./frontend:/app diff --git a/frontend/src/Page/Register.jsx b/frontend/src/Page/Register.jsx index 2259010..8c34e3e 100644 --- a/frontend/src/Page/Register.jsx +++ b/frontend/src/Page/Register.jsx @@ -130,7 +130,7 @@ function Register() { nameRegex.test(name) ) { axios - .post("/user/signup/", { + .post("http://localhost:8080/user/signup/", { name: data.get("name"), pw: data.get("password"), alias: "hohohoho",