Skip to content

Commit

Permalink
working implementation of surf research drive storage
Browse files Browse the repository at this point in the history
  • Loading branch information
trbKnl committed Sep 11, 2024
1 parent 4fb6a19 commit bf33fcf
Show file tree
Hide file tree
Showing 14 changed files with 213 additions and 7 deletions.
2 changes: 1 addition & 1 deletion core/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ config :core, :version, System.get_env("VERSION", "dev")

config :core, :assignment, external_panels: ~w(liss ioresearch generic)

config :core, :storage, services: ~w(builtin yoda)
config :core, :storage, services: ~w(builtin yoda surfresearchdrive)

config :core, BankingClient,
host: 'localhost',
Expand Down
4 changes: 4 additions & 0 deletions core/priv/gettext/en/LC_MESSAGES/eyra-enums.po
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,10 @@ msgstr "Azure Blob"
msgid "storage_service_ids.yoda"
msgstr "Yoda"

#, elixir-autogen, elixir-format
msgid "storage_service_ids.surfresearchdrive"
msgstr "Surf Research Drive"

#, elixir-autogen, elixir-format, fuzzy
msgid "storage_service_ids.aws"
msgstr "Amazon S3"
Expand Down
20 changes: 20 additions & 0 deletions core/priv/gettext/en/LC_MESSAGES/eyra-storage.po
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,22 @@ msgstr "Folder url"
msgid "yoda.user.label"
msgstr "E-mail"

#, elixir-autogen, elixir-format
msgid "surfresearchdrive.user.label"
msgstr "E-Mail"

#, elixir-autogen, elixir-format
msgid "surfresearchdrive.password.label"
msgstr "WebDAV token"

#, elixir-autogen, elixir-format
msgid "surfresearchdrive.url.label"
msgstr "WebDAV Url"

#, elixir-autogen, elixir-format
msgid "surfresearchdrive.folder.label"
msgstr "Folder name"

#, elixir-autogen, elixir-format
msgid "aws.annotation"
msgstr "<div>Use Amazon S3 storage. More information: <a href=\"https://aws.amazon.com/s3\">https://aws.amazon.com/s3</a></div>"
Expand All @@ -79,6 +95,10 @@ msgstr "<div>More information: <a href=\"https://www.centerdata.nl\">https://www
msgid "yoda.annotation"
msgstr "<div>Use Yoda, a research data management service developed at Utrecht University. <br> More information: <a href=\"https://www.uu.nl/en/research/yoda\">https://www.uu.nl/en/research/yoda</a></div>"

#, elixir-autogen, elixir-format
msgid "surfresearchdrive.annotation"
msgstr "<div>Use Surf Research Drive, a storage solution developed by Surf offered by Universities in the Netherlands. <br> More information: <a href=\"https://www.surf.nl/en/services/research-drive\">https://www.surf.nl/en/services/research-drive</a></div>"

#, elixir-autogen, elixir-format
msgid "project.item.tag"
msgstr "Storage"
Expand Down
4 changes: 4 additions & 0 deletions core/priv/gettext/eyra-enums.pot
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,10 @@ msgstr ""
msgid "storage_service_ids.yoda"
msgstr ""

#, elixir-autogen, elixir-format
msgid "storage_service_ids.surfresearchdrive"
msgstr ""

#, elixir-autogen, elixir-format
msgid "storage_service_ids.aws"
msgstr ""
Expand Down
20 changes: 20 additions & 0 deletions core/priv/gettext/eyra-storage.pot
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,22 @@ msgstr ""
msgid "yoda.user.label"
msgstr ""

#, elixir-autogen, elixir-format
msgid "surfresearchdrive.user.label"
msgstr ""

#, elixir-autogen, elixir-format
msgid "surfresearchdrive.password.label"
msgstr ""

#, elixir-autogen, elixir-format
msgid "surfresearchdrive.url.label"
msgstr ""

#, elixir-autogen, elixir-format
msgid "surfresearchdrive.folder.label"
msgstr ""

#, elixir-autogen, elixir-format
msgid "aws.annotation"
msgstr ""
Expand All @@ -71,6 +87,10 @@ msgstr ""
msgid "builtin.annotation"
msgstr ""

#, elixir-autogen, elixir-format
msgid "surfresearchdrive.annotation"
msgstr ""

#, elixir-autogen, elixir-format
msgid "centerdata.annotation"
msgstr ""
Expand Down
14 changes: 13 additions & 1 deletion core/priv/repo/migrations/20231025125051_add_storage.exs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ defmodule Core.Repo.Migrations.AddStorage do
timestamps()
end

create table(:storage_endpoints_surfresearchdrive) do
add(:user, :string)
add(:password, :string)
add(:url, :string)
add(:folder, :string)

timestamps()
end

create table(:storage_endpoints) do
add(:aws_id, references(:storage_endpoints_aws, on_delete: :nilify_all), null: true)
add(:azure_id, references(:storage_endpoints_azure, on_delete: :nilify_all), null: true)
Expand All @@ -42,6 +51,7 @@ defmodule Core.Repo.Migrations.AddStorage do
)

add(:yoda_id, references(:storage_endpoints_yoda, on_delete: :nilify_all), null: true)
add(:surfresearchdrive_id, references(:storage_endpoints_surfresearchdrive, on_delete: :nilify_all), null: true)
timestamps()
end

Expand All @@ -51,7 +61,8 @@ defmodule Core.Repo.Migrations.AddStorage do
2 > CASE WHEN aws_id IS NULL THEN 0 ELSE 1 END +
CASE WHEN azure_id IS NULL THEN 0 ELSE 1 END +
CASE WHEN centerdata_id IS NULL THEN 0 ELSE 1 END +
CASE WHEN yoda_id IS NULL THEN 0 ELSE 1 END
CASE WHEN yoda_id IS NULL THEN 0 ELSE 1 END +
CASE WHEN surfresearchdrive_id IS NULL THEN 0 ELSE 1 END
"""
)
)
Expand All @@ -76,5 +87,6 @@ defmodule Core.Repo.Migrations.AddStorage do
drop(table(:storage_endpoints_centerdata))
drop(table(:storage_endpoints_azure))
drop(table(:storage_endpoints_aws))
drop(table(:storage_endpoints_surfresearchdrive))
end
end
10 changes: 7 additions & 3 deletions core/systems/storage/_private.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ defmodule Systems.Storage.Private do
def build_special(:yoda), do: %Storage.Yoda.EndpointModel{}
def build_special(:aws), do: %Storage.AWS.EndpointModel{}
def build_special(:azure), do: %Storage.Azure.EndpointModel{}
def build_special(:surfresearchdrive), do: %Storage.SurfResearchDrive.EndpointModel{}

def special_info(%Storage.EndpointModel{} = endpoint) do
endpoint
Expand All @@ -26,6 +27,7 @@ defmodule Systems.Storage.Private do
def special_info(%Storage.Yoda.EndpointModel{}), do: {:yoda, Storage.Yoda.Backend}
def special_info(%Storage.AWS.EndpointModel{}), do: {:aws, Storage.AWS.Backend}
def special_info(%Storage.Azure.EndpointModel{}), do: {:azure, Storage.Azure.Backend}
def special_info(%Storage.SurfResearchDrive.EndpointModel{}), do: {:azure, Storage.SurfResearchDrive.Backend}

@spec storage_info(any()) ::
{:error, {:storage_info, :not_available}}
Expand All @@ -35,17 +37,19 @@ defmodule Systems.Storage.Private do
| Systems.Storage.Azure.Backend
| Systems.Storage.BuiltIn.Backend
| Systems.Storage.Centerdata.Backend
| Systems.Storage.Yoda.Backend,
| Systems.Storage.Yoda.Backend
| Systems.Storage.SurfResearchDrive.Backend,
endpoint: %{
:__struct__ =>
Systems.Storage.AWS.EndpointModel
| Systems.Storage.Azure.EndpointModel
| Systems.Storage.BuiltIn.EndpointModel
| Systems.Storage.Centerdata.EndpointModel
| Systems.Storage.Yoda.EndpointModel,
| Systems.Storage.Yoda.EndpointModel
| Systems.Storage.SurfResearchDrive.EndpointModel,
optional(any()) => any()
},
key: :aws | :azure | :builtin | :centerdata | :yoda
key: :aws | :azure | :builtin | :centerdata | :yoda | :surfresearchdrive
}
def storage_info(storage_endpoint, %{external_panel: external_panel}) do
if special = Storage.EndpointModel.special(storage_endpoint) do
Expand Down
5 changes: 5 additions & 0 deletions core/systems/storage/_public.ex
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ defmodule Systems.Storage.Public do
|> Storage.Azure.EndpointModel.changeset(attrs)
end

defp prepare_endpoint_special(:surfresearchdrive, attrs) do
%Storage.SurfResearchDrive.EndpointModel{}
|> Storage.SurfResearchDrive.EndpointModel.changeset(attrs)
end

def store(
%Storage.EndpointModel{id: endpoint_id} = endpoint,
%{key: key, backend: backend, special: special},
Expand Down
1 change: 1 addition & 0 deletions core/systems/storage/endpoint_form.ex
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ defmodule Systems.Storage.EndpointForm do
:centerdata -> dgettext("eyra-storage", "centerdata.annotation")
:aws -> dgettext("eyra-storage", "aws.annotation")
:azure -> dgettext("eyra-storage", "azure.annotation")
:surfresearchdrive -> dgettext("eyra-storage", "azure.annotation")
end

annotation_title = Storage.ServiceIds.translate(special_type)
Expand Down
3 changes: 2 additions & 1 deletion core/systems/storage/endpoint_model.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ defmodule Systems.Storage.EndpointModel do
belongs_to(:centerdata, Storage.Centerdata.EndpointModel, on_replace: :delete)
belongs_to(:aws, Storage.AWS.EndpointModel, on_replace: :delete)
belongs_to(:azure, Storage.Azure.EndpointModel, on_replace: :delete)
belongs_to(:surfresearchdrive, Storage.SurfResearchDrive.EndpointModel, on_replace: :delete)

timestamps()
end

@fields ~w()a
@required_fields @fields
@special_fields ~w(builtin yoda centerdata aws azure)a
@special_fields ~w(builtin yoda centerdata aws azure surfresearchdrive)a

@spec changeset(
{map(), map()}
Expand Down
2 changes: 1 addition & 1 deletion core/systems/storage/service_ids.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ defmodule Systems.Storage.ServiceIds do
Defines list of supported storage services
"""
use Core.Enums.Base,
{:storage_service_ids, [:builtin, :yoda, :aws, :azure]}
{:storage_service_ids, [:builtin, :yoda, :aws, :azure, :surfresearchdrive]}
end
61 changes: 61 additions & 0 deletions core/systems/storage/surfresearchdrive/backend.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
defmodule Systems.Storage.SurfResearchDrive.Backend do
@behaviour Systems.Storage.Backend

alias Systems.Storage.SurfResearchDrive

require Logger

def store(
%{
"user" => username,
"password" => password,
"url" => url,
"folder" => folder
} = _endpoint,
data,
meta_data
) do
filename = filename(meta_data)
file_url = url([url, folder, filename])

credentials = Base.encode64("#{username}:#{password}")

headers = [
{"Authorization", "Basic #{credentials}"}
]

case HTTPoison.put(file_url, data, headers) do
{:ok, %{status_code: 201}} ->
:ok

{_, %{status_code: status_code, body: body}} ->
{:error, "status_code=#{status_code},message=#{body}"}

{:error, error} ->
Logger.error("[SurfResearchDrive.Backend] #{error}")
{:error, error}
end
end

def list_files(_endpoint) do
Logger.error("Not yet implemented: list_files/1")
{:error, :not_implemented}
end

def delete_files(_endpoint) do
Logger.error("Not yet implemented: delete_files/1")
{:error, :not_implemented}
end

def connected?(_), do: false

defp filename(%{"identifier" => identifier}) do
identifier
|> Enum.map_join("_", fn [key, value] -> "#{key}-#{value}" end)
|> then(&"#{&1}.json")
end

defp url(components) do
URI.encode(Enum.join(components, "/"))
end
end
27 changes: 27 additions & 0 deletions core/systems/storage/surfresearchdrive/endpoint_form.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule Systems.Storage.SurfResearchDrive.EndpointForm do
use Systems.Storage.EndpointForm.Helper, Systems.Storage.SurfResearchDrive.EndpointModel

import Systems.Storage.Html

@impl true
def render(assigns) do
~H"""
<div>
<.form id={"#{@id}_surfresearchdrive_endpoint_form"} :let={form} for={@changeset} phx-change="change" phx-submit="save" phx-target={@myself}>
<div class="flex flex-col gap-4">
<.text_input form={form} field={:user} label_text={dgettext("eyra-storage", "surfresearchdrive.user.label")} debounce="0" reserve_error_space={false} />
<.password_input form={form} field={:password} label_text={dgettext("eyra-storage", "surfresearchdrive.password.label")} debounce="0" reserve_error_space={false} />
<.text_input form={form} field={:url} label_text={dgettext("eyra-storage", "surfresearchdrive.url.label")} placeholder="https://{url}/remote.php/webdav/>" debounce="0" reserve_error_space={false} />
<.text_input form={form} field={:folder} label_text={dgettext("eyra-storage", "surfresearchdrive.folder.label")} debounce="0" reserve_error_space={false} />
<div class="flex flex-row gap-4 items-center mt-2">
<Button.dynamic_bar buttons={[@submit_button]} />
<%= if @show_status do %>
<.account_status connected?={@connected?}/>
<% end %>
</div>
</div>
</.form>
</div>
"""
end
end
47 changes: 47 additions & 0 deletions core/systems/storage/surfresearchdrive/endpoint_model.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
defmodule Systems.Storage.SurfResearchDrive.EndpointModel do
use Ecto.Schema
use Frameworks.Utility.Schema

import Ecto.Changeset
alias Systems.Storage.SurfResearchDrive

@fields ~w(user password url folder)a
@required_fields @fields

@derive {Jason.Encoder, only: @fields}
@derive {Inspect, except: [:user, :password]}
schema "storage_endpoints_surfresearchdrive" do
field(:user, :string)
field(:password, :string)
field(:url, :string)
field(:folder, :string)

timestamps()
end

def changeset(endpoint, params) do
endpoint
|> cast(params, @fields)
end

def validate(changeset) do
changeset
|> validate_required(@required_fields)
end

def ready?(endpoint) do
changeset =
changeset(endpoint, %{})
|> validate()

changeset.valid?()
end

def preload_graph(:down), do: []

defimpl Frameworks.Concept.ContentModel do
alias Systems.Storage.SurfResearchDrive
def form(_), do: SurfResearchDrive.EndpointForm
def ready?(endpoint), do: SurfResearchDrive.EndpointModel.ready?(endpoint)
end
end

0 comments on commit bf33fcf

Please sign in to comment.