Skip to content

Commit

Permalink
feat(ui): support for editing pins and description (#1748)
Browse files Browse the repository at this point in the history
  • Loading branch information
jkowalski committed Feb 12, 2022
1 parent 6ae46a4 commit 512dceb
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 1 deletion.
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -88,7 +88,7 @@ require (
github.com/googleapis/gax-go/v2 v2.1.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kopia/htmluibuild v0.0.0-20220211164311-3c58cff936c2
github.com/kopia/htmluibuild v0.0.0-20220212024129-c944ece3b4d0
github.com/kr/fs v0.1.0 // indirect
github.com/mattn/go-ieproxy v0.0.1 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Expand Up @@ -406,6 +406,10 @@ github.com/kopia/htmluibuild v0.0.0-20220208062920-a1d47d1e3096 h1:rbrPWsO4OTT2c
github.com/kopia/htmluibuild v0.0.0-20220208062920-a1d47d1e3096/go.mod h1:eWer4rx9P8lJo2eKc+Q7AZ1dE1x1hJNdkbDFPzMu1Hw=
github.com/kopia/htmluibuild v0.0.0-20220211164311-3c58cff936c2 h1:8EzPQNPLdwH3camd8l6/gHpSRS43cKqd38FKebcXbrE=
github.com/kopia/htmluibuild v0.0.0-20220211164311-3c58cff936c2/go.mod h1:eWer4rx9P8lJo2eKc+Q7AZ1dE1x1hJNdkbDFPzMu1Hw=
github.com/kopia/htmluibuild v0.0.0-20220212022637-f4a448ee180a h1:FugmgYM3pW92AjfMJsGZArtF4TROg5rDKLalXXk/50E=
github.com/kopia/htmluibuild v0.0.0-20220212022637-f4a448ee180a/go.mod h1:eWer4rx9P8lJo2eKc+Q7AZ1dE1x1hJNdkbDFPzMu1Hw=
github.com/kopia/htmluibuild v0.0.0-20220212024129-c944ece3b4d0 h1:jdyUUH53CP2G30w4endw1eXE3GmI4km2hmK1ZZ75fIg=
github.com/kopia/htmluibuild v0.0.0-20220212024129-c944ece3b4d0/go.mod h1:eWer4rx9P8lJo2eKc+Q7AZ1dE1x1hJNdkbDFPzMu1Hw=
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
Expand Down
46 changes: 46 additions & 0 deletions internal/server/api_snapshots.go
Expand Up @@ -128,6 +128,52 @@ func (s *Server) handleDeleteSnapshots(ctx context.Context, r *http.Request, bod
return &serverapi.Empty{}, nil
}

func (s *Server) handleEditSnapshots(ctx context.Context, r *http.Request, body []byte) (interface{}, *apiError) {
var req serverapi.EditSnapshotsRequest

if err := json.Unmarshal(body, &req); err != nil {
return nil, requestError(serverapi.ErrorMalformedRequest, "malformed request")
}

var snaps []*serverapi.Snapshot

if err := repo.WriteSession(ctx, s.rep, repo.WriteSessionOptions{
Purpose: "EditSnapshots",
}, func(ctx context.Context, w repo.RepositoryWriter) error {
for _, id := range req.Snapshots {
snap, err := snapshot.LoadSnapshot(ctx, w, id)
if err != nil {
return errors.Wrap(err, "unable to load snapshot")
}

changed := false

if snap.UpdatePins(req.AddPins, req.RemovePins) {
changed = true
}

if req.NewDescription != nil {
changed = true
snap.Description = *req.NewDescription
}

if changed {
if err := snapshot.UpdateSnapshot(ctx, w, snap); err != nil {
return errors.Wrap(err, "error updating snapshot")
}
}

snaps = append(snaps, convertSnapshotManifest(snap))
}

return nil
}); err != nil {
return nil, internalServerError(err)
}

return snaps, nil
}

func uniqueSnapshots(rows []*serverapi.Snapshot) []*serverapi.Snapshot {
result := []*serverapi.Snapshot{}
resultByRootEntry := map[string]*serverapi.Snapshot{}
Expand Down
78 changes: 78 additions & 0 deletions internal/server/api_snapshots_test.go
Expand Up @@ -177,3 +177,81 @@ func TestListAndDeleteSnapshots(t *testing.T) {

require.Empty(t, sourceList.Sources)
}

func TestEditSnapshots(t *testing.T) {
ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)

si1 := localSource(env, "/dummy/path")

var id11 manifest.ID

require.NoError(t, repo.WriteSession(ctx, env.Repository, repo.WriteSessionOptions{Purpose: "Test"}, func(ctx context.Context, w repo.RepositoryWriter) error {
u := snapshotfs.NewUploader(w)

dir1 := mockfs.NewDirectory()

dir1.AddFile("file1", []byte{1, 2, 3}, 0o644)
dir1.AddFile("file2", []byte{1, 2, 4}, 0o644)

man11, err := u.Upload(ctx, dir1, nil, si1)
require.NoError(t, err)
id11, err = snapshot.SaveSnapshot(ctx, w, man11)
require.NoError(t, err)

return nil
}))

srvInfo := startServer(t, env, false)

cli, err := apiclient.NewKopiaAPIClient(apiclient.Options{
BaseURL: srvInfo.BaseURL,
TrustedServerCertificateFingerprint: srvInfo.TrustedServerCertificateFingerprint,
Username: testUIUsername,
Password: testUIPassword,
})

require.NoError(t, err)
require.NoError(t, cli.FetchCSRFTokenForTesting(ctx))

resp, err := serverapi.ListSnapshots(ctx, cli, si1, true)
require.NoError(t, err)

require.Len(t, resp.Snapshots, 1)

var (
updated []*serverapi.Snapshot

newDesc1 = "desc1"
newDesc2 = "desc2"
)

require.NoError(t, cli.Post(ctx, "snapshots/edit", &serverapi.EditSnapshotsRequest{
Snapshots: []manifest.ID{id11},
AddPins: []string{"pin1", "pin2"},
NewDescription: &newDesc1,
}, &updated))

require.Len(t, updated, 1)
require.EqualValues(t, []string{"pin1", "pin2"}, updated[0].Pins)
require.EqualValues(t, newDesc1, updated[0].Description)

require.NoError(t, cli.Post(ctx, "snapshots/edit", &serverapi.EditSnapshotsRequest{
Snapshots: []manifest.ID{updated[0].ID},
AddPins: []string{"pin3"},
RemovePins: []string{"pin1"},
NewDescription: &newDesc2,
}, &updated))

require.Len(t, updated, 1)
require.EqualValues(t, []string{"pin2", "pin3"}, updated[0].Pins)
require.EqualValues(t, newDesc2, updated[0].Description)

require.NoError(t, cli.Post(ctx, "snapshots/edit", &serverapi.EditSnapshotsRequest{
Snapshots: []manifest.ID{updated[0].ID},
RemovePins: []string{"pin3"},
}, &updated))

require.Len(t, updated, 1)
require.EqualValues(t, []string{"pin2"}, updated[0].Pins)
require.EqualValues(t, newDesc2, updated[0].Description)
}
1 change: 1 addition & 0 deletions internal/server/server.go
Expand Up @@ -96,6 +96,7 @@ func (s *Server) SetupHTMLUIAPIHandlers(m *mux.Router) {
// snapshots
m.HandleFunc("/api/v1/snapshots", s.handleUI(s.handleListSnapshots)).Methods(http.MethodGet)
m.HandleFunc("/api/v1/snapshots/delete", s.handleUI(s.handleDeleteSnapshots)).Methods(http.MethodPost)
m.HandleFunc("/api/v1/snapshots/edit", s.handleUI(s.handleEditSnapshots)).Methods(http.MethodPost)
m.HandleFunc("/api/v1/policy", s.handleUI(s.handlePolicyGet)).Methods(http.MethodGet)
m.HandleFunc("/api/v1/policy", s.handleUI(s.handlePolicyPut)).Methods(http.MethodPut)
m.HandleFunc("/api/v1/policy", s.handleUI(s.handlePolicyDelete)).Methods(http.MethodDelete)
Expand Down
8 changes: 8 additions & 0 deletions internal/serverapi/serverapi.go
Expand Up @@ -178,6 +178,14 @@ type DeleteSnapshotsRequest struct {
DeleteSourceAndPolicy bool `json:"deleteSourceAndPolicy"`
}

// EditSnapshotsRequest contains request to edit one or more snapshots.
type EditSnapshotsRequest struct {
Snapshots []manifest.ID `json:"snapshots"`
NewDescription *string `json:"description"`
AddPins []string `json:"addPins"`
RemovePins []string `json:"removePins"`
}

// MountSnapshotRequest contains request to mount a snapshot.
type MountSnapshotRequest struct {
Root string `json:"root"`
Expand Down

0 comments on commit 512dceb

Please sign in to comment.