김재형

Merge remote-tracking branch 'origin/master' into feature/frontend

# Conflicts:
#	backend/api/views.py
#	backend/khudrive/settings.py
......@@ -14,7 +14,7 @@ class Item(models.Model):
is_deleted = models.BooleanField(default = False)
created_time = models.DateTimeField(auto_now=True)
updated_time = models.DateTimeField(null=True)
status = models.BooleanField()
status = models.BooleanField(default=False)
#file = models.FileField(upload_to = \path)
......
......@@ -4,6 +4,7 @@ import os
from datetime import datetime, timedelta
import boto3
from botocore.client import Config
from django.core import serializers
from django.views.decorators.csrf import csrf_exempt
......@@ -14,12 +15,14 @@ from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated, AllowAny
from .models import Item, SharedItem, User
from .serializers import UserSerializer,GroupSerializer,ItemSerializer
from .serializers import UserSerializer, GroupSerializer, ItemSerializer
from rest_framework import status
from annoying.functions import get_object_or_None
from django.conf import settings
import jwt
from django.http import HttpResponse, JsonResponse
from khudrive.settings import AWS_SESSION_TOKEN, AWS_SECRET_ACCESS_KEY, AWS_ACCESS_KEY_ID, AWS_REGION, \
AWS_STORAGE_BUCKET_NAME
class UserViewSet(viewsets.ModelViewSet):
......@@ -33,15 +36,17 @@ class UserViewSet(viewsets.ModelViewSet):
]
permission_classes_by_action = {'get': [permissions.AllowAny],
'destroy': [permissions.AllowAny]}
@csrf_exempt
@action(detail=False, methods=['POST'], permission_classes=[permissions.AllowAny], url_path='signup', url_name='singup')
@action(detail=False, methods=['POST'], permission_classes=[permissions.AllowAny], url_path='signup',
url_name='singup')
def signup(self, request):
user_id = request.POST.get('user_id', '')
name = request.POST.get('name', '')
password = request.POST.get('password', '')
user = get_object_or_None(User, user_id=user_id)
if user == None:
user = User(user_id = user_id, name = name, password = password, total_size=100000, current_size = 0)
user = User(user_id=user_id, name=name, password=password, total_size=100000, current_size=0)
user.save()
root = Item(is_folder=True, name="root", file_type="folder", path="", user_id=user.int_id, size=0,
status=True)
......@@ -53,7 +58,7 @@ class UserViewSet(viewsets.ModelViewSet):
'int_id': user.int_id,
'user_id': user.user_id,
'name': user.name,
'root_folder':root.item_id,
'root_folder': root.item_id,
'total_size': user.total_size,
'current_size': user.current_size,
'created_time': user.created_time
......@@ -116,7 +121,7 @@ class UserViewSet(viewsets.ModelViewSet):
data = serializers.serialize("json", user)
json_data = json.loads(data)
res = json_data[0]['fields']
res['id']=json_data[0]['pk']
res['id'] = json_data[0]['pk']
return Response({'data': res}, status=status.HTTP_200_OK)
def get_permissions(self):
......@@ -129,11 +134,10 @@ class UserViewSet(viewsets.ModelViewSet):
class ItemViewSet(viewsets.ViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly, permissions.AllowAny,
#IsOwnerOrReadOnly
# IsOwnerOrReadOnly
]
permission_classes_by_action = {'get': [permissions.AllowAny],
'destroy': [permissions.AllowAny]}
......@@ -143,8 +147,8 @@ class ItemViewSet(viewsets.ViewSet):
def search(self, request):
if request.method == 'GET':
keyword = request.GET.get('keyword', '')
user_id = request.GET.get('user_id', '')
item_list = Item.objects.filter(name__icontains = keyword, user_id = user_id )
# user_id = request.GET.get('user_id', '')
item_list = Item.objects.filter(name__icontains=keyword)
data = serializers.serialize("json", item_list)
json_data = json.loads(data)
......@@ -153,33 +157,92 @@ class ItemViewSet(viewsets.ViewSet):
t = i['fields']
t['id'] = i['pk']
res.append(t)
return Response({'data': {'list' : res}}, status=status.HTTP_200_OK)
return Response({'data': {'list': res}}, status=status.HTTP_200_OK)
"""
# url: items/11/
# 마지막 slash도 써주어야함
def get(self, request, pk):
#print(pk)
s3 = boto3.client('s3')
s3_bucket = AWS_STORAGE_BUCKET_NAME
#파일 객체 생성
object_name = request.GET.get('name', '')
presigned_url = s3.generate_presigned_url(
'get_object',
Params={'Bucket': s3_bucket,
'Key': object_name},
ExpiresIn = 3600
)
return Response({'message': presigned_url}, status=status.HTTP_200_OK)
"""
# url: items/11/
# 마지막 slash도 써주어야함
def get(self, request, pk):
s3 = boto3.client('s3',
aws_access_key_id=AWS_ACCESS_KEY_ID,
aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
aws_session_token=AWS_SESSION_TOKEN,
config=Config(signature_version='s3v4'))
s3_bucket = AWS_STORAGE_BUCKET_NAME
item = Item.objects.filter(item_id=pk)
object_name = item.get().name
data = serializers.serialize("json", item)
json_data = json.loads(data)
presigned_url = s3.generate_presigned_url(
'get_object',
Params={'Bucket': s3_bucket,
'Key': object_name},
ExpiresIn=3600
)
res = json_data[0]['fields']
res['id']=json_data[0]['pk']
res['id'] = json_data[0]['pk']
res['signed_url'] = presigned_url
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: # 폴더는 삭제 안되도록 처리
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': 'destroy complete'}, 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='restore', url_name='restore')
def restore(self, request, pk):
if request.method == 'POST':
item = get_object_or_None(Item, item_id=pk)
if item != None:
item.is_deleted = False
item.save()
return Response({'message': 'restore complete'}, status=status.HTTP_200_OK)
return Response({'message': 'item is not existed.'}, status=status.HTTP_204_NO_CONTENT)
@action(methods=['DELETE'], detail=True, permission_classes=[AllowAny], url_path='delete', url_name='delete')
def delete(self, request, pk):
if request.method == 'DELETE':
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.delete()
return Response({'message': 'delete permanently 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')
......@@ -233,15 +296,16 @@ class ItemViewSet(viewsets.ViewSet):
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 = 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)
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 = 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
......@@ -265,10 +329,10 @@ class ItemViewSet(viewsets.ViewSet):
url_path='children', url_name='children')
def children(self, request, pk):
if request.method == 'GET':
children = Item.objects.filter(parent = pk, is_deleted=False)
children = Item.objects.filter(parent=pk, is_deleted=False)
children_data = serializers.serialize("json", children)
json_children = json.loads(children_data)
parent = Item.objects.filter(item_id=pk) #item
parent = Item.objects.filter(item_id=pk) # item
parent_data = serializers.serialize("json", parent)
json_parent = json.loads(parent_data)[0]['fields']
res = json_parent
......@@ -283,25 +347,99 @@ class ItemViewSet(viewsets.ViewSet):
if request.method == 'POST':
name = request.POST.get('name', '')
user_id = request.GET.get('user_id', '')
item = Item(is_folder=True, name=name, file_type="folder", path="", parent=pk, user_id=user_id, size=0, status=True)
item = Item(is_folder=True, name=name, file_type="folder", path="", parent=pk, user_id=user_id, size=0,
status=True)
item.save()
item = Item.objects.filter(item_id = item.item_id)
item = Item.objects.filter(item_id=item.item_id)
item_data = serializers.serialize("json", item)
json_item = json.loads(item_data)
res = json_item[0]['fields']
res['id']=json_item[0]['pk']
res['id'] = json_item[0]['pk']
res['inside_folder_list'] = []
res['inside_file_list'] = []
return Response({'data': res}, status=status.HTTP_200_OK)
@action(methods=['GET'], detail=False, permission_classes=[AllowAny],
url_path='trash', url_name='trash')
def trash(self, request):
if request.method == 'GET':
children = Item.objects.filter(is_deleted = True)
children_data = serializers.serialize("json", children)
json_children = json.loads(children_data)
res = {}
children_list = []
for i in json_children:
t = i['fields']
t['id'] = i['pk']
children_list.append(t)
res['list'] = children_list
return Response({'data': res}, status=status.HTTP_200_OK)
class SharedItemViewSet(viewsets.ModelViewSet):
# url: /upload/
@action(methods=['POST'], detail=True, permission_classes=[AllowAny],
url_path='upload', url_name='upload')
def upload(self, request, pk):
if request.method == 'POST':
s3 = boto3.client('s3')
s3_bucket = AWS_STORAGE_BUCKET_NAME
# 파일 객체 생성
file_name = request.POST.get('name', '')
file_size = request.POST.get('size', '')
file_parent = pk
file_type = mimetypes.guess_type(file_name)[0]
upload_item = Item(name=file_name, size=file_size, user_id=1, file_type=file_type, parent=file_parent)
upload_item.save()
date_long = datetime.utcnow().strftime('%Y%m%dT000000Z')
presigned_post = s3.generate_presigned_post(
s3_bucket,
file_name,
{
"acl": "private",
"Content-Type": file_type,
'region': AWS_REGION,
'x-amz-algorithm': 'AWS4-HMAC-SHA256',
'x-amz-date': date_long
},
[
{"acl": "private"},
{"Content-Type": file_type},
{'x-amz-algorithm': 'AWS4-HMAC-SHA256'},
{'x-amz-date': date_long}
],
3600
)
data = {
"signed_url": presigned_post,
'url': 'https://%s.s3.amazonaws.com/%s' % (s3_bucket, file_name)
}
return Response({'presigned_post': presigned_post, 'proc_data': data}, status=status.HTTP_200_OK)
# url: /status/
@action(methods=['POST'], detail=True, permission_classes=[AllowAny],
url_path='status', url_name='status')
def status(self, request, *args, **kwargs):
if request.method == 'POST':
pk = request.POST.get('item_id', '')
queryset = Item.objects.filter(item_id=pk)
for cand in queryset:
cand.status = True
cand.save()
return Response({'Message': 'File Upload Successful'}, status=status.HTTP_200_OK)
return Response({'Error': 'No such item found in queryset'}, status=status.HTTP_400_BAD_REQUEST)
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
......@@ -315,20 +453,21 @@ class SharedItemViewSet(viewsets.ModelViewSet):
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 = SharedItem(item_id=pk, password=password, expires=expires)
sharedfile.save()
sharedfile = SharedItem.objects.get(item_id = pk)
sharedfile = SharedItem.objects.get(item_id=pk)
# sf = serializers.serialize("json", sharedfile)
item = Item.objects.filter(item_id = pk)
item = Item.objects.filter(item_id=pk)
item_json = serializers.serialize("json", item)
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)
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
......
......@@ -11,10 +11,17 @@ https://docs.djangoproject.com/en/3.0/ref/settings/
"""
import os
import sys
import json
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
ROOT_DIR = os.path.dirname(BASE_DIR)
# secrets.json의 경로
SECRETS_PATH = os.path.join(ROOT_DIR, 'secrets.json')
# json파일을 파이썬 객체로 변환
secrets = json.loads(open(SECRETS_PATH).read())
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
......@@ -127,3 +134,11 @@ USE_TZ = True
# https://docs.djangoproject.com/en/3.0/howto/static-files/
STATIC_URL = '/static/'
#S3
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
for key, value in secrets.items():
setattr(sys.modules[__name__], key, value)
\ No newline at end of file
......
......@@ -30,11 +30,15 @@ urlpatterns = [
path('admin/', admin.site.urls),
path('', include(router.urls)),
url(r'^search/$', views.ItemViewSet.search, name='search'),
url(r'^<int:pk>/delete/$', views.ItemViewSet.delete, name='delete'),
url(r'^<int:pk>/restore/$', views.ItemViewSet.restore, name='restore'),
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'^<int:pk>/children/$', views.ItemViewSet.children, name='copy'),
url(r'^<int:pk>/children/$', views.ItemViewSet.children, name='children'),
url(r'^trash/$', views.ItemViewSet.trash, name='trash'),
url(r'^signup/$', views.UserViewSet.signup, name='signup'),
url(r'^login/$', views.UserViewSet.login, name='login'),
]
url(r'^upload/$', views.ItemViewSet.upload, name='upload'),
url(r'^status/$', views.ItemViewSet.status, name='status'),
]
\ No newline at end of file
......
......@@ -22,3 +22,4 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
.idea
secrets.json
......