Skip to content
Open
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
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