Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
13 commits
Select commit Hold shift + click to select a range
a377a99
ref 2.2.アドオンストレージに絡むファイル移動時のクオータ管理 : Commit code and UT handle quota …
tma-hcphat Apr 28, 2026
fa41a4b
ref 2.2.アドオンストレージに絡むファイル移動時のクオータ管理 : Fix review comment
tma-hcphat Apr 29, 2026
e13fdd9
ref 2.2.アドオンストレージに絡むファイル移動時のクオータ管理 : Fix review UT comment
tma-hcphat May 8, 2026
072c66b
Merge remote-tracking branch 'remotes/origin/develop' into feature/ni…
tma-hcphat May 29, 2026
16e472a
ref 2.2.アドオンストレージに絡むファイル移動時のクオータ管理 : Rework review comment
tma-hcphat Jun 2, 2026
4aaecab
ref 2.2.アドオンストレージに絡むファイル移動時のクオータ管理 : Update script use is_recalculati…
tma-hcphat Jun 10, 2026
f65c169
ref 2.2.アドオンストレージに絡むファイル移動時のクオータ管理: Fix IT error
tma-hcphat Jun 5, 2026
66bbbd6
ref 2.2.アドオンストレージに絡むファイル移動時のクオータ管理: Fix issue version incorrect
tma-hcphat Jun 17, 2026
ba196e1
ref 2.2.アドオンストレージに絡むファイル移動時のクオータ管理: Update script handle error
tma-hcphat Jun 24, 2026
c66bb89
ref 2.2.アドオンストレージに絡むファイル移動時のクオータ管理: Update logic pre-check quota, max…
tma-hcphat Aug 13, 2026
12d1433
ref 2.2.アドオンストレージに絡むファイル移動時のクオータ管理: Merge develop and resolve conflict
tma-hcphat Sep 16, 2026
1c3801e
ref 2.2.アドオンストレージに絡むファイル移動時のクオータ管理: Update file size logic
tma-hcphat Sep 23, 2026
6bbcb08
ref 2.2.アドオンストレージに絡むファイル移動時のクオータ管理: Update handle size is string
tma-hcphat Sep 28, 2026
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
40 changes: 39 additions & 1 deletion addons/base/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
from website.ember_osf_web.decorators import ember_flag_is_active
from website.project.utils import serialize_node
from website.util import rubeus, timestamp, inspect_info # noqa
import re
import json as _json

from osf.features import (
SLOAN_COI_DISPLAY,
Expand Down Expand Up @@ -433,6 +435,14 @@ def get_auth(auth, **kwargs):
credentials = node.serialize_waterbutler_credentials(provider_name)
waterbutler_settings = node.serialize_waterbutler_settings(provider_name)

if is_node_process and provider_settings:
# Same limit the file browser shows;
# Only osfstorage defines `high_max_file_size`.
max_size = getattr(provider_settings.config, 'max_file_size', None)
if auth.user and 'high_upload_limit' in auth.user.system_tags:
max_size = getattr(provider_settings.config, 'high_max_file_size', None) or max_size
waterbutler_settings['max_file_size'] = max_size

if not is_node_process:
# for only location_id value
storage = ExportDataLocation.objects.get(pk=location_id)
Expand Down Expand Up @@ -582,6 +592,33 @@ def create_waterbutler_log(payload, **kwargs):
params=payload
)
if payload.get('email') is True or payload.get('errors'):
# Parse structured error info from WaterButler exception repr strings
# e.g. "<InvalidParameters(413, {"message_key": "quota_exceeded", ...})>"
error_info = None
if payload.get('errors'):
for err_str in payload['errors']:
# Try to extract JSON payload embedded in the repr string
json_match = re.search(r'\((?:\d+),\s*(\{.*\})\)', err_str, re.DOTALL)
if json_match:
try:
err_data = _json.loads(json_match.group(1))
message_key = err_data.get('message_key', '')
if message_key == 'quota_exceeded' or 'quota_exceeded' in err_str:
error_info = {'type': 'quota_exceeded'}
break
elif err_data.get('oversized_files'):
error_info = {
'type': 'oversized',
'oversized_files': err_data['oversized_files'],
'max_size': err_data.get('max_size'),
}
break
except Exception as e:
logger.warning(
f'Failed to parse WaterButler error representation string: {err_str}. '
f'Error: {e}'
)

mails.send_mail(
user.username,
mails.FILE_OPERATION_FAILED if payload.get('errors')
Expand All @@ -592,7 +629,8 @@ def create_waterbutler_log(payload, **kwargs):
source_path=payload['source']['materialized'],
source_addon=payload['source']['addon'],
destination_addon=payload['destination']['addon'],
osf_support_email=settings.OSF_SUPPORT_EMAIL
osf_support_email=settings.OSF_SUPPORT_EMAIL,
error_info=error_info,
)
if payload.get('errors'):
# Action failed but our function succeeded
Expand Down
3 changes: 2 additions & 1 deletion addons/osfstorage/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ def wrapped(payload, *args, **kwargs):
'source': source,
'destination': dest_parent,
'name': payload['destination']['name'],
'is_check_permission': is_check_permission
'is_check_permission': is_check_permission,
'replaced_size': int(payload.get('replaced_size', 0)),
})
except KeyError:
raise HTTPError(http_status.HTTP_400_BAD_REQUEST)
Expand Down
1 change: 1 addition & 0 deletions addons/osfstorage/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ def serialize(self, include_full=None, version=None):
earliest_version = self.versions.order_by('created').first()
ret.update({
'version': self.versions.count(),
'size': version.size if version else ret.get('size'),
'md5': version.metadata.get('md5') if version else None,
'sha256': version.metadata.get('sha256') if version else None,
'sha512': version.metadata.get('sha512') if version else None,
Expand Down
47 changes: 47 additions & 0 deletions addons/osfstorage/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,53 @@ def test_serialize(self):
u'sha512': None,
})

def test_serialize_size_by_version(self):
file = OsfStorageFile(name='versioned_file.txt', target=self.node_settings.owner)
file.save()

version1 = file.create_version(
self.user,
{
u'service': u'cloud',
settings.WATERBUTLER_RESOURCE: u'osf',
u'object': u'aaa111',
}, {
u'size': 1000,
u'contentType': u'text/plain',
})

version2 = file.create_version(
self.user,
{
u'service': u'cloud',
settings.WATERBUTLER_RESOURCE: u'osf',
u'object': u'bbb222',
}, {
u'size': 5000,
u'contentType': u'text/plain',
})

# Default serialize (no version arg) returns latest version's size
result_default = file.serialize()
assert_equal(result_default[u'size'], 5000)
assert_equal(result_default[u'version'], 2)
assert_equal(result_default[u'modified'], version2.created.isoformat())
assert_equal(result_default[u'created'], version1.created.isoformat())

# Serialize with version=1 returns version 1's size
result_v1 = file.serialize(version=1)
assert_equal(result_v1[u'size'], 1000)
assert_equal(result_v1[u'version'], 2)
assert_equal(result_v1[u'modified'], version1.created.isoformat())
assert_equal(result_v1[u'created'], version1.created.isoformat())

# Serialize with version=2 returns version 2's size
result_v2 = file.serialize(version=2)
assert_equal(result_v2[u'size'], 5000)
assert_equal(result_v2[u'version'], 2)
assert_equal(result_v2[u'modified'], version2.created.isoformat())
assert_equal(result_v2[u'created'], version1.created.isoformat())

def test_get_child_by_name(self):
child = self.node_settings.get_root().append_file('Test')
assert_equal(child, self.node_settings.get_root().find_child_by_name('Test'))
Expand Down
Loading
Loading