add saving favorite locations
[qcg-portal.git] / filex / views.py
index 57932d7..5d23947 100644 (file)
@@ -1,13 +1,16 @@
-from datetime import datetime
 import mimetypes
 
+from django.contrib.auth.decorators import login_required
 from django.core.exceptions import PermissionDenied, SuspiciousOperation
 from django.http import JsonResponse, StreamingHttpResponse
+from django.shortcuts import get_object_or_404
 from django.template.defaultfilters import filesizeformat
 from django.utils.formats import date_format
-from django.utils.timezone import UTC, localtime
+from django.views.decorators.http import require_POST
 
+from filex.forms import NewDirForm, RenameForm, FavoriteForm
 from filex.ftp import FTPOperation, FTPException
+from filex.models import Favorite
 from filex.uploadhandler import with_ftp_upload_handler
 
 
@@ -35,23 +38,11 @@ def list_content(request):
         return JsonResponse({'msg': e.message}, status=400)
 
     data = []
+    for item in listing:
+        item['size'] = filesizeformat(item['size'])
+        item['date'] = date_format(item['date'], 'CUSTOM_DATETIME_FORMAT')
 
-    # ignore first two: '.' and '..'
-    for item in listing.strip().splitlines()[2:]:
-        # we may receive empty string when there are multiple consecutive newlines in listing
-        if item:
-            attrs, name = item.split(' ', 1)
-
-            attrs = dict((attr.split('=') for attr in attrs.split(';') if attr))
-
-            date = localtime(datetime.strptime(attrs['Modify'], "%Y%m%d%H%M%S").replace(tzinfo=UTC()))
-
-            data.append({
-                'name': name,
-                'type': 'file' if attrs['Type'] == 'file' else 'directory',
-                'size': filesizeformat(attrs['Size']),
-                'date': date_format(date, 'DATETIME_FORMAT'),
-            })
+        data.append(item)
 
     return JsonResponse(data, safe=False)
 
@@ -85,3 +76,188 @@ def download(request):
 def upload(request):
     # TODO error handling
     return JsonResponse({'success': True})
+
+
+def info(request):
+    check_auth(request)
+
+    # TODO data validation
+    host = request.GET.get('host')
+    path = request.GET.get('path')
+    if not host or not path:
+        raise SuspiciousOperation("No path or host given!")
+
+    url = 'gsiftp://' + host + path
+
+    try:
+        return JsonResponse(FTPOperation(request.session['proxy']).info(url))
+    except FTPException as e:
+        status = 400
+        if 'No such file or directory' in e.message:
+            status = 404
+        elif 'Permission denied' in e.message:
+            status = 403
+
+        return JsonResponse({'msg': e.message}, status=status)
+
+
+@require_POST
+def delete(request):
+    check_auth(request)
+
+    # TODO data validation
+    host = request.POST.get('host')
+    path = request.POST.get('path')
+    dirs = request.POST.getlist('dirs')
+    files = request.POST.getlist('files')
+    if not host or not path or not (files or dirs):
+        raise SuspiciousOperation("No path or host or files given!")
+
+    url = 'gsiftp://' + host + path + '/'
+    ftp = FTPOperation(request.session['proxy'])
+
+    done, fail = [], {}
+
+    for name in dirs:
+        try:
+            ftp.rmdir(url + name)
+        except FTPException as e:
+            fail[name] = e.message
+        else:
+            done.append(name)
+
+    for name in files:
+        try:
+            ftp.delete(url + name)
+        except FTPException as e:
+            fail[name] = e.message
+        else:
+            done.append(name)
+
+    return JsonResponse({'done': done, 'fail': fail})
+
+
+@require_POST
+def mkdir(request):
+    check_auth(request)
+
+    # TODO actual data validation
+    form = NewDirForm(request.POST)
+
+    if form.is_valid():
+        host = form.cleaned_data['host']
+        path = form.cleaned_data['path']
+        name = form.cleaned_data['name']
+
+        url = 'gsiftp://' + host + path + '/' + name
+
+        try:
+            FTPOperation(request.session['proxy']).mkdir(url)
+        except FTPException as e:
+            msg = e.message
+        else:
+            return JsonResponse({'success': True})
+    else:
+        msg = form.errors
+
+    return JsonResponse({'msg': msg}, status=400)
+
+
+@require_POST
+def move(request):
+    check_auth(request)
+
+    # TODO actual data validation
+    form = RenameForm(request.POST)
+
+    if form.is_valid():
+        host = form.cleaned_data['host']
+        path = form.cleaned_data['path']
+        src = form.cleaned_data['src']
+        dst = form.cleaned_data['dst']
+
+        src_url = 'gsiftp://' + host + path + '/' + src
+        dst_url = 'gsiftp://' + host + path + '/' + dst
+
+        try:
+            FTPOperation(request.session['proxy']).move(src_url, dst_url)
+        except FTPException as e:
+            msg = e.message
+        else:
+            return JsonResponse({'success': True})
+    else:
+        msg = form.errors
+
+    return JsonResponse({'msg': msg}, status=400)
+
+
+@require_POST
+def compress(request):
+    check_auth(request)
+
+    # TODO data validation
+    host = request.POST.get('host')
+    path = request.POST.get('path')
+    files = request.POST.getlist('files')
+    archive = request.POST.get('archive')
+    if not host or not path or not files or not archive:
+        raise SuspiciousOperation("No path or host or files or archive given!")
+
+    server = 'gsiftp://' + host
+
+    try:
+        # consume generator with command output
+        list(FTPOperation(request.session['proxy']).compress(server, path, files, archive))
+    except FTPException as e:
+        return JsonResponse({'msg': e.message}, status=400)
+    else:
+        return JsonResponse({'success': True})
+
+
+@require_POST
+def extract(request):
+    check_auth(request)
+
+    # TODO data validation
+    host = request.POST.get('host')
+    archive = request.POST.get('archive')
+    dst = request.POST.get('dst')
+    if not host or not archive or not dst:
+        raise SuspiciousOperation("No path or host or files or archive given!")
+
+    server = 'gsiftp://' + host
+
+    try:
+        # consume generator with command output
+        list(FTPOperation(request.session['proxy']).extract(server, archive, dst))
+    except FTPException as e:
+        return JsonResponse({'msg': e.message}, status=400)
+    else:
+        return JsonResponse({'success': True})
+
+
+@require_POST
+@login_required
+def fav_add(request):
+    data = request.POST.copy()
+    data['owner'] = request.user.id
+
+    form = FavoriteForm(data)
+
+    # TODO check if path exists
+    if form.is_valid():
+        instance = form.save()
+
+        return JsonResponse({'group': 'usr', 'host': instance.host, 'path': instance.path,
+                             'value': instance.host + instance.path})
+
+    return JsonResponse({'msg': form.errors}, status=400)
+
+
+@require_POST
+@login_required
+def fav_delete(request):
+    fav = get_object_or_404(Favorite, owner=request.user, host=request.POST['host'], path=request.POST['path'])
+    fav.delete()
+
+    return JsonResponse({'success': True})