Skip to content

Commit

Permalink
working implementation of surf research drive storage
Browse files Browse the repository at this point in the history
Formatted code

added the possibility to encrypt donations

Formatted code

made field optional
  • Loading branch information
trbKnl committed Oct 8, 2024
1 parent 4fb6a19 commit c4ef514
Show file tree
Hide file tree
Showing 19 changed files with 275 additions and 12 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
2 changes: 1 addition & 1 deletion core/config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ if config_env() == :prod do

# CHANGE BY NIEK
config :core, GoogleSignIn,
redirect_uri: "NOT RELAVANT ANYMORE",
redirect_uri: "NOT RELAVANT ANYMORE",
client_id: "NOT RELEVANT ANYMORE",
client_secret: "NOT RELEVANT ANYMORE"

Expand Down
4 changes: 2 additions & 2 deletions core/frameworks/pixel/components/button_face.ex
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,15 @@ defmodule Frameworks.Pixel.Button.Face do
attr(:icon, :atom, required: true)
attr(:size, :atom, default: :wide)

#def menu_home(assigns) do
# def menu_home(assigns) do
# ~H"""
# <div class={"flex flex-row items-center justify-start rounded-full focus:outline-none h-12"}>
# <div class="flex flex-col items-center justify-center">
# <Icon.menu_home name={@icon} size={@size} />
# </div>
# </div>
# """
#end
# end

def menu_home(assigns) do
~H"""
Expand Down
1 change: 0 additions & 1 deletion core/lib/google_sign_in/plug.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ defmodule GoogleSignIn.PlugUtils do
end
end


defmodule GoogleSignIn.AuthorizePlug do
@moduledoc """
This controller manages the OpenID Connect flow with SurfConext.
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
24 changes: 24 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,26 @@ 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 "surfresearchdrive.passphrase.label"
msgstr "Passphrase for encryption"

#, 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 +99,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
24 changes: 24 additions & 0 deletions core/priv/gettext/eyra-storage.pot
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,26 @@ 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 "surfresearchdrive.passphrase.label"
msgstr ""

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

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

#, elixir-autogen, elixir-format
msgid "centerdata.annotation"
msgstr ""
Expand Down
15 changes: 14 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,16 @@ 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)
add(:passphrase, :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 +52,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 +62,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 +88,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
12 changes: 9 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 @@ -27,6 +28,9 @@ defmodule Systems.Storage.Private do
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 +39,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
69 changes: 69 additions & 0 deletions core/systems/storage/surfresearchdrive/backend.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
defmodule Systems.Storage.SurfResearchDrive.Backend do
@behaviour Systems.Storage.Backend

alias Systems.Storage.SurfResearchDrive.Encryption

require Logger

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

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

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

data =
if passphrase != nil do
Encryption.encrypt(data, passphrase)
else
data
end

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} ->
IO.inspect(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
41 changes: 41 additions & 0 deletions core/systems/storage/surfresearchdrive/encryption.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
defmodule Systems.Storage.SurfResearchDrive.Encryption do
@moduledoc """
Documentation for `Systems.Storage.SurfResearchDrive.Encryption`.
"""

@doc """
Encrypt file with AES-256-CBC
The hashed passphrase is the encryption key
The hash function is there to guarantee the key consists of 256 bits
The hasing function does not offer protection.
If you know the hash or the passphrase you can decrypt the data
Decryption can be done with:
openssl enc -d -aes-256-cbc -in <(tail -c +17 file.enc) \
-out file.txt \
-K <sha256 of passphrase> \
-iv <base16 encode of first 16 bytes of file.enc>
"""
def encrypt(content, passphrase) do
# generate key and iv
key = :crypto.hash(:sha256, passphrase)
iv = :crypto.strong_rand_bytes(16)

padded_content = pad(content, 16)

# Encrypt content
cipher_text = :crypto.crypto_one_time(:aes_256_cbc, key, iv, padded_content, true)

# Prepend IV and write the result
iv <> cipher_text
end

@doc """
Applies PKCS7 padding to the given binary.
"""
def pad(data, block_size) do
padding_size = block_size - rem(byte_size(data), block_size)
data <> :binary.copy(<<padding_size>>, padding_size)
end
end
Loading

0 comments on commit c4ef514

Please sign in to comment.