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" %}
@@ -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 }}