diff --git a/seahub/institutions/migrations/0002_institutionquota.py b/seahub/institutions/migrations/0002_institutionquota.py new file mode 100644 index 0000000000..f862ded98f --- /dev/null +++ b/seahub/institutions/migrations/0002_institutionquota.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('institutions', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='InstitutionQuota', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('quota', models.BigIntegerField()), + ('institution', models.ForeignKey(to='institutions.Institution')), + ], + ), + ] diff --git a/seahub/institutions/models.py b/seahub/institutions/models.py index f3eea40bec..042fee652d 100644 --- a/seahub/institutions/models.py +++ b/seahub/institutions/models.py @@ -11,3 +11,17 @@ class Institution(models.Model): class InstitutionAdmin(models.Model): institution = models.ForeignKey(Institution) user = models.EmailField() + + +class InstitutionQuotaManager(models.Manager): + def get_or_none(self, *args, **kwargs): + try: + return self.get(*args, **kwargs).quota + except self.model.DoesNotExist: + return None + + +class InstitutionQuota(models.Model): + institution = models.ForeignKey(Institution) + quota = models.BigIntegerField() + objects = InstitutionQuotaManager() diff --git a/seahub/institutions/templates/institutions/user_info.html b/seahub/institutions/templates/institutions/user_info.html index bf9806c556..3bfbd95890 100644 --- a/seahub/institutions/templates/institutions/user_info.html +++ b/seahub/institutions/templates/institutions/user_info.html @@ -45,17 +45,14 @@ {% endif %}
{% trans "Space Used" %}
-
{{ space_usage|seahub_filesizeformat }} {% if space_quota > 0 %} / {{ space_quota|seahub_filesizeformat }} {% endif %}
+
{{ space_usage|seahub_filesizeformat }} {% if space_quota > 0 %} / {{ space_quota|seahub_filesizeformat }} {% endif %} {% trans "Set Quota" %}
{% csrf_token %}

{% trans "Set user storage limit" %}

MB -

- {% trans "An integer that is greater than or equal to 0." %}
- {% trans "Tip: 0 means default limit" %} -

+

{% trans "Available quota:" %} {{ available_quota|seahub_filesizeformat}}

@@ -140,5 +137,46 @@ {% block extra_script %} {% endblock %} diff --git a/seahub/institutions/urls.py b/seahub/institutions/urls.py index c245906b67..4c6dc84544 100644 --- a/seahub/institutions/urls.py +++ b/seahub/institutions/urls.py @@ -2,7 +2,7 @@ from django.conf.urls import patterns, url from .views import (info, useradmin, user_info, user_remove, useradmin_search, - user_toggle_status) + user_toggle_status, user_set_quota) urlpatterns = patterns( '', @@ -11,5 +11,6 @@ urlpatterns = patterns( url(r'^useradmin/info/(?P[^/]+)/$', user_info, name='user_info'), url(r'^useradmin/remove/(?P[^/]+)/$', user_remove, name='user_remove'), url('^useradmin/search/$', useradmin_search, name="useradmin_search"), + url(r'^useradmin/set_quota/(?P[^/]+)/$', user_set_quota, name='user_set_quota'), url(r'^useradmin/toggle_status/(?P[^/]+)/$', user_toggle_status, name='user_toggle_status'), ) diff --git a/seahub/institutions/utils.py b/seahub/institutions/utils.py new file mode 100644 index 0000000000..ef861f6316 --- /dev/null +++ b/seahub/institutions/utils.py @@ -0,0 +1,25 @@ +# Copyright (c) 2012-2016 Seafile Ltd. +from seaserv import seafile_api +from seahub.profile.models import Profile +from seahub.institutions.models import InstitutionQuota + + +def get_institution_space_usage(inst): + # TODO: need to refactor + usernames = [x.user for x in Profile.objects.filter(institution=inst.name)] + total = 0 + for user in usernames: + total += seafile_api.get_user_self_usage(user) + return total + +def get_institution_available_quota(inst): + inst_quota = InstitutionQuota.objects.get_or_none(institution=inst) + if inst_quota is None: + return None + + usernames = [x.user for x in Profile.objects.filter(institution=inst.name)] + allocated = 0 + for user in usernames: + allocated += seafile_api.get_user_quota(user) + + return 0 if allocated >= inst_quota else inst_quota - allocated diff --git a/seahub/institutions/views.py b/seahub/institutions/views.py index aac0778d13..d02f13f7e2 100644 --- a/seahub/institutions/views.py +++ b/seahub/institutions/views.py @@ -18,13 +18,16 @@ from seahub.base.decorators import require_POST from seahub.base.models import UserLastLogin from seahub.institutions.decorators import (inst_admin_required, inst_admin_can_manage_user) +from seahub.institutions.utils import get_institution_available_quota from seahub.profile.models import Profile, DetailedProfile from seahub.utils import is_valid_username, clear_token from seahub.utils.rpc import mute_seafile_api +from seahub.utils.file_size import get_file_size_unit from seahub.views.sysadmin import email_user_on_activation, populate_user_info logger = logging.getLogger(__name__) + def _populate_user_quota_usage(user): """Populate space/share quota to user. @@ -162,6 +165,8 @@ def user_info(request, email): else: g.role = _('Member') + available_quota = get_institution_available_quota(request.user.institution) + return render_to_response( 'institutions/user_info.html', { 'owned_repos': owned_repos, @@ -172,6 +177,7 @@ def user_info(request, email): 'profile': profile, 'd_profile': d_profile, 'personal_groups': personal_groups, + 'available_quota': available_quota, }, context_instance=RequestContext(request)) @require_POST @@ -192,6 +198,26 @@ def user_remove(request, email): return HttpResponseRedirect(next) +@login_required_ajax +@require_POST +@inst_admin_required +@inst_admin_can_manage_user +def user_set_quota(request, email): + content_type = 'application/json; charset=utf-8' + quota_mb = int(request.POST.get('space_quota', 0)) + quota = quota_mb * get_file_size_unit('MB') + + available_quota = get_institution_available_quota(request.user.institution) + if available_quota < quota: + result = {} + result['error'] = _(u'Failed to set quota: maximum quota is %d MB' % \ + (available_quota / 10 ** 6)) + return HttpResponse(json.dumps(result), status=400, content_type=content_type) + + seafile_api.set_user_quota(email, quota) + + return HttpResponse(json.dumps({'success': True}), content_type=content_type) + @login_required_ajax @require_POST @inst_admin_required @@ -234,3 +260,4 @@ def user_toggle_status(request, email): except User.DoesNotExist: return HttpResponse(json.dumps({'success': False}), status=500, content_type=content_type) + diff --git a/seahub/templates/sysadmin/sys_inst_info_admins.html b/seahub/templates/sysadmin/sys_inst_info_admins.html index d5c7bc4547..884ff28c0e 100644 --- a/seahub/templates/sysadmin/sys_inst_info_admins.html +++ b/seahub/templates/sysadmin/sys_inst_info_admins.html @@ -49,7 +49,7 @@ {% endblock %} -{% block extra_script %} +{% block extra_script %}{{ block.super }} +{% endblock %} diff --git a/seahub/templates/sysadmin/sys_inst_info_user.html b/seahub/templates/sysadmin/sys_inst_info_user.html index 25d86c1ca6..cf986b3b58 100644 --- a/seahub/templates/sysadmin/sys_inst_info_user.html +++ b/seahub/templates/sysadmin/sys_inst_info_user.html @@ -54,7 +54,7 @@ {% endblock %} -{% block extra_script %} +{% block extra_script %}{{ block.super }}