하재연

auth modified

# Generated by Django 3.0.7 on 2020-06-10 17:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0008_item_file_type'),
]
operations = [
migrations.RemoveField(
model_name='user',
name='id',
),
migrations.AlterField(
model_name='user',
name='int_id',
field=models.AutoField(primary_key=True, serialize=False),
),
]
# Generated by Django 3.0.7 on 2020-06-10 17:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0009_auto_20200611_0240'),
]
operations = [
migrations.AlterField(
model_name='user',
name='current_size',
field=models.BigIntegerField(blank=True, default=0),
),
migrations.AlterField(
model_name='user',
name='total_size',
field=models.BigIntegerField(blank=True, default=1099511627776),
),
]
......@@ -17,7 +17,7 @@ class Item(models.Model):
status = models.BooleanField()
#file = models.FileField(upload_to = \path)
class Meta:
ordering = ['item_id']
......@@ -33,12 +33,13 @@ class SharedItem(models.Model):
class User(models.Model):
int_id = models.IntegerField()
user_id = models.CharField(max_length = 50)
name = models.CharField(max_length = 50)
password = models.CharField(max_length = 20)
total_size = models.IntegerField()
current_size = models.IntegerField()
int_id = models.AutoField(primary_key=True)
user_id = models.CharField(max_length=50)
name = models.CharField(max_length=50)
password = models.CharField(max_length=20)
total_size = models.BigIntegerField(blank=True, default=1099511627776)
current_size = models.BigIntegerField(blank=True, default=0)
created_time = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['int_id']
......
from django.contrib.auth.models import User, Group
from rest_framework import serializers
from api.models import Item, SharedItem
from api.models import User
class UserSerializer(serializers.HyperlinkedModelSerializer):
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['url', 'username', 'email', 'groups']
fields = '__all__'
class SignUpSerializer(serializers.ModelSerializer):
password2 = serializers.CharField(style={"input_type": "password"})
class GroupSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Group
fields = ['url', 'name']
model = User
fields = ['user_id', 'name', 'password', 'password2']
class ItemSerializer(serializers.ModelSerializer):
def create(self, data):
user_id = data['user_id']
name = data['name']
password = self.data['password']
password2 = self.data['password2']
if user_id and User.objects.filter(user_id=user_id).exclude(name=name).exists():
raise serializers.ValidationError({"user_id": "User_id must be unique."})
elif password != password2:
raise serializers.ValidationError({'password': "Passwords must match."})
user = User.objects.create(
user_id=data['user_id'],
name=data['name'],
password=data['password'],
)
user.save()
return user
class UserInfoSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = '__all__'
model = User
fields = ['user_id', 'name', 'total_size', 'current_size', 'created_time']
......
import jwt
import json
from rest_framework import status
from django.http import JsonResponse
from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings
from api.models import User
def login_decorator(func):
def wrapper(self, request, *args, **kwargs):
if 'Authorization' not in request.headers:
return JsonResponse({'Error': 'INVALID_LOGIN'}, status=status.HTTP_401_UNAUTHORIZED)
encode_token = request.headers['Authorization']
try:
payload = jwt.decode(encode_token, settings.SECRET_KEY, algorithm='HS256')
user = User.objects.get(int_id=payload['int_id'])
request.user = user
except jwt.exceptions.DecodeError:
return JsonResponse({'Error': 'INVALID_TOKEN'}, status=status.HTTP_400)
except User.DoesNotExist:
return JsonResponse({'Error': 'UNKNOWN_USER'}, status=status.HTTP_400)
return func(self, request, *args, **kwargs)
return wrapper
\ No newline at end of file
import mimetypes
import json
import os
from datetime import datetime
import boto3
from django.contrib.auth.models import User
from django.core import serializers
from django.views.decorators.csrf import csrf_exempt
from api.models import User
from rest_framework import viewsets
from rest_framework import permissions
from rest_framework.permissions import IsAuthenticated
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.decorators import action, permission_classes, authentication_classes
from rest_framework import status
from api.serializers import UserSerializer, SignUpSerializer
from rest_framework.response import Response
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated, AllowAny
from django.http import HttpResponse, JsonResponse
import jwt
import json
from datetime import datetime, timedelta
from .utils import login_decorator
from django.conf import settings
from django.views.decorators.csrf import csrf_exempt
from api.models import Item, SharedItem
from api.serializers import UserSerializer,GroupSerializer,ItemSerializer
from rest_framework import status
from annoying.functions import get_object_or_None
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all().order_by('-date_joined')
queryset = User.objects.all().order_by('-int_id')
serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticated]
authentication_classes = [JSONWebTokenAuthentication]
@csrf_exempt
@action(detail=False, methods=['POST'], permission_classes=[permissions.AllowAny], url_path='signup', url_name='singup')
def signup(self, request):
serializer = SignUpSerializer(data=request.data)
if serializer.is_valid():
user = serializer.create(data=request.data)
return Response({
'message': 'user created',
'int_id': user.int_id,
'user_id': user.user_id,
'name': user.name,
'total_size': user.total_size,
'current_size': user.current_size,
'created_time': user.created_time
},
status=status.HTTP_200_OK,
)
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
class ItemViewSet(viewsets.ViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly, permissions.AllowAny,
#IsOwnerOrReadOnly
]
permission_classes_by_action = {'get': [permissions.AllowAny],
'destroy': [permissions.AllowAny]}
# url: items/search
@action(methods=['GET'], detail=False, permission_classes=[AllowAny], url_path='search', url_name='search')
def search(self, request):
if request.method == 'GET':
keyword = request.GET.get('keyword', '')
item_list = Item.objects.filter(name__icontains = keyword)
data = serializers.serialize("json", item_list)
json_data = json.loads(data)
res = []
for i in json_data:
t = i['fields']
t['id'] = i['pk']
res.append(t)
return Response({'data': {'list' : res}}, status=status.HTTP_200_OK)
# url: items/11/
# 마지막 slash도 써주어야함
def get(self, request, pk):
item = Item.objects.filter(item_id=pk)
data = serializers.serialize("json", item)
json_data = json.loads(data)
res = json_data[0]['fields']
res['id']=json_data[0]['pk']
return Response({'data': res}, status=status.HTTP_200_OK)
# url: items/11/
# 마지막 slash도 써주어야함
def destroy(self, request, pk):
if request.method == 'DELETE':
print(pk)
item = get_object_or_None(Item, item_id=pk)
if item != None:
if item.is_folder == True: # 폴더는 삭제 안되도록 처리
return Response({'message': 'This item is folder.'}, status=status.HTTP_200_OK)
item.is_deleted = True
item.save()
# item.delete() 이거 하면 완전 삭제되어버림 is deleted True 면 휴지통에서 리스트 조회할 수 있도록!
return Response({'message': 'delete complete'},status=status.HTTP_200_OK)
return Response({'message': 'item is not existed.'}, status=status.HTTP_204_NO_CONTENT)
# url: items/11/move
# 마지막 slash도 써주어야함
@action(methods=['POST'], detail=True, permission_classes=[AllowAny], url_path='move', url_name='move')
def move(self, request, pk):
if request.method == 'POST':
parent_id = request.POST.get('parent', '')
name = request.POST.get('name','')
parent = get_object_or_None(Item, item_id=parent_id)
if parent != None and parent.is_folder == True:
child = get_object_or_None(Item, item_id=pk)
if child == None:
return Response({'message': 'item is not existed.'}, status=status.HTTP_204_NO_CONTENT)
child.parent = parent_id
child.save()
child = Item.objects.filter(item_id = pk)
child_data = serializers.serialize("json", child)
json_child = json.loads(child_data)
res = json_child[0]['fields']
res['id'] = pk
parent = Item.objects.filter(item_id = parent_id)
parent_data = serializers.serialize("json", parent)
json_parent = json.loads(parent_data)[0]['fields']
res['parentInfo'] = json_parent
return Response({'data': res}, status=status.HTTP_200_OK)
if parent == None:
return Response({'message': 'parent is not existed.'}, status=status.HTTP_200_OK)
if parent.is_folder == False:
return Response({'message': 'parent is not folder.'}, status=status.HTTP_200_OK)
return Response({'message': 'item is not existed.'}, status=status.HTTP_204_NO_CONTENT)
@action(methods=['POST'], detail=True, permission_classes=[AllowAny], url_path='copy', url_name='copy')
def copy(self, request, pk):
if request.method == 'POST':
parent_id = request.POST.get('parent', '')
parent = get_object_or_None(Item, item_id=parent_id)
if parent != None and parent.is_folder == True:
child = get_object_or_None(Item, item_id=pk)
if child == None:
return Response({'message': 'item is not existed.'}, status=status.HTTP_204_NO_CONTENT)
if child.is_folder == True:
return Response({'message': 'item is folder'}, status=status.HTTP_204_NO_CONTENT)
copiedName = child.name + "_복사본_" + str(datetime.now().strftime('%Y-%m-%d %H:%M'))
copiedItem = Item(is_folder = False, name = copiedName, path =child.path, parent = parent_id, user_id= child.user_id, size=child.size, status=child.status)
copiedItem.save()
copiedItem = Item.objects.filter(name = copiedName)
copied_data = serializers.serialize("json", copiedItem)
json_data = json.loads(copied_data)
res = json_data[0]['fields']
res['id'] = json_data[0]['pk']
parent = Item.objects.filter(item_id = parent_id)
parent_data = serializers.serialize("json", parent)
json_parent = json.loads(parent_data)[0]['fields']
res['parentInfo'] = json_parent
return Response({'data': res}, status=status.HTTP_200_OK)
if parent == None:
return Response({'message': 'parent is not existed.'}, status=status.HTTP_200_OK)
if parent.is_folder == False:
return Response({'message': 'parent is not folder.'}, status=status.HTTP_200_OK)
return Response({'message': 'item is not existed.'}, status=status.HTTP_204_NO_CONTENT)
def get_permissions(self):
@csrf_exempt
@action(methods=['post'], detail=False, permission_classes=[permissions.AllowAny],
url_path='login', url_name='login')
def login(self, request):
if not request.data:
return Response({'Error': "Please provide user_id/password"}, status=status.HTTP_400_BAD_REQUEST)
user_id = request.POST['user_id']
password = request.POST['password']
try:
# return permission_classes depending on `action`
return [permission() for permission in self.permission_classes_by_action[self.action]]
except KeyError:
# action is not set return default permission_classes
return [permission() for permission in self.permission_classes]
user = User.objects.get(user_id=user_id, password=password)
except User.DoesNotExist:
return Response({'Error': "Invalid user_id/password"}, status=status.HTTP_400_BAD_REQUEST)
if user:
payload1 = {
'int_id': user.int_id,
'user_id': user.user_id,
'exp': datetime.utcnow() + timedelta(seconds=300)
}
payload2 = {
'int_id': user.int_id,
'user_id': user.user_id,
'exp': datetime.utcnow() + timedelta(days=5)
}
access = jwt.encode(payload1, settings.SECRET_KEY, algorithm='HS256')
access = access.decode('utf-8')
refresh = jwt.encode(payload2, settings.SECRET_KEY, algorithm='HS256')
refresh = refresh.decode('utf-8')
exp = jwt.decode(access, settings.SECRET_KEY, algorithm='HS256')['exp']
token = {'access': access,
'refresh': refresh,
'exp': exp}
return JsonResponse(
token,
status=status.HTTP_200_OK,
)
else:
return JsonResponse(
{'Error': "Invalid credentials"},
status=status.HTTP_400_BAD_REQUEST,
)
return JsonResponse(status=status.HTTP_405_METHOD_NOT_ALLOWED)
class SharedItemViewSet(viewsets.ModelViewSet):
queryset = SharedItem.objects.all()
# serializer_class = SharedItemSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly, permissions.AllowAny,
# IsOwnerOrReadOnly
]
# url: http://localhost:8000/items/1/share/
# 마지막 slash도 써주어야함
@csrf_exempt
@action(methods=['POST'], detail=True, permission_classes=[AllowAny], url_path='share', url_name='share')
def share(self, request, pk):
if request.method == 'POST':
password = request.POST.get('password', '')
expires = request.POST.get('expires', '')
sharedfile = get_object_or_None(SharedItem, item_id=pk)
if sharedfile != None:
# 서버는 정상이나 이미 공유객체로 등록된 파일임
return Response({'message': 'This file is already shared'}, status=status.HTTP_200_OK)
sharedfile = SharedItem(item_id =pk, password=password, expires = expires)
sharedfile.save()
sharedfile = SharedItem.objects.get(item_id = pk)
# sf = serializers.serialize("json", sharedfile)
item = Item.objects.filter(item_id = pk)
item_json = serializers.serialize("json", item)
@login_decorator
@action(methods=['POST'], detail=False, url_path='renew', url_name='renew')
def renew(self, request):
user = request.user
payload1 = {
'int_id': user.int_id,
'user_id': user.user_id,
'exp': datetime.utcnow() + timedelta(seconds=300)
}
payload2 = {
'int_id': user.int_id,
'user_id': user.user_id,
'exp': datetime.utcnow() + timedelta(days=5)
}
access = jwt.encode(payload1, settings.SECRET_KEY, algorithm='HS256')
refresh = jwt.encode(payload2, settings.SECRET_KEY, algorithm='HS256')
exp = jwt.decode(access, settings.SECRET_KEY, algorithm='HS256')['exp']
token = {'access': access,
'refresh': refresh,
'exp': exp}
return JsonResponse(
token,
status=status.HTTP_200_OK,
)
json_data = json.loads(item_json)
print(json_data)
res = json_data[0]['fields']
res['id'] = json_data[0]['pk']
return Response({"shared": sharedfile.created_time , 'data': res}, status=status.HTTP_200_OK)
item = ItemViewSet.as_view({
'delete': 'destroy',
})
\ No newline at end of file
@csrf_exempt
@login_decorator
@action(methods=['GET'], detail=True, permission_classes=[permissions.IsAuthenticated],
url_path='info', url_name='info')
def info(self, request, pk):
if request.method == 'GET':
user = User.objects.get(id=pk)
data = {
'int_id': user.int_id,
'user_id': user.user_id,
'name': user.name,
'total_size': user.total_size,
'current_size': user.current_size,
'created_time': user.created_time
}
return HttpResponse(
data,
status=status.HTTP_200_OK,
content_type="application/json")
return HttpResponse(
{'Error': 'The Method is not allowed.'},
status=status.HTTP_405_METHOD_NOT_ALLOWED,
content_type="application/json")
......
"""
Django settings for khudrive project.
Generated by 'django-admin startproject' using Django 3.0.7.
For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = ')i0_(*4t7k3=rcqp*_i0u((9zbk8q(2(3tk(%$woji-e-37=o*'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
......@@ -40,7 +27,6 @@ INSTALLED_APPS = [
'rest_framework',
'api.apps.ApiConfig',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
......@@ -50,9 +36,7 @@ MIDDLEWARE = [
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'khudrive.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
......@@ -68,10 +52,7 @@ TEMPLATES = [
},
},
]
WSGI_APPLICATION = 'khudrive.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
DATABASES = {
......@@ -82,17 +63,14 @@ DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'khuDrive',
'USER': 'jooheekwon',
'PASSWORD': '',
'USER': 'hjy',
'PASSWORD': '2521',
'HOST': 'localhost',
'PORT': '',
'PORT': '5432',
}
}
# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
......@@ -107,23 +85,13 @@ AUTH_PASSWORD_VALIDATORS = [
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/
STATIC_URL = '/static/'
STATIC_URL = '/static/'
\ No newline at end of file
......
"""khudrive URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.urls import include, path
from rest_framework import routers
from django.contrib import admin
from api import views
from django.conf.urls import url
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'items', views.ItemViewSet)
router.register(r'items', views.SharedItemViewSet)
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
path('admin/', admin.site.urls),
path('', include(router.urls)),
url(r'^search/$', views.ItemViewSet.search, name='search'),
url(r'^<int:pk>/share/$', views.SharedItemViewSet.share, name='share'),
url(r'^<int:pk>/move/$', views.ItemViewSet.move, name='move'),
url(r'^<int:pk>/copy/$', views.ItemViewSet.copy, name='copy'),
]
url(r'^signup/$', views.UserViewSet.signup, name='signup'),
url(r'^login/$', views.UserViewSet.login, name='login'),
url(r'^renew/$', views.UserViewSet.renew, name='renew'),
url(r'^<int:pk>/info/$', views.UserViewSet.info, name='info'),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]
\ No newline at end of file
......