diff --git a/seahub/templates/sysadmin/sys_group_admin.html b/seahub/templates/sysadmin/sys_group_admin.html index 35f7bbda2f..c85d1b8c86 100644 --- a/seahub/templates/sysadmin/sys_group_admin.html +++ b/seahub/templates/sysadmin/sys_group_admin.html @@ -16,7 +16,11 @@ {% for group in groups %} - {{ group.props.group_name }} + {{ group.props.group_name }} + {% if group.org_name %} +

({{group.org_name}})

+ {% endif %} + {{ group.props.creator_name }} {{ group.props.timestamp|tsstr_sec }} {% trans "Delete" %} diff --git a/seahub/templates/sysadmin/sys_org_admin.html b/seahub/templates/sysadmin/sys_org_admin.html index 7809781aa1..fe4326302d 100644 --- a/seahub/templates/sysadmin/sys_org_admin.html +++ b/seahub/templates/sysadmin/sys_org_admin.html @@ -39,7 +39,7 @@ {% for org in orgs %} - {{ org.org_name }} + {{ org.org_name }} {{ org.url_prefix }} {{ org.creator }} diff --git a/seahub/templates/sysadmin/sys_org_info.html b/seahub/templates/sysadmin/sys_org_info.html deleted file mode 100644 index a69e43b632..0000000000 --- a/seahub/templates/sysadmin/sys_org_info.html +++ /dev/null @@ -1,240 +0,0 @@ -{% extends "admin_base.html" %} -{% load i18n avatar_tags seahub_tags group_avatar_tags %} -{% load url from future %} - -{% block nav_orgadmin_class %}class="cur"{% endblock %} - -{% block extra_style %} - -{% endblock %} - -{% block left_panel %} -
- - -

{{ org.org_name }}

-
-
{% trans "Number of members" %}
-
{{ users_count }}
-
{% trans "Number of groups" %}
-
{{ groups_count }}
-
- -

{% trans "Space Used" %}

-

{{ quota_usage|filesizeformat }} {% if total_quota > 0 %}/ {{ total_quota|filesizeformat }} {% endif %}

- {% trans "Set Quota" %} -
-
{% csrf_token %} -

{% trans "Set org storage limit" %}

- - MB -

{% trans "Tip: 0 means default limit" %}

-

- -
-{% endblock %} - -{% block right_panel %} -
-
- -
- -
- - - - - - - - - - {% for user in users %} - - - - - - - - {% endfor %} -
{% trans "Email" %}{% trans "Status" %}{% trans "Space Used" %}{% trans "Create At / Last Login" %}{% trans "Operations" %}
{{ user.email }} -
- {% if user.is_active %} - {% trans "Active" %} - {% else %} - {% trans "Inactive" %} - {% endif %} - {% trans -
- -
- {% if CALC_SHARE_USAGE %} - {{ user.self_usage|filesizeformat }} + {{ user.share_usage|filesizeformat }} {% if user.quota > 0 %} / {{ user.quota|filesizeformat }} {% endif %} - {% else %} - {{ user.self_usage|filesizeformat }} {% if user.quota > 0 %} / {{ user.quota|filesizeformat }} {% endif %} - {% endif %} - - {{ user.ctime|tsstr_sec }} / {% if user.last_login %}{{user.last_login|translate_seahub_time}} {% else %} -- {% endif %} - - {% if not user.is_self %} - {% trans "Delete" %} - {% trans "ResetPwd" %} - {% endif %} -
-
- -
- {% if groups %} - - - - - - - - {% for group in groups %} - - - - - - - {% endfor %} -
{% trans "Name" %}{% trans "Creator" %}{% trans "Create At" %}{% trans "Operations" %}
{{ group.group_name }}{{ group.creator_name }}{{ group.timestamp|tsstr_sec }}{% trans "Delete" %}
- {% else %} -

{% trans "None" %}

- {% endif %} -
-
-
-

{% trans "Activating..., please wait" %}

-
-{% endblock %} - -{% block extra_script %} - -{% endblock %} diff --git a/seahub/templates/sysadmin/sys_org_info_base.html b/seahub/templates/sysadmin/sys_org_info_base.html new file mode 100644 index 0000000000..811178956d --- /dev/null +++ b/seahub/templates/sysadmin/sys_org_info_base.html @@ -0,0 +1,39 @@ +{% extends "admin_base.html" %} +{% load i18n seahub_tags %} +{% load url from future %} + +{% block nav_orgadmin_class %}class="cur"{% endblock %} + +{% block extra_style %} + +{% endblock %} + +{% block left_panel %} +
+ + +

{{ org.org_name }}

+
+
{% trans "Number of members" %}
+
{{ users_count }}
+
{% trans "Number of groups" %}
+
{{ groups_count }}
+
+ +

{% trans "Space Used" %}

+

{{ quota_usage|filesizeformat }} {% if total_quota > 0 %}/ {{ total_quota|filesizeformat }} {% endif %}

+ {% trans "Set Quota" %} +
+
{% csrf_token %} +

{% trans "Set org storage limit" %}

+ + MB +

{% trans "Tip: 0 means default limit" %}

+

+ +
+{% endblock %} diff --git a/seahub/templates/sysadmin/sys_org_info_group.html b/seahub/templates/sysadmin/sys_org_info_group.html new file mode 100644 index 0000000000..b3cd91d3ee --- /dev/null +++ b/seahub/templates/sysadmin/sys_org_info_group.html @@ -0,0 +1,47 @@ +{% extends "sysadmin/sys_org_info_base.html" %} +{% load i18n seahub_tags %} +{% load url from future %} + +{% block right_panel %} +
+ +
+ +{% if groups %} + + + + + + + + {% for group in groups %} + + + + + + + {% endfor %} +
{% trans "Name" %}{% trans "Creator" %}{% trans "Create At" %}{% trans "Operations" %}
{{ group.group_name }}{{ group.creator_name }}{{ group.timestamp|tsstr_sec }}{% trans "Delete" %}
+{% else %} +
+

{% trans "This organization doesn't have any groups" %}

+
+{% endif %} +{% endblock %} + +{% block extra_script %} + +{% endblock %} diff --git a/seahub/templates/sysadmin/sys_org_info_library.html b/seahub/templates/sysadmin/sys_org_info_library.html new file mode 100644 index 0000000000..1f8284b814 --- /dev/null +++ b/seahub/templates/sysadmin/sys_org_info_library.html @@ -0,0 +1,61 @@ +{% extends "sysadmin/sys_org_info_base.html" %} +{% load i18n seahub_tags %} +{% load url from future %} + +{% block right_panel %} +
+ +
+ +{% if org_repos %} + + + + + + + + + {% for repo in org_repos %} + + + + + + + + {% endfor %} +
{% trans "Name" %}ID{% trans "Owner" %}{% trans "Description" %}{% trans "Operations" %}
{{ repo.name }}{{ repo.id }} + {% if repo.owner %} + {{ repo.owner}} + {% else %} + -- + {% endif %} + {{ repo.desc }} +
+ {% trans "Delete" %} +
+
+{% else %} +
+

{% trans "This organization doesn't have any libraries" %}

+
+{% endif %} + +{% include 'snippets/repo_del_popup.html' %} +{% include 'sysadmin/repo_transfer_form.html' %} + +{% endblock %} + +{% block extra_script %} + +{% endblock %} diff --git a/seahub/templates/sysadmin/sys_org_info_setting.html b/seahub/templates/sysadmin/sys_org_info_setting.html new file mode 100644 index 0000000000..d872a513d2 --- /dev/null +++ b/seahub/templates/sysadmin/sys_org_info_setting.html @@ -0,0 +1,30 @@ +{% extends "sysadmin/sys_org_info_base.html" %} +{% load i18n seahub_tags %} +{% load url from future %} + +{% block right_panel %} +
+ +
+ +
+

{% trans "Rename Organization" %}

+
{% csrf_token %} +
+
+ +
+
+ +{% endblock %} + +{% block extra_script %} + +{% endblock %} diff --git a/seahub/templates/sysadmin/sys_org_info_user.html b/seahub/templates/sysadmin/sys_org_info_user.html new file mode 100644 index 0000000000..5df68abdfd --- /dev/null +++ b/seahub/templates/sysadmin/sys_org_info_user.html @@ -0,0 +1,138 @@ +{% extends "sysadmin/sys_org_info_base.html" %} +{% load i18n seahub_tags %} +{% load url from future %} + +{% block right_panel %} +
+ +
+ + + + + + + + + + + {% for user in users %} + + + + + + + + {% endfor %} +
{% trans "Email" %}{% trans "Status" %}{% trans "Space Used" %}{% trans "Create At / Last Login" %}{% trans "Operations" %}
{{ user.email }} +
+ {% if user.is_active %} + {% trans "Active" %} + {% else %} + {% trans "Inactive" %} + {% endif %} + {% trans +
+ +
+ {% if CALC_SHARE_USAGE %} + {{ user.self_usage|filesizeformat }} + {{ user.share_usage|filesizeformat }} {% if user.quota > 0 %} / {{ user.quota|filesizeformat }} {% endif %} + {% else %} + {{ user.self_usage|filesizeformat }} {% if user.quota > 0 %} / {{ user.quota|filesizeformat }} {% endif %} + {% endif %} + + {{ user.ctime|tsstr_sec }} / {% if user.last_login %}{{user.last_login|translate_seahub_time}} {% else %} -- {% endif %} + + {% if not user.is_self %} + {% trans "Delete" %} + {% trans "ResetPwd" %} + {% endif %} +
+ +
+

{% trans "Activating..., please wait" %}

+
+ +{% endblock %} + +{% block extra_script %} + +{% endblock %} diff --git a/seahub/templates/sysadmin/sys_org_set_quota_js.html b/seahub/templates/sysadmin/sys_org_set_quota_js.html new file mode 100644 index 0000000000..64501c3618 --- /dev/null +++ b/seahub/templates/sysadmin/sys_org_set_quota_js.html @@ -0,0 +1,41 @@ +{% load i18n%} +$('#set-quota').click(function() { + $("#set-quota-form").modal({appendTo: "#main"}); + return false; +}); + +$('#set-quota-form .submit').click(function() { + var form = $('#set-quota-form'), + form_id = form.attr('id'); + + var quota = $('input[name="quota"]', form).val(); + if (!$.trim(quota)) { + apply_form_error(form_id, "{% trans "Quota can not be empty" %}"); + return false; + } + + var sb_btn = $(this); + disable(sb_btn); + $.ajax({ + url: '{% url 'sys_org_set_quota' org.org_id %}', + type: 'POST', + dataType: 'json', + cache: 'false', + beforeSend: prepareCSRFToken, + data: { + 'quota': quota + }, + success: function(data) { + location.reload(true); + }, + error: function(xhr, textStatus, errorThrown) { + if (xhr.responseText) { + apply_form_error(form_id, $.parseJSON(xhr.responseText).error); + } else { + apply_form_error(form_id, "{% trans "Failed. Please check the network." %}"); + } + enable(sb_btn); + } + }); + return false; +}); diff --git a/seahub/templates/sysadmin/useradmin_table.html b/seahub/templates/sysadmin/useradmin_table.html index f5d961a109..7b9c1f957b 100644 --- a/seahub/templates/sysadmin/useradmin_table.html +++ b/seahub/templates/sysadmin/useradmin_table.html @@ -13,7 +13,7 @@ {{ user.email }} {% if user.org %} -

({{user.org.org_name}})

+

({{user.org.org_name}})

{% endif %} diff --git a/seahub/templates/sysadmin/userinfo.html b/seahub/templates/sysadmin/userinfo.html index b68f58c5e0..327c1607e9 100644 --- a/seahub/templates/sysadmin/userinfo.html +++ b/seahub/templates/sysadmin/userinfo.html @@ -11,6 +11,11 @@
{% trans "Email" %}
{{ email }}
+ {% if org_name %} +
{% trans "Organization" %}
+
{{ org_name }}
+ {% endif %} + {% if profile %}
{% trans "Name" context "true name" %}
{{ profile.nickname }}
diff --git a/seahub/urls.py b/seahub/urls.py index ac37ba4c7f..5c8213b67d 100644 --- a/seahub/urls.py +++ b/seahub/urls.py @@ -187,8 +187,12 @@ urlpatterns = patterns('', url(r'^sys/useradmin/admins/$', sys_user_admin_admins, name='sys_useradmin_admins'), url(r'^sys/groupadmin/$', sys_group_admin, name='sys_group_admin'), url(r'^sys/orgadmin/$', sys_org_admin, name='sys_org_admin'), - url(r'^sys/orgadmin/(?P\d+)/$', sys_org_info, name='sys_org_info'), url(r'^sys/orgadmin/(?P\d+)/set_quota/$', sys_org_set_quota, name='sys_org_set_quota'), + url(r'^sys/orgadmin/(?P\d+)/rename/$', sys_org_rename, name='sys_org_rename'), + url(r'^sys/orgadmin/(?P\d+)/user/$', sys_org_info_user, name='sys_org_info_user'), + url(r'^sys/orgadmin/(?P\d+)/group/$', sys_org_info_group, name='sys_org_info_group'), + url(r'^sys/orgadmin/(?P\d+)/library/$', sys_org_info_library, name='sys_org_info_library'), + url(r'^sys/orgadmin/(?P\d+)/setting/$', sys_org_info_setting, name='sys_org_info_setting'), url(r'^sys/publinkadmin/$', sys_publink_admin, name='sys_publink_admin'), url(r'^sys/notificationadmin/', notification_list, name='notification_list'), url(r'^useradmin/add/$', user_add, name="user_add"), diff --git a/seahub/views/sysadmin.py b/seahub/views/sysadmin.py index ba70384023..53b7741ad2 100644 --- a/seahub/views/sysadmin.py +++ b/seahub/views/sysadmin.py @@ -331,6 +331,7 @@ def user_info(request, email): owned_repos = seafile_api.get_owned_repo_list(email) org = ccnet_threaded_rpc.get_orgs_by_user(email) + org_name = None if not org: my_usage = seafile_api.get_user_self_usage(email) quota = seafile_api.get_user_quota(email) @@ -340,6 +341,7 @@ def user_info(request, email): get_org_user_quota_usage(org_id, email) quota = seafserv_threaded_rpc. \ get_org_user_quota(org_id, email) + org_name = org[0].org_name if CALC_SHARE_USAGE: try: @@ -371,6 +373,7 @@ def user_info(request, email): 'email': email, 'profile': profile, 'd_profile': d_profile, + 'org_name': org_name, }, context_instance=RequestContext(request)) @login_required_ajax @@ -394,7 +397,13 @@ def user_set_quota(request, email): seafile_api.set_user_quota(email, quota) else: org_id = org[0].org_id - seafserv_threaded_rpc.set_org_user_quota(org_id, email, quota) + org_quota_mb = seafserv_threaded_rpc.get_org_quota(org_id) / (1 << 20) + if quota_mb > org_quota_mb: + result['error'] = _(u'Failed to set quota: maximum quota is %d MB' % \ + org_quota_mb) + return HttpResponse(json.dumps(result), status=400, content_type=content_type) + else: + seafserv_threaded_rpc.set_org_user_quota(org_id, email, quota) except: result['error'] = _(u'Failed to set quota: internal server error') return HttpResponse(json.dumps(result), status=500, content_type=content_type) @@ -444,8 +453,8 @@ def user_remove(request, user_id): return HttpResponseRedirect(next) org_id = org[0].org_id - org_repos = seafile_api.get_org_owned_repo_list(org_id, user.email) - for repo in org_repos: + org_user_repos = seafile_api.get_org_owned_repo_list(org_id, user.email) + for repo in org_user_repos: seafile_api.remove_repo(repo.id) user.delete() @@ -733,8 +742,13 @@ def sys_group_admin(request): groups_plus_one = ccnet_threaded_rpc.get_all_groups(per_page * (current_page -1), per_page +1) - + groups = groups_plus_one[:per_page] + for grp in groups: + org_id = ccnet_threaded_rpc.get_org_id_by_group(int(grp.id)) + if org_id > 0: + grp.org_id = org_id + grp.org_name = ccnet_threaded_rpc.get_org_by_id(int(org_id)).org_name if len(groups_plus_one) == per_page + 1: page_next = True @@ -784,18 +798,59 @@ def sys_org_admin(request): @login_required @sys_staff_required -def sys_org_info(request, org_id): +def sys_org_rename(request, org_id): + + if request.method != 'POST': + raise Http404 + + referer = request.META.get('HTTP_REFERER', None) + next = reverse('sys_org_admin') if referer is None else referer + + new_name = request.POST.get('new_name', None) + if new_name: + try: + ccnet_threaded_rpc.set_org_name(int(org_id), new_name) + messages.success(request, _(u'Success')) + except Exception as e: + logger.error(e) + messages.error(request, _(u'Failed to rename organization')) + + return HttpResponseRedirect(next) + +def sys_get_org_base_info(org_id): - org_id = int(org_id) org = ccnet_threaded_rpc.get_org_by_id(org_id) + # users users = ccnet_threaded_rpc.get_org_emailusers(org.url_prefix, -1, -1) users_count = len(users) + # groups + groups = ccnet_threaded_rpc.get_org_groups(org_id, -1, -1) + groups_count = len(groups) + # quota total_quota = seafserv_threaded_rpc.get_org_quota(org_id) quota_usage = seafserv_threaded_rpc.get_org_quota_usage(org_id) + return { + "org": org, + "users": users, + "users_count": users_count, + "groups": groups, + "groups_count": groups_count, + "total_quota": total_quota, + "quota_usage": quota_usage, + } + +@login_required +@sys_staff_required +def sys_org_info_user(request, org_id): + + org_id = int(org_id) + + org_basic_info = sys_get_org_base_info(org_id) + users = org_basic_info["users"] last_logins = UserLastLogin.objects.filter(username__in=[x.email for x in users]) for user in users: if user.id == request.user.id: @@ -803,7 +858,7 @@ def sys_org_info(request, org_id): try: user.self_usage =seafserv_threaded_rpc. \ get_org_user_quota_usage(org_id, user.email) - user.share_usage = 0 #seafile_api.get_user_share_usage(user.email) + user.share_usage = 0 user.quota = seafserv_threaded_rpc. \ get_org_user_quota(org_id, user.email) except SearpcError as e: @@ -818,20 +873,49 @@ def sys_org_info(request, org_id): if last_login.username == user.email: user.last_login = last_login.last_login - # groups - groups = ccnet_threaded_rpc.get_org_groups(org_id, -1, -1) - groups_count = len(groups) + return render_to_response('sysadmin/sys_org_info_user.html', + org_basic_info, context_instance=RequestContext(request)) - return render_to_response('sysadmin/sys_org_info.html', { - 'org': org, - 'users': users, - 'users_count': users_count, - 'total_quota': total_quota, - 'quota_usage': quota_usage, - 'groups': groups, - 'groups_count': groups_count, - }, context_instance=RequestContext(request)) +@login_required +@sys_staff_required +def sys_org_info_group(request, org_id): + + org_id = int(org_id) + org_basic_info = sys_get_org_base_info(org_id) + + return render_to_response('sysadmin/sys_org_info_group.html', + org_basic_info, context_instance=RequestContext(request)) + +@login_required +@sys_staff_required +def sys_org_info_library(request, org_id): + + org_id = int(org_id) + org_basic_info = sys_get_org_base_info(org_id) + + # library + org_repos = seafserv_threaded_rpc.get_org_repo_list(org_id, -1, -1) + + for repo in org_repos: + try: + repo.owner = seafserv_threaded_rpc.get_org_repo_owner(repo.id) + except: + repo.owner = None + + org_basic_info["org_repos"] = org_repos + return render_to_response('sysadmin/sys_org_info_library.html', + org_basic_info, context_instance=RequestContext(request)) + +@login_required +@sys_staff_required +def sys_org_info_setting(request, org_id): + + org_id = int(org_id) + org_basic_info = sys_get_org_base_info(org_id) + + return render_to_response('sysadmin/sys_org_info_setting.html', + org_basic_info, context_instance=RequestContext(request)) @login_required @sys_staff_required @@ -930,12 +1014,18 @@ def sys_repo_transfer(request): new_owner = request.POST.get('email', None) if repo_id and new_owner: - try: - User.objects.get(email=new_owner) - seafile_api.set_repo_owner(repo_id, new_owner) - messages.success(request, _(u'Successfully transfered.')) - except User.DoesNotExist: - messages.error(request, _(u'Failed to transfer, user %s not found') % new_owner) + if seafserv_threaded_rpc.get_org_id_by_repo_id(repo_id) > 0: + messages.error(request, _(u'Can not transfer organization library')) + else: + try: + User.objects.get(email=new_owner) + if ccnet_threaded_rpc.get_orgs_by_user(new_owner): + messages.error(request, _(u'Can not transfer library to organization user %s') % new_owner) + else: + seafile_api.set_repo_owner(repo_id, new_owner) + messages.success(request, _(u'Successfully transfered.')) + except User.DoesNotExist: + messages.error(request, _(u'Failed to transfer, user %s not found') % new_owner) else: messages.error(request, _(u'Failed to transfer, invalid arguments.'))