Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/apps/api/tests/test_datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from rest_framework.test import APITestCase
from datasets.models import Data
from factories import UserFactory, DataFactory
from utils.data import pretty_bytes
from utils.data import pretty_bytes, gb_to_bytes


faker = Factory.create()
Expand Down Expand Up @@ -50,10 +50,19 @@ def test_dataset_api_checks_for_authentication(self):
def test_dataset_api_check_quota(self):
self.client.login(username='creator', password='creator')

# User quota is in GB
quota = float(self.creator.quota)
# Convert to bytes to compute available space
quota = gb_to_bytes(quota)
# Used storage is in bytes
storage_used = float(self.creator.get_used_storage_space())

available_space = quota - storage_used
file_size = 1024 * 1024 * 1024 * 1024

# 1 GB = 1,000,000,000 Bytes
# 1 TB = 1,000 GB = 1,000,000,000,000 Bytes
# Using a big file size of 1 TB to run the test
file_size = 1000 * 1000 * 1000 * 1000

# Fake upload a very big dataset
resp = self.client.post(reverse("data-list"), {
Expand All @@ -68,7 +77,7 @@ def test_dataset_api_check_quota(self):
assert resp.data["data_file"][0] == f'Insufficient space. Your available space is {pretty_bytes(available_space)}. The file size is {pretty_bytes(file_size)}. Please free up some space and try again. You can manage your files in the Resources page.'

# Fake upload a small file
file_size = available_space - 1024
file_size = available_space - 1000
resp = self.client.post(reverse("data-list"), {
'name': 'new-file-test',
'type': Data.COMPETITION_BUNDLE,
Expand Down
3 changes: 2 additions & 1 deletion src/apps/api/views/datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from api.serializers import datasets as serializers
from datasets.models import Data, DataGroup
from competitions.models import CompetitionCreationTaskStatus
from utils.data import make_url_sassy, pretty_bytes
from utils.data import make_url_sassy, pretty_bytes, gb_to_bytes


class DataViewSet(ModelViewSet):
Expand Down Expand Up @@ -90,6 +90,7 @@ def create(self, request, *args, **kwargs):
# Check User quota
storage_used = float(request.user.get_used_storage_space())
quota = float(request.user.quota)
quota = gb_to_bytes(quota)
file_size = float(request.data['file_size'])
if storage_used + file_size > quota:
available_space = pretty_bytes(quota - storage_used)
Expand Down
5 changes: 4 additions & 1 deletion src/apps/api/views/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from profiles.models import User
from tasks.models import Task
from datasets.models import Data
from utils.data import pretty_bytes
from utils.data import pretty_bytes, gb_to_bytes


# TODO:// TaskViewSimple uses simple serializer from tasks, which exists purely for the use of Select2 on phase modal
Expand Down Expand Up @@ -210,7 +210,10 @@ def upload_task(self, request):

# Check if user has enough quota to proceed
storage_used = float(request.user.get_used_storage_space())
# User quota is in GB
quota = float(request.user.quota)
# Convert user quota to bytes
quota = gb_to_bytes(quota)
file_size = uploaded_file.size
if storage_used + file_size > quota:
file_size = pretty_bytes(file_size)
Expand Down
4 changes: 4 additions & 0 deletions src/apps/profiles/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ def get_chahub_is_valid(self):
return True

def get_used_storage_space(self, binary=False):
"""
Function to calculate storage used by a user
Returns in bytes
"""

factor = 1024 if binary else 1000
from datasets.models import Data
Expand Down
17 changes: 17 additions & 0 deletions src/apps/profiles/quota.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import logging
from .models import User

logger = logging.getLogger()


def reset_all_users_quota_to_gb():
"""
Converts user quota from bytes to GB if it's stored in bytes.
Skips users whose quota is already in GB.
"""
users = User.objects.all()
for user in users:
# If quota is in bytes (greater than 1 GB in bytes)
if user.quota > 1000 * 1000 * 1000:
user.quota = user.quota / 1e9 # Convert to GB
user.save()
2 changes: 1 addition & 1 deletion src/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@
GS_BUCKET_NAME = GS_PUBLIC_BUCKET_NAME # Default bucket set to public bucket

# Quota
DEFAULT_USER_QUOTA = 15 * 1000 * 1000 * 1000 # 15GB
DEFAULT_USER_QUOTA = 15 # 15GB


# =============================================================================
Expand Down
2 changes: 1 addition & 1 deletion src/static/riot/quota_management.tag
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

<!-- Quota -->
<div style="flex: 0 0 auto; margin-left: auto;">
Quota: {formatSize(storage_used)} / {formatSize(quota)}
Quota: {formatSize(storage_used)} / {quota} GB
</div>
</div>

Expand Down
5 changes: 5 additions & 0 deletions src/utils/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,8 @@ def pretty_bytes(bytes, decimal_places=1, suffix="B", binary=False):
bytes /= factor

return f"{bytes:.{decimal_places}f}{units[-1]}{suffix}"


def gb_to_bytes(gb, binary=False):
factor = 1024**3 if binary else 1000**3
return gb * factor