diff --git a/admin/institutional_storage_quota_control/views.py b/admin/institutional_storage_quota_control/views.py index 7b028da5986..ce8e844a4c7 100644 --- a/admin/institutional_storage_quota_control/views.py +++ b/admin/institutional_storage_quota_control/views.py @@ -1,16 +1,20 @@ +import logging from django.contrib.auth.mixins import UserPassesTestMixin from django.db import connection, transaction, IntegrityError from django.db.models import Subquery, OuterRef from django.http import Http404 +logger = logging.getLogger(__name__) + from admin.institutions.views import QuotaUserList -from osf.models import Institution, OSFUser, UserQuota +from osf.models import Institution, OSFUser, UserQuota, InstitutionDefaultMaxQuota from admin.base import settings from addons.osfstorage.models import Region from django.views.generic import ListView, View from django.shortcuts import redirect from admin.rdm.utils import RdmPermissionMixin from django.core.urlresolvers import reverse +from api.base import settings as api_settings class InstitutionStorageList(RdmPermissionMixin, UserPassesTestMixin, ListView): @@ -122,6 +126,22 @@ def get_institution(self): raise Http404 return institution + def get_default_max_quota(self): + """Get default max quota for the institution, fallback to DEFAULT_MAX_QUOTA when not found.""" + try: + institution_default_max_quota = InstitutionDefaultMaxQuota.objects.get( + institution_id=self.institution_id + ) + return institution_default_max_quota.default_max_quota + except InstitutionDefaultMaxQuota.DoesNotExist: + return api_settings.DEFAULT_MAX_QUOTA + + def get_context_data(self, **kwargs): + """ Add default_max_quota to template context """ + context = super().get_context_data(**kwargs) + context['default_max_quota'] = self.get_default_max_quota() + return context + class UpdateQuotaUserListByInstitutionStorageID(RdmPermissionMixin, UserPassesTestMixin, View): """ Change max quota for an institution's users if that institution is not using NII Storage. """ @@ -163,17 +183,23 @@ def post(self, request, *args, **kwargs): min_value, max_value = connection.ops.integer_field_range('PositiveIntegerField') if min_value <= max_quota <= max_value: # If max quota value is between 0 and 2147483647, update or create used quota for each user in the institution - for user in OSFUser.objects.filter( - affiliated_institutions=self.institution_id): - try: - with transaction.atomic(): - UserQuota.objects.update_or_create( - user=user, - storage_type=UserQuota.CUSTOM_STORAGE, - defaults={'max_quota': max_quota} - ) - except IntegrityError: - UserQuota.objects.filter(user=user, storage_type=UserQuota.CUSTOM_STORAGE).update(max_quota=max_quota) + with transaction.atomic(): + InstitutionDefaultMaxQuota.objects.update_or_create( + institution_id=self.institution_id, + defaults={'default_max_quota': max_quota} + ) + for user in OSFUser.objects.filter( + affiliated_institutions=self.institution_id): + try: + with transaction.atomic(): + UserQuota.objects.update_or_create( + user=user, + storage_type=UserQuota.CUSTOM_STORAGE, + defaults={'max_quota': max_quota} + ) + except IntegrityError as e: + logger.warning(u'IntegrityError while updating UserQuota: user={}, storage_type={}, max_quota={}: {}.'.format(user.id, UserQuota.CUSTOM_STORAGE, max_quota, str(e))) + UserQuota.objects.filter(user=user, storage_type=UserQuota.CUSTOM_STORAGE).update(max_quota=max_quota) return redirect( 'institutional_storage_quota_control:institution_user_list', institution_id=self.institution_id diff --git a/admin/quota_recalc/views.py b/admin/quota_recalc/views.py index 29484c3d559..abeb1bf6537 100644 --- a/admin/quota_recalc/views.py +++ b/admin/quota_recalc/views.py @@ -1,12 +1,14 @@ +import logging from django.http import JsonResponse from django.db import transaction, IntegrityError from addons.osfstorage.models import Region -from api.base import settings as api_settings from osf.models import OSFUser, UserQuota, Node from osf.models.node import set_project_storage_type from osf.utils.requests import check_select_for_update -from website.util.quota import used_quota +from website.util.quota import get_default_max_quota, used_quota + +logger = logging.getLogger(__name__) def calculate_quota(user): @@ -23,6 +25,7 @@ def calculate_quota(user): with transaction.atomic(): for storage_type in storage_type_list: used = used_quota(user._id, storage_type) + max_quota = get_default_max_quota(user, storage_type) try: if check_select_for_update(): user_quota = UserQuota.objects.filter( @@ -42,10 +45,11 @@ def calculate_quota(user): UserQuota.objects.create( user=user, storage_type=storage_type, - max_quota=api_settings.DEFAULT_MAX_QUOTA, + max_quota=max_quota, used=used, ) - except IntegrityError: + except IntegrityError as e: + logger.warning(u'IntegrityError while creating UserQuota in calculate_quota: user={}, storage_type={}: {}.'.format(user.id, storage_type, str(e))) used = used_quota(user._id, storage_type) if check_select_for_update(): user_quota = UserQuota.objects.filter( diff --git a/admin/templates/institutional_storage_quota_control/user_list_by_institute.html b/admin/templates/institutional_storage_quota_control/user_list_by_institute.html index 2e2050514b0..3d747299e1c 100644 --- a/admin/templates/institutional_storage_quota_control/user_list_by_institute.html +++ b/admin/templates/institutional_storage_quota_control/user_list_by_institute.html @@ -121,7 +121,7 @@

{% trans "Institutional Storage" %} > {{ institution_name }}