diff --git a/requirements.txt b/requirements.txt index db1ff19a81..bcaaddbcb8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,4 @@ django-statici18n==1.1.2 djangorestframework==3.3.1 git+git://github.com/haiwen/django-constance.git@bde7f7cdfd0ed1631a6817fd4cd76f37bf54fe35#egg=django-constance[database] openpyxl==2.3.0 +pytz==2015.7 diff --git a/seahub/api2/endpoints/group_discussions.py b/seahub/api2/endpoints/group_discussions.py index 81c5960b9f..914b4a6edd 100644 --- a/seahub/api2/endpoints/group_discussions.py +++ b/seahub/api2/endpoints/group_discussions.py @@ -2,7 +2,6 @@ import json from django.core.paginator import EmptyPage, InvalidPage from django.http import HttpResponse -from django.utils.dateformat import DateFormat from rest_framework import status from rest_framework.authentication import SessionAuthentication @@ -16,6 +15,7 @@ from seahub.api2.throttling import UserRateThrottle from seahub.api2.utils import api_error from seahub.group.models import GroupMessage from seahub.utils.paginator import Paginator +from seahub.utils.timeutils import datetime_to_isoformat_timestr from .utils import api_check_group json_content_type = 'application/json; charset=utf-8' @@ -55,12 +55,13 @@ class GroupDiscussions(APIView): msgs = [] for e in group_msgs: + isoformat_timestr = datetime_to_isoformat_timestr(e.timestamp) msgs.append({ "group_id": group_id, "discussion_id": e.pk, "user": e.from_email, "content": e.message, - "created_at": e.timestamp.strftime("%Y-%m-%dT%H:%M:%S") + DateFormat(e.timestamp).format('O'), + "created_at": isoformat_timestr, }) return HttpResponse(json.dumps(msgs), status=200, @@ -79,10 +80,11 @@ class GroupDiscussions(APIView): from_email=username, message=content) + isoformat_timestr = datetime_to_isoformat_timestr(discuss.timestamp) return Response({ "group_id": group_id, "discussion_id": discuss.pk, "user": username, "content": discuss.message, - "created_at": discuss.timestamp.strftime("%Y-%m-%dT%H:%M:%S") + DateFormat(discuss.timestamp).format('O'), + "created_at": isoformat_timestr, }, status=201) diff --git a/seahub/api2/endpoints/groups.py b/seahub/api2/endpoints/groups.py index fd29a9ab7d..8490dd904b 100644 --- a/seahub/api2/endpoints/groups.py +++ b/seahub/api2/endpoints/groups.py @@ -1,6 +1,5 @@ import logging -from django.utils.dateformat import DateFormat from django.utils.translation import ugettext as _ from django.template.defaultfilters import filesizeformat @@ -21,7 +20,7 @@ from seahub.avatar.settings import GROUP_AVATAR_DEFAULT_SIZE from seahub.avatar.templatetags.group_avatar_tags import api_grp_avatar_url, \ get_default_group_avatar_url from seahub.utils import is_org_context, is_valid_username -from seahub.utils.timeutils import dt, utc_to_local +from seahub.utils.timeutils import timestamp_to_isoformat_timestr from seahub.group.utils import validate_group_name, check_group_name_conflict, \ is_group_member, is_group_admin, is_group_owner, is_group_admin_or_owner from seahub.group.views import remove_group_common @@ -52,12 +51,12 @@ def get_group_info(request, group_id, avatar_size=GROUP_AVATAR_DEFAULT_SIZE): logger.error(e) avatar_url = get_default_group_avatar_url() - val = utc_to_local(dt(group.timestamp)) + isoformat_timestr = timestamp_to_isoformat_timestr(group.timestamp) group_info = { "id": group.id, "name": group.group_name, "owner": group.creator_name, - "created_at": val.strftime("%Y-%m-%dT%H:%M:%S") + DateFormat(val).format('O'), + "created_at": isoformat_timestr, "avatar_url": request.build_absolute_uri(avatar_url), "admins": get_group_admins(group.id), "wiki_enabled": is_wiki_mod_enabled_for_group(group_id) diff --git a/seahub/api2/endpoints/shared_upload_links.py b/seahub/api2/endpoints/shared_upload_links.py index 551265db75..4c55c949e8 100644 --- a/seahub/api2/endpoints/shared_upload_links.py +++ b/seahub/api2/endpoints/shared_upload_links.py @@ -2,7 +2,6 @@ import json import os from django.http import HttpResponse -from django.utils.dateformat import DateFormat from rest_framework.authentication import SessionAuthentication from rest_framework.permissions import IsAuthenticated from rest_framework.views import APIView @@ -13,6 +12,7 @@ from seahub.api2.authentication import TokenAuthentication from seahub.api2.throttling import UserRateThrottle from seahub.share.models import UploadLinkShare from seahub.utils import gen_shared_upload_link +from seahub.utils.timeutils import datetime_to_isoformat_timestr json_content_type = 'application/json; charset=utf-8' @@ -45,7 +45,7 @@ class SharedUploadLinksView(APIView): link.repo = r if link.expire_date: - expire_date = link.expire_date.strftime("%Y-%m-%dT%H:%M:%S") + DateFormat(link.expire_date).format('O') + expire_date = datetime_to_isoformat_timestr(link.expire_date) else: expire_date = "" @@ -54,7 +54,7 @@ class SharedUploadLinksView(APIView): "repo_id": link.repo_id, "path": link.path, "token": link.token, - "ctime": link.ctime.strftime("%Y-%m-%dT%H:%M:%S") + DateFormat(link.ctime).format('O'), + "ctime": datetime_to_isoformat_timestr(link.ctime), "view_cnt": link.view_cnt, "expire_date": expire_date, }) diff --git a/seahub/api2/urls.py b/seahub/api2/urls.py index a13264d073..538a47f5a7 100644 --- a/seahub/api2/urls.py +++ b/seahub/api2/urls.py @@ -61,6 +61,7 @@ urlpatterns = patterns('', url(r'^repos/(?P[-0-9-a-f]{36})/dir/download/$', DirDownloadView.as_view(), name='api2-dir-download'), url(r'^repos/(?P[-0-9-a-f]{36})/thumbnail/$', ThumbnailView.as_view(), name='api2-thumbnail'), url(r'^starredfiles/', StarredFileView.as_view(), name='starredfiles'), + url(r'^devices/', DevicesView.as_view(), name='api2-devices'), url(r'^shared-repos/$', SharedRepos.as_view(), name='sharedrepos'), url(r'^shared-repos/(?P[-0-9-a-f]{36})/$', SharedRepo.as_view(), name='sharedrepo'), url(r'^beshared-repos/$', BeShared.as_view(), name='beshared'), diff --git a/seahub/api2/views.py b/seahub/api2/views.py index 3c0cb0c9f6..76b239d94b 100644 --- a/seahub/api2/views.py +++ b/seahub/api2/views.py @@ -29,7 +29,6 @@ from django.template.defaultfilters import filesizeformat from django.shortcuts import render_to_response from django.utils import timezone from django.utils.translation import ugettext as _ -from django.utils.dateformat import DateFormat from .throttling import ScopedRateThrottle, AnonRateThrottle, UserRateThrottle from .authentication import TokenAuthentication @@ -75,11 +74,12 @@ from seahub.utils import gen_file_get_url, gen_token, gen_file_upload_url, \ gen_file_share_link, gen_dir_share_link, is_org_context, gen_shared_link, \ get_org_user_events, calculate_repos_last_modify, send_perm_audit_msg, \ gen_shared_upload_link, convert_cmmt_desc_link, is_org_repo_creation_allowed +from seahub.utils.devices import get_user_devices, do_unlink_device from seahub.utils.repo import get_sub_repo_abbrev_origin_path from seahub.utils.star import star_file, unstar_file from seahub.utils.file_types import IMAGE, DOCUMENT from seahub.utils.file_size import get_file_size_unit -from seahub.utils.timeutils import utc_to_local +from seahub.utils.timeutils import utc_to_local, datetime_to_isoformat_timestr from seahub.views import validate_owner, is_registered_user, check_file_lock, \ group_events_data, get_diff, create_default_library, get_owned_repo_list, \ list_inner_pub_repos, get_virtual_repos_by_owner, \ @@ -1861,6 +1861,38 @@ class OwaFileView(APIView): send_file_access_msg(request, repo, path, 'api') return Response(wopi_dict) +class DevicesView(APIView): + """List user devices""" + authentication_classes = (TokenAuthentication, SessionAuthentication) + permission_classes = (IsAuthenticated,) + throttle_classes = (UserRateThrottle, ) + + def get(self, request, format=None): + username = request.user.username + user_devices = get_user_devices(username) + return Response(user_devices) + + def delete(self, request, format=None): + + platform = request.data.get('platform', '') + device_id = request.data.get('device_id', '') + + if not platform: + error_msg = 'platform invalid.' + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + if not device_id: + error_msg = 'device_id invalid.' + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + try: + do_unlink_device(request.user.username, platform, device_id) + except SearpcError as e: + logger.error(e) + error_msg = 'Internal Server Error' + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + + return Response({'success': True}) class FileView(APIView): """ @@ -4327,8 +4359,7 @@ class RepoDownloadSharedLinks(APIView): shared_link['create_by'] = fs.username shared_link['creator_name'] = email2nickname(fs.username) - # return time with time zone: 2016-01-18T15:03:10+0800 - shared_link['create_time'] = fs.ctime.strftime("%Y-%m-%dT%H:%M:%S") + DateFormat(fs.ctime).format('O') + shared_link['create_time'] = datetime_to_isoformat_timestr(fs.ctime) shared_link['token'] = fs.token shared_link['path'] = path shared_link['name'] = os.path.basename(path.rstrip('/')) if path != '/' else '/' @@ -4412,8 +4443,7 @@ class RepoUploadSharedLinks(APIView): shared_link['create_by'] = fs.username shared_link['creator_name'] = email2nickname(fs.username) - # return time with time zone: 2016-01-18T15:03:10+0800 - shared_link['create_time'] = fs.ctime.strftime("%Y-%m-%dT%H:%M:%S") + DateFormat(fs.ctime).format('O') + shared_link['create_time'] = datetime_to_isoformat_timestr(fs.ctime) shared_link['token'] = fs.token shared_link['path'] = path shared_link['name'] = os.path.basename(path.rstrip('/')) if path != '/' else '/' diff --git a/seahub/templates/devices.html b/seahub/templates/devices.html deleted file mode 100644 index d99bd157f7..0000000000 --- a/seahub/templates/devices.html +++ /dev/null @@ -1,120 +0,0 @@ -{% extends "home_base.html" %} - -{% load seahub_tags avatar_tags i18n %} - -{% block sub_title %}{% trans "Devices" %} - {% endblock %} -{% block cur_devices %}tab-cur{% endblock %} - -{% block right_panel %} -

{% trans "Devices" %}

-{% if devices %} - - - - - - - - - - {% for device in devices %} - - - - - - - - - {% endfor %} -
{% trans "Platform" %}{% trans "Device Name" %}{% trans "IP" %}{% trans "Last Access" %}{% trans "# Libraries" %}
{{ device.platform }}{{ device.device_name }}{{ device.last_login_ip }}{{ device.last_accessed | translate_seahub_time }} - {{ device.synced_repos|length }}{% if device.synced_repos %} {% endif %} - {% if device.synced_repos %} - - {% endif %} - -
- -
-
-
-

{% trans "Really want to unlink %s?" %}

-

{% trans "It will immediately stop syncing." %}

- - -
-{% else %} -
-

{% trans "You do not have connected devices" %}

-

{% trans "Your clients (Desktop/Android/iOS) will be listed here." %}

-
-{% endif %} - -{% endblock %} - -{% block extra_script %}{{block.super}} - -{% endblock %} diff --git a/seahub/templates/home_base.html b/seahub/templates/home_base.html index 0321384ce9..ae3cc3498b 100644 --- a/seahub/templates/home_base.html +++ b/seahub/templates/home_base.html @@ -50,7 +50,7 @@
  • {% trans "Personal Wiki" %}
  • {% endif %} {% endfor %} -
  • {% trans "Devices" %}
  • +
  • {% trans "Devices" %}
  • {% trans "Share Admin" %}

    diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html index cb13f8ab7c..aacebe8000 100644 --- a/seahub/templates/js/templates.html +++ b/seahub/templates/js/templates.html @@ -666,7 +666,7 @@
  • {% trans "Personal Wiki" %}
  • <% } %> <% } %> -
  • {% trans "Devices" %}
  • +
  • {% trans "Devices" %}
  • {% trans "Share Admin" %}

    @@ -845,6 +845,27 @@ +