Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
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: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ COPY ./addons/swift/requirements.txt ./addons/swift/
COPY ./addons/azureblobstorage/requirements.txt ./addons/azureblobstorage/
COPY ./addons/weko/requirements.txt ./addons/weko/
COPY ./addons/s3compat/requirements.txt ./addons/s3compat/
COPY ./addons/s3compatsigv4/requirements.txt ./addons/s3compatsigv4/
COPY ./addons/s3compatinstitutions/requirements.txt ./addons/s3compatinstitutions/
COPY ./addons/s3compatb3/requirements.txt ./addons/s3compatb3/
COPY ./addons/ociinstitutions/requirements.txt ./addons/ociinstitutions/
Expand Down Expand Up @@ -167,6 +168,7 @@ COPY ./addons/azureblobstorage/static/ ./addons/azureblobstorage/static/
COPY ./addons/weko/static/ ./addons/weko/static/
COPY ./addons/jupyterhub/static/ ./addons/jupyterhub/static/
COPY ./addons/s3compat/static/ ./addons/s3compat/static/
COPY ./addons/s3compatsigv4/static/ ./addons/s3compatsigv4/static/
COPY ./addons/s3compatinstitutions/static/ ./addons/s3compatinstitutions/static/
COPY ./addons/s3compatb3/static/ ./addons/s3compatb3/static/
COPY ./addons/ociinstitutions/requirements.txt ./addons/ociinstitutions/
Expand Down
8 changes: 8 additions & 0 deletions addons.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"weko",
"jupyterhub",
"s3compat",
"s3compatsigv4",
"s3compatinstitutions",
"s3compatb3",
"ociinstitutions",
Expand Down Expand Up @@ -62,6 +63,7 @@
"azureblobstorage": "partial",
"weko": "partial",
"s3compat": "partial",
"s3compatsigv4": "partial",
"s3compatinstitutions": "partial",
"s3compatb3": "partial",
"ociinstitutions": "partial",
Expand Down Expand Up @@ -89,6 +91,7 @@
"azureblobstorage",
"weko",
"s3compat",
"s3compatsigv4",
"s3compatinstitutions",
"s3compatb3",
"ociinstitutions",
Expand Down Expand Up @@ -129,6 +132,7 @@
"weko": "JAIRO Cloud is an application server to share, archive data.",
"jupyterhub": "Jupyter is a web-based interactive computational environment. Files on a GakuNin RDM project can be imported to/exported from Jupyter",
"s3compat": "S3 Compatible Storage is a file storage add-on. Connect your S3 Compatible Storage account to a GakuNin RDM project to interact with files hosted on S3 Compatible Storage via the GakuNin RDM.",
"s3compatsigv4": "S3 Compatible Storage (SigV4) is a file storage add-on. Connect your S3 Compatible Storage (SigV4) account to a GakuNin RDM project to interact with files hosted on S3 Compatible Storage (SigV4) via the GakuNin RDM.",
"s3compatinstitutions": "S3 Compatible Storage for Institutions is a file storage add-on. Connect your S3 Compatible Storage account to a GakuNin RDM project to interact with files hosted on S3 Compatible Storage via the GakuNin RDM.",
"s3compatb3": "S3 Compatible Storage is a file storage add-on. Connect your S3 Compatible Storage account to a GakuNin RDM project to interact with files hosted on S3 Compatible Storage via the GakuNin RDM.",
"ociinstitutions": "Oracle Cloud Infrastructure for Institutions is a file storage add-on. Connect your Oracle Cloud Infrastructure Object Storage account to a GakuNin RDM project to interact with files hosted on Oracle Cloud Infrastructure Object Storage via the GakuNin RDM.",
Expand Down Expand Up @@ -161,6 +165,7 @@
"weko": "https://weko.at.nii.ac.jp/",
"jupyterhub": "https://jupyterhub.readthedocs.io/",
"s3compat": "https://aws.amazon.com/s3/",
"s3compatsigv4": "https://aws.amazon.com/s3/",
"s3compatb3": "https://aws.amazon.com/s3/",
"nextcloud": "https://nextcloud.com/",
"iqbrims": "https://drive.google.com",
Expand All @@ -187,18 +192,21 @@
"onedrive",
"s3",
"s3compat",
"s3compatsigv4",
"owncloud"
],
"addons_has_max_keys": [
"s3",
"s3compat",
"s3compatsigv4",
"s3compatinstitutions",
"s3compatb3",
"ociinstitutions"
],
"addons_folder_field": {
"s3": "folder_name",
"s3compat": "folder_name",
"s3compatsigv4": "folder_name",
"s3compatb3": "folder_name",
"azureblobstorage": "folder_name",
"box": "folder_name",
Expand Down
33 changes: 33 additions & 0 deletions addons/s3compatsigv4/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# RDM S3 Compatible Storage (SigV4) Addon

S3 Compatible Storage (SigV4) Addon enables to mount Cloud Storage which supports Amazon S3-like API on the project.

## Configuring the addon

Users can select storage from the S3 Compatible Storage (SigV4) List,
which is defined in `addons/s3compatsigv4/static/settings.json`.

```
{
"availableServices": [{"name": "Wasabi",
"host": "s3.wasabisys.com",
"bucketLocations": {
"us-east": {"name": "us-east", "host": "s3.wasabisys.com"},
"us-west-1": {"name": "us-west-1", "host": "s3.us-west-1.wasabisys.com"},
"eu-central": {"name": "eu-central", "host": "s3.eu-central-1.wasabisys.com"},
"": {"name": "Virginia"}}},
{"name": "My Private Storage",
"host": "my-private-storage-address:80"}
],
"encryptUploads": true
}
```

## Enabling the addon

### Enable on RDM
1. On RDM, enable S3 Compatible Storage (SigV4) as a provider
2. Scroll down to Configure Add-ons
3. Choose desired storage service
4. Connect your account and enter your ID and secret
5. Select a bucket to work from, or create a new one.
1 change: 1 addition & 0 deletions addons/s3compatsigv4/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default_app_config = 'addons.s3compatsigv4.apps.S3CompatSigV4AddonAppConfig'
68 changes: 68 additions & 0 deletions addons/s3compatsigv4/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import os
from addons.base.apps import BaseAddonAppConfig, generic_root_folder
from addons.s3compatsigv4.settings import MAX_UPLOAD_SIZE

s3compatsigv4_root_folder = generic_root_folder('s3compatsigv4')

HERE = os.path.dirname(os.path.abspath(__file__))
TEMPLATE_PATH = os.path.join(
HERE,
'templates'
)

class S3CompatSigV4AddonAppConfig(BaseAddonAppConfig):

name = 'addons.s3compatsigv4'
label = 'addons_s3compatsigv4'
owners = ['user', 'node']
configs = ['accounts', 'node']
categories = ['storage']
has_hgrid_files = True
max_file_size = MAX_UPLOAD_SIZE
node_settings_template = os.path.join(TEMPLATE_PATH, 's3compatsigv4_node_settings.mako')
user_settings_template = os.path.join(TEMPLATE_PATH, 's3compatsigv4_user_settings.mako')

@property
def full_name(self):
return 'S3 Compatible Storage (SigV4)'

@property
def short_name(self):
return 's3compatsigv4'

@property
def get_hgrid_data(self):
return s3compatsigv4_root_folder

BUCKET_LINKED = 's3compatsigv4_bucket_linked'
BUCKET_UNLINKED = 's3compatsigv4_bucket_unlinked'
FILE_ADDED = 's3compatsigv4_file_added'
FILE_REMOVED = 's3compatsigv4_file_removed'
FILE_UPDATED = 's3compatsigv4_file_updated'
FOLDER_CREATED = 's3compatsigv4_folder_created'
NODE_AUTHORIZED = 's3compatsigv4_node_authorized'
NODE_DEAUTHORIZED = 's3compatsigv4_node_deauthorized'
NODE_DEAUTHORIZED_NO_USER = 's3compatsigv4_node_deauthorized_no_user'

actions = (BUCKET_LINKED,
BUCKET_UNLINKED,
FILE_ADDED,
FILE_REMOVED,
FILE_UPDATED,
FOLDER_CREATED,
NODE_AUTHORIZED,
NODE_DEAUTHORIZED,
NODE_DEAUTHORIZED_NO_USER)

@property
def routes(self):
from . import routes
return [routes.api_routes]

@property
def user_settings(self):
return self.get_model('UserSettings')

@property
def node_settings(self):
return self.get_model('NodeSettings')
68 changes: 68 additions & 0 deletions addons/s3compatsigv4/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.28 on 2026-01-12 14:02
from __future__ import unicode_literals

import addons.base.models
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django_extensions.db.fields
import osf.models.base
import osf.utils.datetime_aware_jsonfield
import osf.utils.fields


class Migration(migrations.Migration):

initial = True

dependencies = [
('osf', '0261_auto_20260112_1402'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='NodeSettings',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, verbose_name='created')),
('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, verbose_name='modified')),
('_id', models.CharField(db_index=True, default=osf.models.base.generate_object_id, max_length=24, unique=True)),
('is_deleted', models.BooleanField(default=False)),
('deleted', osf.utils.fields.NonNaiveDateTimeField(blank=True, null=True)),
('folder_id', models.TextField(blank=True, null=True)),
('folder_name', models.TextField(blank=True, null=True)),
('folder_location', models.TextField(blank=True, null=True)),
('encrypt_uploads', models.BooleanField(default=True)),
('external_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='addons_s3compatsigv4_node_settings', to='osf.ExternalAccount')),
('owner', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='addons_s3compatsigv4_node_settings', to='osf.AbstractNode')),
],
options={
'abstract': False,
},
bases=(models.Model, osf.models.base.QuerySetExplainMixin, addons.base.models.BaseStorageAddon),
),
migrations.CreateModel(
name='UserSettings',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, verbose_name='created')),
('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, verbose_name='modified')),
('_id', models.CharField(db_index=True, default=osf.models.base.generate_object_id, max_length=24, unique=True)),
('is_deleted', models.BooleanField(default=False)),
('deleted', osf.utils.fields.NonNaiveDateTimeField(blank=True, null=True)),
('oauth_grants', osf.utils.datetime_aware_jsonfield.DateTimeAwareJSONField(blank=True, default=dict, encoder=osf.utils.datetime_aware_jsonfield.DateTimeAwareJSONEncoder)),
('owner', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='addons_s3compatsigv4_user_settings', to=settings.AUTH_USER_MODEL)),
],
options={
'abstract': False,
},
bases=(models.Model, osf.models.base.QuerySetExplainMixin),
),
migrations.AddField(
model_name='nodesettings',
name='user_settings',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='addons_s3compatsigv4.UserSettings'),
),
]
Empty file.
Loading
Loading