Skip to content

Commit 712f460

Browse files
authored
refactor: rework file transfer to use presigned URLs (#1255)
- In the previous code, file uploads and downloads were handled by the backend. Now, the backend only generates presigned URLs for uploads and downloads, and the actual file transfer will be done directly between the client and the storage Signed-off-by: ArnelaL <arnela.lisic@secomind.com>
1 parent 1e728ad commit 712f460

34 files changed

+1212
-3892
lines changed

backend/config/runtime.exs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#
22
# This file is part of Edgehog.
33
#
4-
# Copyright 2021 - 2025 SECO Mind Srl
4+
# Copyright 2021 - 2026 SECO Mind Srl
55
#
66
# Licensed under the Apache License, Version 2.0 (the "License");
77
# you may not use this file except in compliance with the License.
@@ -140,6 +140,17 @@ if config_env() in [:prod, :test] do
140140
:prod -> edgehog_enable_s3_storage?
141141
end
142142

143+
# Parse the public/external S3 host from S3_ASSET_HOST so that presigned URL
144+
# generation can embed the correct external address. The old Waffle upload path
145+
# continues to use :ex_aws config
146+
# (S3_HOST / S3_SCHEME / S3_PORT, i.e. the internal address) unaffected.
147+
s3_presign_host_config =
148+
if storage_type != "azure" do
149+
asset_host = s3.asset_host || "http://localhost:9000"
150+
uri = URI.parse(asset_host)
151+
%{scheme: uri.scheme <> "://", host: uri.host, port: uri.port || 80}
152+
end
153+
143154
config :azurex, Azurex.Blob.Config,
144155
api_url: azure_api_url,
145156
default_container: azure.container,
@@ -149,7 +160,10 @@ if config_env() in [:prod, :test] do
149160
# Enable uploaders only when the S3 storage has been configured
150161
config :edgehog,
151162
enable_s3_storage?: edgehog_enable_s3_storage?,
152-
max_upload_size_bytes: max_upload_size_bytes
163+
max_upload_size_bytes: max_upload_size_bytes,
164+
storage_type: String.to_atom(storage_type),
165+
storage_bucket: waffle_bucket,
166+
s3_presign_host_config: s3_presign_host_config
153167

154168
config :ex_aws, :s3,
155169
scheme: s3.scheme,

backend/config/test.exs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,6 @@ config :edgehog, :astarte_trigger_data_layer, Edgehog.Astarte.Trigger.MockDataLa
132132
config :edgehog, :astarte_wifi_scan_result_module, Edgehog.Astarte.Device.WiFiScanResultMock
133133
config :edgehog, :base_images_storage_module, Edgehog.BaseImages.StorageMock
134134
config :edgehog, :container_reconciler, Edgehog.Containers.ReconcilerMock
135-
config :edgehog, :files_ephemeral_file_module, Edgehog.Files.EphemeralFileMock
136-
config :edgehog, :files_storage_module, Edgehog.Files.StorageMock
137135
config :edgehog, :os_management_ephemeral_image_module, Edgehog.OSManagement.EphemeralImageMock
138136
config :edgehog, :reconciler_module, Edgehog.Tenants.ReconcilerMock
139137

backend/lib/edgehog/files/ephemeral_file/ephemeral_file.ex

Lines changed: 0 additions & 45 deletions
This file was deleted.

backend/lib/edgehog/files/file/bucket_storage.ex

Lines changed: 0 additions & 63 deletions
This file was deleted.

backend/lib/edgehog/files/file/changes/handle_file_deletion.ex renamed to backend/lib/edgehog/files/file/changes/delete_file.ex

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,12 @@
1818
# SPDX-License-Identifier: Apache-2.0
1919
#
2020

21-
defmodule Edgehog.Files.File.Changes.HandleFileDeletion do
21+
defmodule Edgehog.Files.File.Changes.DeleteFile do
2222
@moduledoc """
23-
Ash change to handle file deletion after a file record is deleted.
23+
Deletes a file from the storage backend that was uploaded via a presigned URL.
2424
"""
25-
2625
use Ash.Resource.Change
2726

28-
alias Edgehog.Files.File.BucketStorage
29-
30-
require Logger
31-
32-
@storage_module Application.compile_env(
33-
:edgehog,
34-
:files_storage_module,
35-
BucketStorage
36-
)
37-
3827
@impl Ash.Resource.Change
3928
def change(%Ash.Changeset{valid?: false} = changeset, _opts, _context), do: changeset
4029

@@ -45,7 +34,13 @@ defmodule Edgehog.Files.File.Changes.HandleFileDeletion do
4534
end
4635

4736
defp delete_old_file({:ok, file} = result) do
48-
_ = @storage_module.delete(file)
37+
tenant_id = file.tenant_id
38+
repository_id = file.repository_id
39+
filename = file.name
40+
41+
file_path = "uploads/tenants/#{tenant_id}/repositories/#{repository_id}/files/#{filename}"
42+
43+
_ = Edgehog.Storage.delete(file_path)
4944

5045
result
5146
end

backend/lib/edgehog/files/file/changes/handle_file_upload.ex

Lines changed: 0 additions & 106 deletions
This file was deleted.

backend/lib/edgehog/files/file/file.ex

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ defmodule Edgehog.Files.File do
2525
extensions: [AshGraphql.Resource]
2626

2727
alias Edgehog.Files.File.Changes
28+
alias Edgehog.Files.File.ManualActions
2829

2930
graphql do
3031
type :file
@@ -37,20 +38,13 @@ defmodule Edgehog.Files.File do
3738
description "Create a new file by uploading it to the storage."
3839
primary? true
3940

40-
accept [:name, :mode, :user_id, :group_id]
41+
accept [:name, :size, :digest, :mode, :user_id, :group_id, :url]
4142

4243
argument :repository_id, :uuid do
4344
description "The ID of the repository this file will belong to."
4445
allow_nil? false
4546
end
4647

47-
argument :file, Edgehog.Types.Upload do
48-
description "The file to upload, which will be stored in the bucket."
49-
allow_nil? false
50-
end
51-
52-
change Changes.HandleFileUpload
53-
5448
change manage_relationship(:repository_id, :repository, type: :append)
5549
end
5650

@@ -65,16 +59,28 @@ defmodule Edgehog.Files.File do
6559
end
6660

6761
destroy :destroy do
68-
description "Deletes a file and its stored content."
62+
description "Deletes a file"
6963
primary? true
70-
71-
# Needed because HandleFileDeletion is not atomic
7264
require_atomic? false
7365

74-
change Changes.HandleFileDeletion
66+
change Changes.DeleteFile
7567
end
7668

7769
destroy :destroy_fixture
70+
71+
action :create_presigned_url, :map do
72+
argument :filename, :string, allow_nil?: false
73+
argument :repository_id, :uuid, allow_nil?: false
74+
75+
run ManualActions.CreatePresignedUrl
76+
end
77+
78+
action :read_presigned_url, :map do
79+
argument :filename, :string, allow_nil?: false
80+
argument :repository_id, :uuid, allow_nil?: false
81+
82+
run ManualActions.ReadPresignedUrl
83+
end
7884
end
7985

8086
attributes do
@@ -137,6 +143,10 @@ defmodule Edgehog.Files.File do
137143
end
138144
end
139145

146+
identities do
147+
identity :unique_repository_file, [:name, :repository_id]
148+
end
149+
140150
postgres do
141151
table "files"
142152
repo Edgehog.Repo

0 commit comments

Comments
 (0)