mirror of
https://github.com/eduardolat/pgbackweb.git
synced 2026-01-23 21:19:31 -06:00
Fix download button to support local backups
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
package executions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/eduardolat/pgbackweb/internal/database/dbgen"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func (s *Service) GetExecutionDownloadLink(
|
||||
ctx context.Context, executionID uuid.UUID,
|
||||
) (string, error) {
|
||||
data, err := s.dbgen.ExecutionsServiceGetDownloadLinkData(
|
||||
ctx, dbgen.ExecutionsServiceGetDownloadLinkDataParams{
|
||||
ExecutionID: executionID,
|
||||
DecryptionKey: *s.env.PBW_ENCRYPTION_KEY,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if !data.Path.Valid {
|
||||
return "", fmt.Errorf("execution has no file associated")
|
||||
}
|
||||
|
||||
return s.ints.StorageClient.S3GetDownloadLink(
|
||||
data.DecryptedAccessKey, data.DecryptedSecretKey, data.Region,
|
||||
data.Endpoint, data.BucketName, data.Path.String, time.Hour*12,
|
||||
)
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
-- name: ExecutionsServiceGetDownloadLinkData :one
|
||||
SELECT
|
||||
executions.path AS path,
|
||||
destinations.bucket_name AS bucket_name,
|
||||
destinations.region AS region,
|
||||
destinations.endpoint AS endpoint,
|
||||
pgp_sym_decrypt(destinations.access_key, sqlc.arg('decryption_key')::TEXT) AS decrypted_access_key,
|
||||
pgp_sym_decrypt(destinations.secret_key, sqlc.arg('decryption_key')::TEXT) AS decrypted_secret_key
|
||||
FROM executions
|
||||
JOIN backups ON backups.id = executions.backup_id
|
||||
JOIN destinations ON destinations.id = backups.destination_id
|
||||
WHERE executions.id = @execution_id;
|
||||
@@ -0,0 +1,47 @@
|
||||
package executions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/eduardolat/pgbackweb/internal/database/dbgen"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// GetExecutionDownloadLinkOrPath returns a download link for the file associated
|
||||
// with the given execution. If the execution is stored locally, the link will
|
||||
// be a file path.
|
||||
//
|
||||
// Returns a boolean indicating if the file is locally stored and the download
|
||||
// link/path.
|
||||
func (s *Service) GetExecutionDownloadLinkOrPath(
|
||||
ctx context.Context, executionID uuid.UUID,
|
||||
) (bool, string, error) {
|
||||
data, err := s.dbgen.ExecutionsServiceGetDownloadLinkOrPathData(
|
||||
ctx, dbgen.ExecutionsServiceGetDownloadLinkOrPathDataParams{
|
||||
ExecutionID: executionID,
|
||||
DecryptionKey: *s.env.PBW_ENCRYPTION_KEY,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
|
||||
if !data.Path.Valid {
|
||||
return false, "", fmt.Errorf("execution has no file associated")
|
||||
}
|
||||
|
||||
if data.IsLocal {
|
||||
return true, s.ints.StorageClient.LocalGetFullPath(data.Path.String), nil
|
||||
}
|
||||
|
||||
link, err := s.ints.StorageClient.S3GetDownloadLink(
|
||||
data.DecryptedAccessKey, data.DecryptedSecretKey, data.Region.String,
|
||||
data.Endpoint.String, data.BucketName.String, data.Path.String, time.Hour*12,
|
||||
)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
return false, link, nil
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
-- name: ExecutionsServiceGetDownloadLinkOrPathData :one
|
||||
SELECT
|
||||
executions.path AS path,
|
||||
backups.is_local AS is_local,
|
||||
destinations.bucket_name AS bucket_name,
|
||||
destinations.region AS region,
|
||||
destinations.endpoint AS endpoint,
|
||||
destinations.endpoint as destination_endpoint,
|
||||
(
|
||||
CASE WHEN destinations.access_key IS NOT NULL
|
||||
THEN pgp_sym_decrypt(destinations.access_key, sqlc.arg('decryption_key')::TEXT)
|
||||
ELSE ''
|
||||
END
|
||||
) AS decrypted_access_key,
|
||||
(
|
||||
CASE WHEN destinations.secret_key IS NOT NULL
|
||||
THEN pgp_sym_decrypt(destinations.secret_key, sqlc.arg('decryption_key')::TEXT)
|
||||
ELSE ''
|
||||
END
|
||||
) AS decrypted_secret_key
|
||||
FROM executions
|
||||
INNER JOIN backups ON backups.id = executions.backup_id
|
||||
LEFT JOIN destinations ON destinations.id = backups.destination_id
|
||||
WHERE executions.id = @execution_id;
|
||||
@@ -1,11 +1,13 @@
|
||||
package executions
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
|
||||
lucide "github.com/eduardolat/gomponents-lucide"
|
||||
"github.com/eduardolat/pgbackweb/internal/database/dbgen"
|
||||
"github.com/eduardolat/pgbackweb/internal/util/timeutil"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/component"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/htmx"
|
||||
"github.com/google/uuid"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/maragudk/gomponents"
|
||||
@@ -17,17 +19,21 @@ func (h *handlers) downloadExecutionHandler(c echo.Context) error {
|
||||
|
||||
executionID, err := uuid.Parse(c.Param("executionID"))
|
||||
if err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
return c.String(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
link, err := h.servs.ExecutionsService.GetExecutionDownloadLink(
|
||||
isLocal, link, err := h.servs.ExecutionsService.GetExecutionDownloadLinkOrPath(
|
||||
ctx, executionID,
|
||||
)
|
||||
if err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
return c.String(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return htmx.RespondRedirect(c, link)
|
||||
if isLocal {
|
||||
return c.Attachment(link, filepath.Base(link))
|
||||
}
|
||||
|
||||
return c.Redirect(http.StatusFound, link)
|
||||
}
|
||||
|
||||
func showExecutionButton(
|
||||
@@ -114,9 +120,9 @@ func showExecutionButton(
|
||||
html.Div(
|
||||
html.Class("flex justify-end items-center space-x-2"),
|
||||
deleteExecutionButton(execution.ID),
|
||||
html.Button(
|
||||
htmx.HxGet("/dashboard/executions/"+execution.ID.String()+"/download"),
|
||||
htmx.HxDisabledELT("this"),
|
||||
html.A(
|
||||
html.Href("/dashboard/executions/"+execution.ID.String()+"/download"),
|
||||
html.Target("_blank"),
|
||||
html.Class("btn btn-primary"),
|
||||
component.SpanText("Download"),
|
||||
lucide.Download(),
|
||||
|
||||
Reference in New Issue
Block a user