Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c25eb1f
D2 - Add code
tma-ndhuy Jan 12, 2023
98f1df9
D1 - Add code
tma-ndhuy Jan 12, 2023
ffe0e97
D2 - UT code
tma-ndhuy Jan 13, 2023
b507150
D2 - update code for fix CI
tma-ndhuy Jan 17, 2023
547c4a1
D2 - fix CI
tma-ndhuy Jan 17, 2023
c05db12
D2 - fix CI
tma-ndhuy Jan 18, 2023
13b947d
D2 - fix CI
tma-ndhuy Jan 19, 2023
874b3e1
D1 - UT code
tma-ndhuy Jan 19, 2023
3c2227c
refs #34: UT code for utils (D.1)
tma-ndhuy Jan 30, 2023
32f4a64
refs #34: Fix CI D.1
tma-ndhuy Jan 31, 2023
6863b74
refs #34: Remove unnecessary import
tma-ndhuy Jan 31, 2023
a8b5fcb
D1 - Update code following comment
tma-ndhuy Feb 3, 2023
96cbc18
refs (D).1.5 [ストレージアドオン]タイムスタンプ機能の改修.[Nextcloud]へ機能移植: Update UT code…
tma-ndhuy Feb 21, 2023
6fa7406
refs (D).1.6 [機関ストレージ]GakuNin RDM ファイル機能の既存のバグ修正: Fix bug IT
tma-ndhuy Mar 8, 2023
2dad6e8
refs (C).2.6 [機関ストレージ]GakuNin RDM ファイル機能の既存のバグ修正: Fix bug IT
tma-ndhuy Mar 9, 2023
e306fa5
refs (C).2.6 [機関ストレージ]GakuNin RDM ファイル機能の既存のバグ修正: Fix bug IT
tma-ndhuy Mar 15, 2023
fb67245
refs (C).2.6 [機関ストレージ]GakuNin RDM ファイル機能の既存のバグ修正: Fix error CI
tma-ndhuy Mar 15, 2023
bf1d5f8
refs (C).2.6 [機関ストレージ]GakuNin RDM ファイル機能の既存のバグ修正: Fix PR error CI
tma-ndhuy Apr 5, 2023
f73d561
Merge remote-tracking branch 'origin/develop' into feature/R-2022-57-…
tma-ntphat Dec 1, 2023
f7040cd
refs (C).2.6 [機関ストレージ]GakuNin RDM ファイル機能の既存のバグ修正: Fix TravisCI - reve…
tma-ntphat Dec 1, 2023
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
2 changes: 1 addition & 1 deletion addons/base/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,7 @@ def addon_view_file(auth, node, file_node, version):
'size': version.size if version.size is not None else 9966699,
'private': getattr(node.get_addon(file_node.provider), 'is_private', False),
'file_tags': list(file_node.tags.filter(system=False).values_list('name', flat=True)) if not file_node._state.adding else [], # Only access ManyRelatedManager if saved
'file_guid': file_node.get_guid()._id,
'file_guid': file_node.get_guid(create=True)._id,
'file_id': file_node._id,
'allow_comments': file_node.provider in settings.ADDONS_COMMENTABLE,
'checkout_user': file_node.checkout._id if file_node.checkout else None,
Expand Down
66 changes: 64 additions & 2 deletions addons/nextcloud/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
from addons.nextcloud.serializer import NextcloudSerializer
from addons.nextcloud.settings import DEFAULT_HOSTS, USE_SSL
from osf.models.external import BasicAuthProviderMixin
from website.util import api_v2_url
from website.util import api_v2_url, timestamp
from addons.nextcloudinstitutions import utils

logger = logging.getLogger(__name__)


Expand All @@ -25,7 +27,67 @@ class NextcloudFolder(NextcloudFileNode, Folder):


class NextcloudFile(NextcloudFileNode, File):
pass
@property
def _hashes(self):
"""This property for getting the latest hash value when uploading files on Nextcloud

:return: None or a dictionary contain MD5, SHA256 and SHA512 hashes value of the Nextcloud
"""
try:
return self._history[-1]['extra']['hashes']['nextcloud']
except (IndexError, KeyError):
return None

def get_hash_for_timestamp(self):
"""This method use for getting hash type SHA512

:return: (None, None) or a tuple includes type hash and the SHA512 hash
"""
hashes = self._hashes
if hashes:
if 'sha512' in hashes:
return timestamp.HASH_TYPE_SHA512, hashes['sha512']
return None, None

def _my_node_settings(self):
"""This method use for getting an addon config of the project

:return: None or the addon config
"""
node = self.target
if node:
addon = node.get_addon(self.provider)
if addon:
return addon
return None

def get_timestamp(self):
"""This method use for getting timestamp data from Nextcloud server

:return: (None, None, None) or a tuple includes a decoded timestamp, a timestamp status and a context
"""
node_settings = self._my_node_settings()
if node_settings:
return utils.get_timestamp(
node_settings,
node_settings.folder_id + self.path,
provider_name=self.provider)
return None, None, None

def set_timestamp(self, timestamp_data, timestamp_status, context):
"""This method use for setting timestamp data to Nextcloud server

:param timestamp_data: a string of 8-bit binary bytes this is the decoded value of the timestamp
:param timestamp_status: an integer value this is the status of the timestamp
:param context: a dictionary contains a url, username and password.
"""
node_settings = self._my_node_settings()
if node_settings:
utils.set_timestamp(
node_settings,
node_settings.folder_id + self.path,
timestamp_data, timestamp_status, context=context,
provider_name=self.provider)


class NextcloudProvider(BasicAuthProviderMixin):
Expand Down
25 changes: 24 additions & 1 deletion addons/nextcloud/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from factory.django import DjangoModelFactory
from osf_tests.factories import UserFactory, ProjectFactory, ExternalAccountFactory

from addons.nextcloud.models import UserSettings, NodeSettings
from addons.nextcloud.models import UserSettings, NodeSettings, NextcloudFile


class NextcloudAccountFactory(ExternalAccountFactory):
Expand All @@ -29,3 +29,26 @@ class Meta:
owner = factory.SubFactory(ProjectFactory)
user_settings = factory.SubFactory(NextcloudUserSettingsFactory)
folder_id = '/Documents/'


class NextcloudFactory(ExternalAccountFactory):
provider = 'nextcloud'
provider_id = factory.Sequence(lambda n: 'id:{0}'.format(n))
oauth_key = factory.Sequence(lambda n: 'key-{0}'.format(n))


class NodeSettingsFactory(DjangoModelFactory):
class Meta:
model = NodeSettings

external_account = factory.SubFactory(NextcloudFactory)
owner = factory.SubFactory(ProjectFactory)


class NextcloudFileFactory(DjangoModelFactory):
class Meta:
model = NextcloudFile

provider = 'nextcloud'
path = 'test.txt'
target = factory.SubFactory(ProjectFactory)
128 changes: 127 additions & 1 deletion addons/nextcloud/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@
import pytest
import unittest

from unittest import mock
from addons.base.tests.models import (OAuthAddonNodeSettingsTestSuiteMixin,
OAuthAddonUserSettingTestSuiteMixin)

from addons.nextcloud.models import NodeSettings
from osf_tests.test_archiver import MockAddon
from addons.nextcloud.tests.factories import (
NextcloudAccountFactory, NextcloudNodeSettingsFactory,
NextcloudUserSettingsFactory
NextcloudUserSettingsFactory, NextcloudFileFactory
)
from addons.nextcloud.settings import USE_SSL
from admin.rdm_addons.utils import get_rdm_addon_option
from osf_tests.factories import (
ExternalAccountFactory,
UserFactory, InstitutionFactory
)

pytestmark = pytest.mark.django_db

Expand Down Expand Up @@ -57,3 +64,122 @@ def test_serialize_settings(self):
'verify_ssl': USE_SSL
}
assert_equal(settings, expected)


class TestNextcloudFile(unittest.TestCase):
def setUp(self):
super(TestNextcloudFile, self).setUp()

def test_get_hash_for_timestamp_return_none(self):
# UT code for the get_hash_for_timestamp method of the NextcloudFile class in case hash not contain sha512
test_obj = NextcloudFileFactory()
res = test_obj.get_hash_for_timestamp()
# Assert result
assert res == (None, None)

def test_my_node_settings(self):
# UT code for the _my_node_settings method of the NextcloudFile class
# Define mock object for the rename_folder method of the IQBRIMSClient class
mock_rename_folder = mock.MagicMock()
mock_rename_folder.return_value = None

# Define mock object for the get_folder_info method of the IQBRIMSClient class
mock_get_folder_info = mock.MagicMock()
mock_get_folder_info.return_value = {'title': 'test_title'}

with mock.patch('addons.iqbrims.client.IQBRIMSClient.rename_folder', mock_rename_folder):
with mock.patch('addons.iqbrims.client.IQBRIMSClient.get_folder_info', mock_get_folder_info):
with mock.patch('osf.models.mixins.AddonModelMixin.get_addon') as mock_get_addon:
test_obj = NextcloudFileFactory()
mock_addon = MockAddon()
mock_get_addon.return_value = mock_addon
res = test_obj._my_node_settings()
# Assert result
assert res != None

def test_my_node_settings_return_none(self):
# UT code for the _my_node_settings method in case project is None
test_obj = NextcloudFileFactory()
res = test_obj._my_node_settings()
# Assert result
assert res == None

def test_get_timestamp(self):
# UT code for the get_timestamp method of the NextcloudFile class
# Define mock object for the get_timestamp function
mock_utils = mock.MagicMock()
mock_utils.return_value = 'abc'

# Define mock object for the rename_folder method of the IQBRIMSClient class
mock_rename_folder = mock.MagicMock()
mock_rename_folder.return_value = None

# Define mock object for the get_folder_info method of the IQBRIMSClient class
mock_get_folder_info = mock.MagicMock()
mock_get_folder_info.return_value = {'title': 'test_title'}

with mock.patch('addons.iqbrims.client.IQBRIMSClient.rename_folder', mock_rename_folder):
with mock.patch('addons.iqbrims.client.IQBRIMSClient.get_folder_info', mock_get_folder_info):
with mock.patch('osf.models.mixins.AddonModelMixin.get_addon') as mock_get_addon:
with mock.patch('addons.nextcloudinstitutions.utils.get_timestamp', mock_utils):
test_obj = NextcloudFileFactory()
mock_addon = MockAddon()
mock_get_addon.return_value = mock_addon
res = test_obj.get_timestamp()
# Assert result
assert res == 'abc'

def test_get_timestamp_return_none(self):
# UT code for the get_timestamp method in case get nodesettings return None
test_obj = NextcloudFileFactory()
res = test_obj.get_timestamp()
# Assert result
assert res == (None, None, None)

def test_set_timestamp(self):
# UT code for the set_timestamp method of the NextcloudFile class
# Define mock object for the set_timestamp function
mock_utils = mock.MagicMock()
mock_utils.return_value = 'abc'

# Define mock object for the rename_folder method of the IQBRIMSClient class
mock_rename_folder = mock.MagicMock()
mock_rename_folder.return_value = None

# Define mock object for the get_folder_info method of the IQBRIMSClient class
mock_get_folder_info = mock.MagicMock()
mock_get_folder_info.return_value = {'title': 'test_title'}

with mock.patch('addons.iqbrims.client.IQBRIMSClient.rename_folder', mock_rename_folder):
with mock.patch('addons.iqbrims.client.IQBRIMSClient.get_folder_info', mock_get_folder_info):
with mock.patch('osf.models.mixins.AddonModelMixin.get_addon') as mock_get_addon:
with mock.patch('addons.nextcloudinstitutions.utils.set_timestamp', mock_utils):
test_obj = NextcloudFileFactory()
mock_addon = MockAddon()
mock_get_addon.return_value = mock_addon
test_obj.set_timestamp('timestamp_data', 'timestamp_status', 'context')

def test_get_hash_for_timestamp(self):
# UT code for the get_hash_for_timestamp method of the NextcloudFile class in case hash contain sha512
# Define mock object for the _hashes property of the NextcloudFile class
mock_hash = mock.MagicMock()
mock_hash = {'sha512': 'data_sha512'}

# Define mock object for the rename_folder method of the IQBRIMSClient class
mock_rename_folder = mock.MagicMock()
mock_rename_folder.return_value = None

# Define mock object for the get_folder_info method of the IQBRIMSClient class
mock_get_folder_info = mock.MagicMock()
mock_get_folder_info.return_value = {'title': 'test_title'}

with mock.patch('addons.iqbrims.client.IQBRIMSClient.rename_folder', mock_rename_folder):
with mock.patch('addons.iqbrims.client.IQBRIMSClient.get_folder_info', mock_get_folder_info):
with mock.patch('osf.models.mixins.AddonModelMixin.get_addon') as mock_get_addon:
with mock.patch('addons.nextcloud.models.NextcloudFile._hashes', mock_hash):
test_obj = NextcloudFileFactory()
mock_addon = MockAddon()
mock_get_addon.return_value = mock_addon
res = test_obj.get_hash_for_timestamp()
# Assert result
assert res == ('sha512', 'data_sha512')
20 changes: 20 additions & 0 deletions addons/nextcloudinstitutions/tests/factories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
import factory

from osf_tests.factories import ExternalAccountFactory


class NextcloudInstitutionsFactory(ExternalAccountFactory):
provider = 'nextcloudinstitutions'
provider_id = factory.Sequence(lambda n: 'id:{0}'.format(n))
oauth_key = factory.Sequence(lambda n: 'key-{0}'.format(n))


class NextcloudInstitutionsAccountFactory:
def __init__(self):
self.account = NextcloudInstitutionsFactory()


class NextcloudInstitutionsNodeSettingsFactory:
def __init__(self):
self.provider = NextcloudInstitutionsAccountFactory()
Loading