Builds for
2 pipelines
canceled
in
15 minutes 31 seconds
Merge branch 'feature/upload' into 'master'
Feature/upload See merge request !8
Showing
9 changed files
with
177 additions
and
104 deletions
... | @@ -23,7 +23,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | ... | @@ -23,7 +23,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
23 | SECRET_KEY = 'wfs076redt^-5_*dw6!_dqz*2z!a_#()33y@r_q7&+4r_40h9$' | 23 | SECRET_KEY = 'wfs076redt^-5_*dw6!_dqz*2z!a_#()33y@r_q7&+4r_40h9$' |
24 | 24 | ||
25 | # SECURITY WARNING: don't run with debug turned on in production! | 25 | # SECURITY WARNING: don't run with debug turned on in production! |
26 | -DEBUG = True | 26 | +DEBUG = False |
27 | 27 | ||
28 | ALLOWED_HOSTS = ['127.0.0.1', 'khubox-api.khunet.net'] | 28 | ALLOWED_HOSTS = ['127.0.0.1', 'khubox-api.khunet.net'] |
29 | 29 | ||
... | @@ -49,6 +49,7 @@ MIDDLEWARE = [ | ... | @@ -49,6 +49,7 @@ MIDDLEWARE = [ |
49 | 'django.contrib.auth.middleware.AuthenticationMiddleware', | 49 | 'django.contrib.auth.middleware.AuthenticationMiddleware', |
50 | 'django.contrib.messages.middleware.MessageMiddleware', | 50 | 'django.contrib.messages.middleware.MessageMiddleware', |
51 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', | 51 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', |
52 | + 'khubox.middlewares.auth.AuthMiddleware', | ||
52 | ] | 53 | ] |
53 | 54 | ||
54 | ROOT_URLCONF = 'config.urls' | 55 | ROOT_URLCONF = 'config.urls' |
... | @@ -128,9 +129,6 @@ STATIC_URL = '/static/' | ... | @@ -128,9 +129,6 @@ STATIC_URL = '/static/' |
128 | 129 | ||
129 | # Custom Settings | 130 | # Custom Settings |
130 | S3_BUCKET = 'khubox-files' | 131 | S3_BUCKET = 'khubox-files' |
131 | -CDN_PATH = 'https://khubox-files.khunet.net' | ||
132 | -CLOUDFRONT_KEY_ID = 'APKAJ3FOBWI34OZJTXJQ' | ||
133 | -CLOUDFRONT_KEY_PRIVATE = '-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA18VtzURs+fQev5L00LRwRbJaObQI4kfJCIsOE7eWSOqq4Akh\nA7fI6vs3z8orXBvgc+k6GgAHrIdNwckxoQuTsCxrTDm1104qy1T4JkVxkIBYHJgH\nGzKUloK5IqdmcYbOK7IQeHJ2gR9Mv/3oKUytJSsrbM9k4oLrsxGpyEuJeHIg28aP\nwhoVWmBGcPu48l4aYAZEVY7LZRJSOQ9y7Lf8FS1u7Xtw1P91gEaqrqVXqRWY02C8\nsixpJJuiAPnM3rpcpVNlAaPdDkWmaWYJoJDOlce7Dmx1a9Ckr24krM//vpEljurC\nGml0AsHpL8LE9msM5VA+miCxCz/K+wDgm2xvvQIDAQABAoIBAFmP3pLceyuJVBYK\n5smWjB+x91eKTkG2sFB2f8JZau0bUxApWeXULHa1DiaW8UaLX7BdN7vBFW5cvz7X\nx1zklEoFNghuz/btwD+kJlikbI4hZ/F+fTyh0yFiY3xp5dDrtrpWcBW+1UeleVMc\nDnjOFfSepajFsUeANlue0k2MZSRz34s2T2scV5ZkooqdXddYUF/wDhefYm6uvCgI\nPyvY/mbJTyhte/xagY/m6yzk5gxgad0qP2ZZrHhLLMlJ/GEZToWDxD2xUei61NQT\nFFc5ZutkAE6fVb3I4SJUBSX5fl0tTMz4Aak1GP2phMhjZyjYnQMq8kvL4BNFb7gp\nary8W/UCgYEA+eKkfjjlPsEx6yHMhD7pAwy/MpUqJmF5LMxIG+qfd+GZMQ2oucn5\npUAwBHP7BD6E9H7/7jdjnCiO+iPrzM9vNLfqsdCtPWzoFYJp/6Fv002uX8seNYvJ\nQyQqrM85LYIghhnkcmJMA8GR/Iu5ZEeE2BkAl9T2EKclzmB62d/ki6MCgYEA3Q0V\nz08IEwSJW+jEsOM+XGg2YkNqCVKGQD9n4CPx0TFVJxfqFl2nVwlN2hfrlJLUQ9+l\nfXnS5AW3tE88t9we+ea0saJZEqqlm/rGsfTV/twS9cWSgvG5fTzhUbu9/ElMU29L\nmydQfWTvCup7zCuQtgwM5ZRtPwuKsI8urUg6zR8CgYAt0coZvvMCI8i0dbkbkrGF\nNqQkcUeOTBc9CKQ8QjRFdh9x6DBFCOz2ySNE3cNsTs5wSo1BL/Ta4HD/GvEU2ABr\nKUImor3xYnPX5dbr4b0wgLD1rbf3V49q+Um98C1q086E6GCEPNP1aFwNc81lvtt0\nCHmcXZdVDGEZS4WbR7uPgwKBgBO/moY12lPQoPDsH75p3uVkjg9DVJLWo5XT1FTr\nASyeSqw+b7Rl05BsDV+BqZNRdtNFhMRsANJMTHg4aAVJDh9nZBdGmMyZIEiKI/w8\nEm49fRgl+YvnSpoMuViS/EswxTfjBo8q+P7q6IxCHKNF9Ry+gNx14TizsEVL1XC3\ntkEjAoGBAMyp7wdPobJMXcclRVq6rqHs9OMcnZAveVKyxNgDbZu4OB5X4xTxGEYT\nNZQ0MFf/HcwlnH7797gVQeqF9dlqUJYe+Fc8lc/Rcwta/4R5uMgri9t8RKN91YKF\nUUFBsDEkWlkoAmfPkcrrq9cLJlmSNt3ehQj4p5iAJwoVBXXa++PO\n-----END RSA PRIVATE KEY-----' | ||
134 | 132 | ||
135 | 133 | ||
136 | # Cors | 134 | # Cors | ... | ... |
1 | import boto3 | 1 | import boto3 |
2 | -import datetime | ||
3 | -from botocore.signers import CloudFrontSigner | ||
4 | -from cryptography.hazmat.backends import default_backend | ||
5 | -from cryptography.hazmat.primitives import hashes, serialization | ||
6 | -from cryptography.hazmat.primitives.asymmetric import padding | ||
7 | from django.conf import settings | 2 | from django.conf import settings |
8 | 3 | ||
9 | 4 | ||
10 | -def rsa_signer(message): | 5 | +def sign_download(file_id): |
11 | - private_key = serialization.load_pem_private_key( | 6 | + s3 = boto3.client('s3') |
12 | - settings.CLOUDFRONT_KEY_PRIVATE.encode('ascii'), | 7 | + signed_url = s3.generate_presigned_url( |
13 | - password=None, | 8 | + 'get_object', |
14 | - backend=default_backend() | 9 | + Params={'Bucket': settings.S3_BUCKET, 'Key': file_id}, |
10 | + ExpiresIn=3600, | ||
11 | + HttpMethod='GET' | ||
15 | ) | 12 | ) |
16 | - return private_key.sign(message, padding.PKCS1v15(), hashes.SHA1()) | ||
17 | - | ||
18 | - | ||
19 | -def sign_download(url): | ||
20 | - expire_date = datetime.datetime.utcnow() + datetime.timedelta(hours=1) | ||
21 | - cloudfront_signer = CloudFrontSigner(settings.CLOUDFRONT_KEY_ID, rsa_signer) | ||
22 | - signed_url = cloudfront_signer.generate_presigned_url(url, date_less_than=expire_date) | ||
23 | return signed_url | 13 | return signed_url |
24 | 14 | ||
25 | 15 | ||
... | @@ -52,3 +42,13 @@ def s3_copy(file_id, new_file_id): | ... | @@ -52,3 +42,13 @@ def s3_copy(file_id, new_file_id): |
52 | } | 42 | } |
53 | obj = bucket.Object(str(new_file_id)) | 43 | obj = bucket.Object(str(new_file_id)) |
54 | obj.copy(copy_source) | 44 | obj.copy(copy_source) |
45 | + | ||
46 | + | ||
47 | +def s3_update_and_return_size(file_id, name): | ||
48 | + s3 = boto3.resource('s3') | ||
49 | + s3_object = s3.Object(settings.S3_BUCKET, file_id) | ||
50 | + s3_object.copy_from(CopySource={'Bucket': settings.S3_BUCKET, 'Key': file_id}, | ||
51 | + ContentType='application/octet-stream', | ||
52 | + ContentDisposition='attachment; filename=%s' % name, | ||
53 | + MetadataDirective='REPLACE') | ||
54 | + return s3_object.content_length | ... | ... |
khubox-api/khubox/lambda.py
0 → 100644
1 | +import os | ||
2 | +import django | ||
3 | +from .aws import s3_delete, s3_update_and_return_size | ||
4 | +from .models import File | ||
5 | + | ||
6 | +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings") | ||
7 | +django.setup() | ||
8 | + | ||
9 | + | ||
10 | +def process_upload(event, context): | ||
11 | + file_id = event['Records'][0]['s3']['object']['key'] | ||
12 | + file = File.objects.filter(id=file_id, deleted_at__isnull=True) | ||
13 | + | ||
14 | + # File Gone | ||
15 | + if len(file) == 0: | ||
16 | + s3_delete([file_id]) | ||
17 | + return | ||
18 | + | ||
19 | + # Update | ||
20 | + file[0].size = s3_update_and_return_size(file_id, file[0].name) | ||
21 | + file[0].save() |
khubox-api/khubox/middlewares/auth.py
0 → 100644
1 | +import jwt | ||
2 | +from django.conf import settings | ||
3 | +from django.http import JsonResponse | ||
4 | + | ||
5 | + | ||
6 | +class AuthMiddleware: | ||
7 | + def __init__(self, get_response): | ||
8 | + self.get_response = get_response | ||
9 | + | ||
10 | + def __call__(self, request): | ||
11 | + if 'HTTP_AUTHORIZATION' in request.META: | ||
12 | + token = str(request.META['HTTP_AUTHORIZATION'])[7:] | ||
13 | + try: | ||
14 | + decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256']) | ||
15 | + request.user_id = decoded['id'] | ||
16 | + except jwt.exceptions.DecodeError: | ||
17 | + return JsonResponse({'result': False, 'error': '토큰이 잘못되었습니다.'}) | ||
18 | + except jwt.exceptions.ExpiredSignatureError: | ||
19 | + return JsonResponse({'result': False, 'error': '토큰이 만료되었습니다.'}) | ||
20 | + else: | ||
21 | + request.user_id = None | ||
22 | + | ||
23 | + response = self.get_response(request) | ||
24 | + return response |
1 | import json | 1 | import json |
2 | import uuid | 2 | import uuid |
3 | -from django.conf import settings | ||
4 | from django.utils import timezone | 3 | from django.utils import timezone |
5 | -from ..aws import sign_upload, sign_download, s3_copy, s3_delete | 4 | +from pathvalidate import sanitize_filename |
5 | +from ..aws import sign_upload, sign_download, s3_copy, s3_delete, s3_update_and_return_size | ||
6 | from ..models import File, GroupUser | 6 | from ..models import File, GroupUser |
7 | 7 | ||
8 | 8 | ||
9 | # 폴더/파일 목록 | 9 | # 폴더/파일 목록 |
10 | def list_item(request): | 10 | def list_item(request): |
11 | - # TODO: Auth | 11 | + # Check Login |
12 | - request.user_id = 1 | 12 | + if request.user_id is None: |
13 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
13 | 14 | ||
14 | # Validate | 15 | # Validate |
15 | if request.GET.get('is_public') != 'true' \ | 16 | if request.GET.get('is_public') != 'true' \ |
16 | and request.GET.get('is_starred') != 'true' \ | 17 | and request.GET.get('is_starred') != 'true' \ |
17 | and request.GET.get('is_trashed') != 'true': | 18 | and request.GET.get('is_trashed') != 'true': |
18 | - return {'result': False, 'error': '입력이 누락되었습니다.'} | 19 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
19 | 20 | ||
20 | # Query Files | 21 | # Query Files |
21 | files = None | 22 | files = None |
... | @@ -26,7 +27,7 @@ def list_item(request): | ... | @@ -26,7 +27,7 @@ def list_item(request): |
26 | elif request.GET.get('is_trashed') == 'true': | 27 | elif request.GET.get('is_trashed') == 'true': |
27 | files = File.objects.filter(owner_user_id=request.user_id, is_trashed=1, deleted_at__isnull=True) | 28 | files = File.objects.filter(owner_user_id=request.user_id, is_trashed=1, deleted_at__isnull=True) |
28 | 29 | ||
29 | - # Structure | 30 | + # Serialize |
30 | data = [] | 31 | data = [] |
31 | for file in files: | 32 | for file in files: |
32 | data.append({ | 33 | data.append({ |
... | @@ -45,23 +46,24 @@ def list_item(request): | ... | @@ -45,23 +46,24 @@ def list_item(request): |
45 | 46 | ||
46 | # 폴더 생성, 파일 업로드 | 47 | # 폴더 생성, 파일 업로드 |
47 | def create(request): | 48 | def create(request): |
48 | - # TODO: Auth | 49 | + # Check Login |
49 | - request.user_id = 1 | 50 | + if request.user_id is None: |
51 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
50 | 52 | ||
51 | # Load | 53 | # Load |
52 | try: | 54 | try: |
53 | received = json.loads(request.body.decode('utf-8')) | 55 | received = json.loads(request.body.decode('utf-8')) |
54 | except json.decoder.JSONDecodeError: | 56 | except json.decoder.JSONDecodeError: |
55 | - return {'result': False, 'error': '입력이 잘못되었습니다.'} | 57 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
56 | 58 | ||
57 | # Validate | 59 | # Validate |
58 | if 'parent_id' not in received \ | 60 | if 'parent_id' not in received \ |
59 | or 'type' not in received \ | 61 | or 'type' not in received \ |
60 | or 'name' not in received: | 62 | or 'name' not in received: |
61 | - return {'result': False, 'error': '입력이 누락되었습니다.'} | 63 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
62 | if (received['type'] != 'folder' and received['type'] != 'file') \ | 64 | if (received['type'] != 'folder' and received['type'] != 'file') \ |
63 | or received['name'] == '': | 65 | or received['name'] == '': |
64 | - return {'result': False, 'error': '입력이 잘못되었습니다.'} | 66 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
65 | 67 | ||
66 | # Get Parent | 68 | # Get Parent |
67 | parent = File.objects.filter(id=received['parent_id'], is_trashed=0, deleted_at__isnull=True) | 69 | parent = File.objects.filter(id=received['parent_id'], is_trashed=0, deleted_at__isnull=True) |
... | @@ -89,7 +91,7 @@ def create(request): | ... | @@ -89,7 +91,7 @@ def create(request): |
89 | owner_group_id=parent[0].owner_group_id, | 91 | owner_group_id=parent[0].owner_group_id, |
90 | uploader_id=request.user_id, | 92 | uploader_id=request.user_id, |
91 | type=received['type'], | 93 | type=received['type'], |
92 | - name=received['name'], | 94 | + name=sanitize_filename(received['name']), |
93 | size=0, | 95 | size=0, |
94 | created_at=timezone.now() | 96 | created_at=timezone.now() |
95 | ) | 97 | ) |
... | @@ -105,8 +107,9 @@ def create(request): | ... | @@ -105,8 +107,9 @@ def create(request): |
105 | 107 | ||
106 | # 휴지통 비우기 | 108 | # 휴지통 비우기 |
107 | def empty_trash(request): | 109 | def empty_trash(request): |
108 | - # TODO: Auth | 110 | + # Check Login |
109 | - request.user_id = 1 | 111 | + if request.user_id is None: |
112 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
110 | 113 | ||
111 | # Query Files | 114 | # Query Files |
112 | files = File.objects.filter(owner_user_id=request.user_id, is_trashed=1, deleted_at__isnull=True) | 115 | files = File.objects.filter(owner_user_id=request.user_id, is_trashed=1, deleted_at__isnull=True) |
... | @@ -138,8 +141,9 @@ def empty_trash(request): | ... | @@ -138,8 +141,9 @@ def empty_trash(request): |
138 | 141 | ||
139 | # 폴더/파일 조회 | 142 | # 폴더/파일 조회 |
140 | def find_item(request, file_id): | 143 | def find_item(request, file_id): |
141 | - # TODO: Auth | 144 | + # Check Login |
142 | - request.user_id = 1 | 145 | + if request.user_id is None: |
146 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
143 | 147 | ||
144 | # Query | 148 | # Query |
145 | file = File.objects.filter(id=file_id, deleted_at__isnull=True) | 149 | file = File.objects.filter(id=file_id, deleted_at__isnull=True) |
... | @@ -174,12 +178,10 @@ def find_item(request, file_id): | ... | @@ -174,12 +178,10 @@ def find_item(request, file_id): |
174 | 178 | ||
175 | # Return File | 179 | # Return File |
176 | if file[0].type == 'file': | 180 | if file[0].type == 'file': |
177 | - download_url = '%s/%s' % (settings.CDN_PATH, file[0].id) | 181 | + download_url = sign_download(file[0].id) |
178 | - download_url = sign_download(download_url) | ||
179 | data = { | 182 | data = { |
180 | 'id': file[0].id, | 183 | 'id': file[0].id, |
181 | 'parent_id': file[0].parent_id, | 184 | 'parent_id': file[0].parent_id, |
182 | - 'uploader_id': file[0].uploader_id, | ||
183 | 'name': file[0].name, | 185 | 'name': file[0].name, |
184 | 'size': file[0].size, | 186 | 'size': file[0].size, |
185 | 'is_public': file[0].is_public, | 187 | 'is_public': file[0].is_public, |
... | @@ -213,14 +215,15 @@ def find_item(request, file_id): | ... | @@ -213,14 +215,15 @@ def find_item(request, file_id): |
213 | 215 | ||
214 | # 폴더/파일 수정 | 216 | # 폴더/파일 수정 |
215 | def update_item(request, file_id): | 217 | def update_item(request, file_id): |
216 | - # TODO: Auth | 218 | + # Check Login |
217 | - request.user_id = 1 | 219 | + if request.user_id is None: |
220 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
218 | 221 | ||
219 | # Load | 222 | # Load |
220 | try: | 223 | try: |
221 | received = json.loads(request.body.decode('utf-8')) | 224 | received = json.loads(request.body.decode('utf-8')) |
222 | except json.decoder.JSONDecodeError: | 225 | except json.decoder.JSONDecodeError: |
223 | - return {'result': False, 'error': '입력이 잘못되었습니다.'} | 226 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
224 | 227 | ||
225 | # Validate | 228 | # Validate |
226 | if 'name' not in received \ | 229 | if 'name' not in received \ |
... | @@ -228,7 +231,7 @@ def update_item(request, file_id): | ... | @@ -228,7 +231,7 @@ def update_item(request, file_id): |
228 | and 'is_public' not in received \ | 231 | and 'is_public' not in received \ |
229 | and 'is_starred' not in received \ | 232 | and 'is_starred' not in received \ |
230 | and 'is_trashed' not in received: | 233 | and 'is_trashed' not in received: |
231 | - return {'result': False, 'error': '입력이 누락되었습니다.'} | 234 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
232 | 235 | ||
233 | # Query | 236 | # Query |
234 | file = File.objects.filter(id=file_id, deleted_at__isnull=True) | 237 | file = File.objects.filter(id=file_id, deleted_at__isnull=True) |
... | @@ -267,7 +270,10 @@ def update_item(request, file_id): | ... | @@ -267,7 +270,10 @@ def update_item(request, file_id): |
267 | 270 | ||
268 | # Update | 271 | # Update |
269 | if 'name' in received: | 272 | if 'name' in received: |
270 | - file[0].name = received['name'] | 273 | + if received['name'] == '': |
274 | + return {'result': False, 'error': '이름을 제대로 입력해주세요.'} | ||
275 | + file[0].name = sanitize_filename(received['name']) | ||
276 | + s3_update_and_return_size(file_id, file[0].name) | ||
271 | if 'parent_id' in received: | 277 | if 'parent_id' in received: |
272 | file[0].parent_id = received['parent_id'] | 278 | file[0].parent_id = received['parent_id'] |
273 | if 'is_public' in received: | 279 | if 'is_public' in received: |
... | @@ -285,8 +291,9 @@ def update_item(request, file_id): | ... | @@ -285,8 +291,9 @@ def update_item(request, file_id): |
285 | 291 | ||
286 | # 파일 복제 | 292 | # 파일 복제 |
287 | def copy(request, file_id): | 293 | def copy(request, file_id): |
288 | - # TODO: Auth | 294 | + # Check Login |
289 | - request.user_id = 1 | 295 | + if request.user_id is None: |
296 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
290 | 297 | ||
291 | # Get File | 298 | # Get File |
292 | file = File.objects.filter(id=file_id, type='file', is_trashed=0, deleted_at__isnull=True) | 299 | file = File.objects.filter(id=file_id, type='file', is_trashed=0, deleted_at__isnull=True) | ... | ... |
... | @@ -7,18 +7,19 @@ from ..models import File, Group, GroupUser, User | ... | @@ -7,18 +7,19 @@ from ..models import File, Group, GroupUser, User |
7 | 7 | ||
8 | # 그룹 생성 | 8 | # 그룹 생성 |
9 | def create(request): | 9 | def create(request): |
10 | - # TODO: Auth | 10 | + # Check Login |
11 | - request.user_id = 1 | 11 | + if request.user_id is None: |
12 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
12 | 13 | ||
13 | # Load | 14 | # Load |
14 | try: | 15 | try: |
15 | received = json.loads(request.body.decode('utf-8')) | 16 | received = json.loads(request.body.decode('utf-8')) |
16 | except json.decoder.JSONDecodeError: | 17 | except json.decoder.JSONDecodeError: |
17 | - return {'result': False, 'error': '입력이 잘못되었습니다.'} | 18 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
18 | 19 | ||
19 | # Validate | 20 | # Validate |
20 | if 'name' not in received or received['name'] == '': | 21 | if 'name' not in received or received['name'] == '': |
21 | - return {'result': False, 'error': '입력이 누락되었습니다.'} | 22 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
22 | 23 | ||
23 | # Create | 24 | # Create |
24 | root_folder = uuid.uuid4() | 25 | root_folder = uuid.uuid4() |
... | @@ -44,24 +45,24 @@ def create(request): | ... | @@ -44,24 +45,24 @@ def create(request): |
44 | created_at=timezone.now() | 45 | created_at=timezone.now() |
45 | ) | 46 | ) |
46 | 47 | ||
47 | - return {'result': True, 'group_id': group.id} | 48 | + return {'result': True} |
48 | 49 | ||
49 | 50 | ||
50 | # 그룹 초대장 조회 | 51 | # 그룹 초대장 조회 |
51 | def find_invite(request, invite_code): | 52 | def find_invite(request, invite_code): |
52 | - # TODO: Auth | 53 | + # Check Login |
53 | - request.user_id = 1 | 54 | + if request.user_id is None: |
55 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
54 | 56 | ||
55 | # Query | 57 | # Query |
56 | group = Group.objects.filter(invite_code=invite_code) | 58 | group = Group.objects.filter(invite_code=invite_code) |
57 | 59 | ||
58 | # Check Exists | 60 | # Check Exists |
59 | if len(group) == 0: | 61 | if len(group) == 0: |
60 | - return {'result': False, 'error': '존재하지 않는 초대장입니다.'} | 62 | + return {'result': False, 'error': '잘못된 초대코드입니다.'} |
61 | 63 | ||
62 | - # Structure | 64 | + # Serialize |
63 | data = { | 65 | data = { |
64 | - 'id': group[0].id, | ||
65 | 'name': group[0].name | 66 | 'name': group[0].name |
66 | } | 67 | } |
67 | 68 | ||
... | @@ -77,15 +78,16 @@ def find_invite(request, invite_code): | ... | @@ -77,15 +78,16 @@ def find_invite(request, invite_code): |
77 | 78 | ||
78 | # 그룹 초대장 사용 | 79 | # 그룹 초대장 사용 |
79 | def use_invite(request, invite_code): | 80 | def use_invite(request, invite_code): |
80 | - # TODO: Auth | 81 | + # Check Login |
81 | - request.user_id = 1 | 82 | + if request.user_id is None: |
83 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
82 | 84 | ||
83 | # Query | 85 | # Query |
84 | group = Group.objects.filter(invite_code=invite_code) | 86 | group = Group.objects.filter(invite_code=invite_code) |
85 | 87 | ||
86 | # Check Exists | 88 | # Check Exists |
87 | if len(group) == 0: | 89 | if len(group) == 0: |
88 | - return {'result': False, 'error': '존재하지 않는 초대장입니다.'} | 90 | + return {'result': False, 'error': '잘못된 초대코드입니다.'} |
89 | 91 | ||
90 | # Check Joined | 92 | # Check Joined |
91 | joined = GroupUser.objects.filter(group_id=group[0].id, user_id=request.user_id) | 93 | joined = GroupUser.objects.filter(group_id=group[0].id, user_id=request.user_id) |
... | @@ -104,18 +106,18 @@ def use_invite(request, invite_code): | ... | @@ -104,18 +106,18 @@ def use_invite(request, invite_code): |
104 | 106 | ||
105 | # 그룹 목록 | 107 | # 그룹 목록 |
106 | def list_me(request): | 108 | def list_me(request): |
107 | - # TODO: Auth | 109 | + # Check Login |
108 | - request.user_id = 1 | 110 | + if request.user_id is None: |
111 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
109 | 112 | ||
110 | # Query | 113 | # Query |
111 | joined = GroupUser.objects.filter(user_id=request.user_id).values_list('group_id', flat=True) | 114 | joined = GroupUser.objects.filter(user_id=request.user_id).values_list('group_id', flat=True) |
112 | groups = Group.objects.filter(id__in=joined) | 115 | groups = Group.objects.filter(id__in=joined) |
113 | 116 | ||
114 | - # Structure | 117 | + # Serialize |
115 | data = [] | 118 | data = [] |
116 | for group in groups: | 119 | for group in groups: |
117 | data.append({ | 120 | data.append({ |
118 | - 'id': group.id, | ||
119 | 'name': group.name, | 121 | 'name': group.name, |
120 | 'root_folder': group.root_folder, | 122 | 'root_folder': group.root_folder, |
121 | }) | 123 | }) |
... | @@ -125,24 +127,24 @@ def list_me(request): | ... | @@ -125,24 +127,24 @@ def list_me(request): |
125 | 127 | ||
126 | # 그룹 조회 | 128 | # 그룹 조회 |
127 | def find_item(request, group_id): | 129 | def find_item(request, group_id): |
128 | - # TODO: Auth | 130 | + # Check Login |
129 | - request.user_id = 1 | 131 | + if request.user_id is None: |
132 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
130 | 133 | ||
131 | # Check Joined | 134 | # Check Joined |
132 | joined = GroupUser.objects.filter(group_id=group_id, user_id=request.user_id) | 135 | joined = GroupUser.objects.filter(group_id=group_id, user_id=request.user_id) |
133 | if len(joined) == 0: | 136 | if len(joined) == 0: |
134 | - return {'result': False, 'error': '입력이 잘못되었습니다.'} | 137 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
135 | 138 | ||
136 | # Query | 139 | # Query |
137 | group = Group.objects.filter(id=group_id) | 140 | group = Group.objects.filter(id=group_id) |
138 | 141 | ||
139 | # Check Exists | 142 | # Check Exists |
140 | if len(group) == 0: | 143 | if len(group) == 0: |
141 | - return {'result': False, 'error': '존재하지 않는 그룹입니다.'} | 144 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
142 | 145 | ||
143 | - # Structure | 146 | + # Serialize |
144 | data = { | 147 | data = { |
145 | - 'id': group[0].id, | ||
146 | 'name': group[0].name, | 148 | 'name': group[0].name, |
147 | 'root_folder': group[0].root_folder, | 149 | 'root_folder': group[0].root_folder, |
148 | } | 150 | } |
... | @@ -157,9 +159,9 @@ def find_item(request, group_id): | ... | @@ -157,9 +159,9 @@ def find_item(request, group_id): |
157 | 'id': user.id, | 159 | 'id': user.id, |
158 | 'name': user.name, | 160 | 'name': user.name, |
159 | }) | 161 | }) |
160 | - data['user'] = user_data | 162 | + data['id'] = group[0].id |
163 | + data['users'] = user_data | ||
161 | data['invite_code'] = group[0].invite_code | 164 | data['invite_code'] = group[0].invite_code |
162 | - data['created_at'] = group[0].created_at | ||
163 | data['is_owner'] = True | 165 | data['is_owner'] = True |
164 | 166 | ||
165 | return {'result': True, 'data': data} | 167 | return {'result': True, 'data': data} |
... | @@ -167,29 +169,30 @@ def find_item(request, group_id): | ... | @@ -167,29 +169,30 @@ def find_item(request, group_id): |
167 | 169 | ||
168 | # 그룹 수정 | 170 | # 그룹 수정 |
169 | def update_item(request, group_id): | 171 | def update_item(request, group_id): |
170 | - # TODO: Auth | 172 | + # Check Login |
171 | - request.user_id = 1 | 173 | + if request.user_id is None: |
174 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
172 | 175 | ||
173 | # Load | 176 | # Load |
174 | try: | 177 | try: |
175 | received = json.loads(request.body.decode('utf-8')) | 178 | received = json.loads(request.body.decode('utf-8')) |
176 | except json.decoder.JSONDecodeError: | 179 | except json.decoder.JSONDecodeError: |
177 | - return {'result': False, 'error': '입력이 잘못되었습니다.'} | 180 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
178 | 181 | ||
179 | # Validate | 182 | # Validate |
180 | if 'name' not in received or received['name'] == '': | 183 | if 'name' not in received or received['name'] == '': |
181 | - return {'result': False, 'error': '입력이 누락되었습니다.'} | 184 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
182 | 185 | ||
183 | # Query | 186 | # Query |
184 | group = Group.objects.filter(id=group_id) | 187 | group = Group.objects.filter(id=group_id) |
185 | 188 | ||
186 | # Check Exists | 189 | # Check Exists |
187 | if len(group) == 0: | 190 | if len(group) == 0: |
188 | - return {'result': False, 'error': '존재하지 않는 그룹입니다.'} | 191 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
189 | 192 | ||
190 | # Check Owner | 193 | # Check Owner |
191 | if group[0].owner_id != request.user_id: | 194 | if group[0].owner_id != request.user_id: |
192 | - return {'result': False, 'error': '권한이 없습니다.'} | 195 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
193 | 196 | ||
194 | # Update | 197 | # Update |
195 | group[0].name = received['name'] | 198 | group[0].name = received['name'] |
... | @@ -200,19 +203,20 @@ def update_item(request, group_id): | ... | @@ -200,19 +203,20 @@ def update_item(request, group_id): |
200 | 203 | ||
201 | # 그룹 삭제 | 204 | # 그룹 삭제 |
202 | def delete_item(request, group_id): | 205 | def delete_item(request, group_id): |
203 | - # TODO: Auth | 206 | + # Check Login |
204 | - request.user_id = 1 | 207 | + if request.user_id is None: |
208 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
205 | 209 | ||
206 | # Query | 210 | # Query |
207 | group = Group.objects.filter(id=group_id) | 211 | group = Group.objects.filter(id=group_id) |
208 | 212 | ||
209 | # Check Exists | 213 | # Check Exists |
210 | if len(group) == 0: | 214 | if len(group) == 0: |
211 | - return {'result': False, 'error': '존재하지 않는 그룹입니다.'} | 215 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
212 | 216 | ||
213 | # Check Owner | 217 | # Check Owner |
214 | if group[0].owner_id != request.user_id: | 218 | if group[0].owner_id != request.user_id: |
215 | - return {'result': False, 'error': '권한이 없습니다.'} | 219 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
216 | 220 | ||
217 | # S3 Delete | 221 | # S3 Delete |
218 | del_list = File.objects.filter(owner_group_id=group_id).values_list('id', flat=True) | 222 | del_list = File.objects.filter(owner_group_id=group_id).values_list('id', flat=True) |
... | @@ -228,15 +232,16 @@ def delete_item(request, group_id): | ... | @@ -228,15 +232,16 @@ def delete_item(request, group_id): |
228 | 232 | ||
229 | # 그룹 사용자 삭제 | 233 | # 그룹 사용자 삭제 |
230 | def remove_user(request, group_id, user_id): | 234 | def remove_user(request, group_id, user_id): |
231 | - # TODO: Auth | 235 | + # Check Login |
232 | - request.user_id = 1 | 236 | + if request.user_id is None: |
237 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
233 | 238 | ||
234 | # Query | 239 | # Query |
235 | group = Group.objects.filter(id=group_id) | 240 | group = Group.objects.filter(id=group_id) |
236 | 241 | ||
237 | # Check Owner | 242 | # Check Owner |
238 | if group[0].owner_id != request.user_id: | 243 | if group[0].owner_id != request.user_id: |
239 | - return {'result': False, 'error': '권한이 없습니다.'} | 244 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
240 | 245 | ||
241 | # Check Me | 246 | # Check Me |
242 | if int(user_id) == request.user_id: | 247 | if int(user_id) == request.user_id: | ... | ... |
... | @@ -16,32 +16,34 @@ def create(request): | ... | @@ -16,32 +16,34 @@ def create(request): |
16 | try: | 16 | try: |
17 | received = json.loads(request.body.decode('utf-8')) | 17 | received = json.loads(request.body.decode('utf-8')) |
18 | except json.decoder.JSONDecodeError: | 18 | except json.decoder.JSONDecodeError: |
19 | - return {'result': False, 'error': '입력이 잘못되었습니다.'} | 19 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
20 | 20 | ||
21 | # Validate | 21 | # Validate |
22 | if 'email' not in received \ | 22 | if 'email' not in received \ |
23 | or 'password' not in received \ | 23 | or 'password' not in received \ |
24 | or 'name' not in received: | 24 | or 'name' not in received: |
25 | - return {'result': False, 'error': '입력이 누락되었습니다.'} | 25 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
26 | 26 | ||
27 | # Validate Email | 27 | # Validate Email |
28 | try: | 28 | try: |
29 | validate_email(received['email']) | 29 | validate_email(received['email']) |
30 | except ValidationError: | 30 | except ValidationError: |
31 | - return {'result': False, 'error': '이메일 형식이 잘못되었습니다.'} | 31 | + return {'result': False, 'error': '이메일을 제대로 입력해주세요.'} |
32 | 32 | ||
33 | # Validate Password | 33 | # Validate Password |
34 | if len(received['password']) < 8: | 34 | if len(received['password']) < 8: |
35 | - return {'result': False, 'error': '비밀번호는 최소 8글자 입니다.'} | 35 | + return {'result': False, 'error': '비밀번호를 8자리 이상으로 입력해주세요.'} |
36 | 36 | ||
37 | # Validate Name | 37 | # Validate Name |
38 | if len(received['name']) > 50: | 38 | if len(received['name']) > 50: |
39 | return {'result': False, 'error': '이름은 최대 50글자 입니다.'} | 39 | return {'result': False, 'error': '이름은 최대 50글자 입니다.'} |
40 | + elif len(received['name']) == 0: | ||
41 | + return {'result': False, 'error': '이름을 제대로 입력해주세요.'} | ||
40 | 42 | ||
41 | # Check Duplicates | 43 | # Check Duplicates |
42 | is_exists = User.objects.filter(email=received['email']) | 44 | is_exists = User.objects.filter(email=received['email']) |
43 | if len(is_exists) > 0: | 45 | if len(is_exists) > 0: |
44 | - return {'result': False, 'error': '이미 사용중인 이메일 주소 입니다.'} | 46 | + return {'result': False, 'error': '이미 사용 중인 이메일입니다.'} |
45 | 47 | ||
46 | # Insert | 48 | # Insert |
47 | root_folder = uuid.uuid4() | 49 | root_folder = uuid.uuid4() |
... | @@ -70,21 +72,21 @@ def login(request): | ... | @@ -70,21 +72,21 @@ def login(request): |
70 | try: | 72 | try: |
71 | received = json.loads(request.body.decode('utf-8')) | 73 | received = json.loads(request.body.decode('utf-8')) |
72 | except json.decoder.JSONDecodeError: | 74 | except json.decoder.JSONDecodeError: |
73 | - return {'result': False, 'error': '입력이 잘못되었습니다.'} | 75 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
74 | 76 | ||
75 | # Validate | 77 | # Validate |
76 | if 'email' not in received \ | 78 | if 'email' not in received \ |
77 | or 'password' not in received: | 79 | or 'password' not in received: |
78 | - return {'result': False, 'error': '입력이 누락되었습니다.'} | 80 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
79 | 81 | ||
80 | - # Select | 82 | + # Query |
81 | user = User.objects.filter(email=received['email']) | 83 | user = User.objects.filter(email=received['email']) |
82 | 84 | ||
83 | - # Not Exists | 85 | + # Check Exists |
84 | if len(user) != 1: | 86 | if len(user) != 1: |
85 | return {'result': False, 'error': '로그인에 실패하였습니다.'} | 87 | return {'result': False, 'error': '로그인에 실패하였습니다.'} |
86 | 88 | ||
87 | - # Check | 89 | + # Check Password |
88 | if check_password(received['password'], user[0].password) is False: | 90 | if check_password(received['password'], user[0].password) is False: |
89 | return {'result': False, 'error': '로그인에 실패하였습니다.'} | 91 | return {'result': False, 'error': '로그인에 실패하였습니다.'} |
90 | 92 | ||
... | @@ -97,8 +99,9 @@ def login(request): | ... | @@ -97,8 +99,9 @@ def login(request): |
97 | 99 | ||
98 | # 회원정보 조회 | 100 | # 회원정보 조회 |
99 | def find_me(request): | 101 | def find_me(request): |
100 | - # TODO: Auth | 102 | + # Check Login |
101 | - request.user_id = 1 | 103 | + if request.user_id is None: |
104 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
102 | 105 | ||
103 | # Query | 106 | # Query |
104 | user = User.objects.filter(id=request.user_id) | 107 | user = User.objects.filter(id=request.user_id) |
... | @@ -121,19 +124,20 @@ def find_me(request): | ... | @@ -121,19 +124,20 @@ def find_me(request): |
121 | 124 | ||
122 | # 회원정보 수정 | 125 | # 회원정보 수정 |
123 | def update_me(request): | 126 | def update_me(request): |
124 | - # TODO: Auth | 127 | + # Check Login |
125 | - request.user_id = 1 | 128 | + if request.user_id is None: |
129 | + return {'result': False, 'error': '로그인을 해주세요.'} | ||
126 | 130 | ||
127 | # Load | 131 | # Load |
128 | try: | 132 | try: |
129 | received = json.loads(request.body.decode('utf-8')) | 133 | received = json.loads(request.body.decode('utf-8')) |
130 | except json.decoder.JSONDecodeError: | 134 | except json.decoder.JSONDecodeError: |
131 | - return {'result': False, 'error': '입력이 잘못되었습니다.'} | 135 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
132 | 136 | ||
133 | # Validate | 137 | # Validate |
134 | if 'name' not in received \ | 138 | if 'name' not in received \ |
135 | and ('old_password' not in received and 'password' not in received): | 139 | and ('old_password' not in received and 'password' not in received): |
136 | - return {'result': False, 'error': '입력이 누락되었습니다.'} | 140 | + return {'result': False, 'error': '잘못된 요청입니다.'} |
137 | 141 | ||
138 | # Query | 142 | # Query |
139 | user = User.objects.filter(id=request.user_id) | 143 | user = User.objects.filter(id=request.user_id) |
... | @@ -144,14 +148,16 @@ def update_me(request): | ... | @@ -144,14 +148,16 @@ def update_me(request): |
144 | 148 | ||
145 | # Change Name | 149 | # Change Name |
146 | if 'name' in received: | 150 | if 'name' in received: |
151 | + if len(received['name']) == 0: | ||
152 | + return {'result': False, 'error': '이름을 제대로 입력해주세요.'} | ||
147 | user[0].name = received['name'] | 153 | user[0].name = received['name'] |
148 | 154 | ||
149 | # Change Password | 155 | # Change Password |
150 | if 'old_password' in received and 'password' in received: | 156 | if 'old_password' in received and 'password' in received: |
151 | if check_password(received['old_password'], user[0].password) is False: | 157 | if check_password(received['old_password'], user[0].password) is False: |
152 | - return {'result': False, 'error': '이전 비밀번호가 잘못되었습니다.'} | 158 | + return {'result': False, 'error': '이전 비밀번호를 제대로 입력해주세요.'} |
153 | if len(received['password']) < 8: | 159 | if len(received['password']) < 8: |
154 | - return {'result': False, 'error': '비밀번호는 최소 8글자 입니다.'} | 160 | + return {'result': False, 'error': '비밀번호를 8자리 이상으로 입력해주세요.'} |
155 | user[0].password = make_password(received['password']) | 161 | user[0].password = make_password(received['password']) |
156 | 162 | ||
157 | # Save | 163 | # Save | ... | ... |
... | @@ -17,6 +17,7 @@ idna==2.9 | ... | @@ -17,6 +17,7 @@ idna==2.9 |
17 | importlib-metadata==1.6.0 | 17 | importlib-metadata==1.6.0 |
18 | jmespath==0.10.0 | 18 | jmespath==0.10.0 |
19 | -e git+http://khuhub.khu.ac.kr/2016104129/kappa.git@1b0e17bb6da7460d9d494828c682a5ef66736aa3#egg=kappa | 19 | -e git+http://khuhub.khu.ac.kr/2016104129/kappa.git@1b0e17bb6da7460d9d494828c682a5ef66736aa3#egg=kappa |
20 | +pathvalidate==2.3.0 | ||
20 | pip-tools==5.1.2 | 21 | pip-tools==5.1.2 |
21 | placebo==0.9.0 | 22 | placebo==0.9.0 |
22 | pycparser==2.20 | 23 | pycparser==2.20 | ... | ... |
... | @@ -10,6 +10,17 @@ | ... | @@ -10,6 +10,17 @@ |
10 | "vpc_config": { | 10 | "vpc_config": { |
11 | "SubnetIds": ["subnet-02d51e69"], | 11 | "SubnetIds": ["subnet-02d51e69"], |
12 | "SecurityGroupIds": ["sg-09c30d37d6a504f5c"] | 12 | "SecurityGroupIds": ["sg-09c30d37d6a504f5c"] |
13 | - } | 13 | + }, |
14 | + "events": [ | ||
15 | + { | ||
16 | + "function": "khubox.lambda.process_upload", | ||
17 | + "event_source": { | ||
18 | + "arn": "arn:aws:s3:::khubox-files", | ||
19 | + "events": [ | ||
20 | + "s3:ObjectCreated:Put" | ||
21 | + ] | ||
22 | + } | ||
23 | + } | ||
24 | + ] | ||
14 | } | 25 | } |
15 | } | 26 | } | ... | ... |
-
Please register or login to post a comment