Skip to content

Commit 2b98aed

Browse files
mhofstetterwillnorris
authored andcommitted
allow deletion of unowned links
It should be possible to delete links owned by non-existing users (tagged-devices or deleted) in the same ways as it's possible to edit these links. Signed-off-by: Marco Hofstetter <[email protected]>
1 parent a762273 commit 2b98aed

File tree

2 files changed

+38
-13
lines changed

2 files changed

+38
-13
lines changed

golink.go

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -605,8 +605,8 @@ func serveDelete(w http.ResponseWriter, r *http.Request) {
605605
return
606606
}
607607

608-
if link.Owner != login {
609-
http.Error(w, "cannot delete link owned by another user", http.StatusForbidden)
608+
if err := checkLinkOwnership(r.Context(), link, login); err != nil {
609+
http.Error(w, fmt.Sprintf("cannot delete link: %v", err), http.StatusForbidden)
610610
return
611611
}
612612

@@ -653,17 +653,9 @@ func serveSave(w http.ResponseWriter, r *http.Request) {
653653
http.Error(w, err.Error(), http.StatusInternalServerError)
654654
}
655655

656-
if link != nil && link.Owner != "" && link.Owner != login {
657-
exists, err := userExists(r.Context(), link.Owner)
658-
if err != nil {
659-
log.Printf("looking up tailnet user %q: %v", link.Owner, err)
660-
}
661-
// Don't allow taking over links if the owner account still exists
662-
// or if we're unsure because an error occurred.
663-
if exists || err != nil {
664-
http.Error(w, "not your link; owned by "+link.Owner, http.StatusForbidden)
665-
return
666-
}
656+
if err := checkLinkOwnership(r.Context(), link, login); err != nil {
657+
http.Error(w, fmt.Sprintf("cannot update link: %v", err), http.StatusForbidden)
658+
return
667659
}
668660

669661
// allow transferring ownership to valid users. If empty, set owner to current user.
@@ -705,6 +697,23 @@ func serveSave(w http.ResponseWriter, r *http.Request) {
705697
}
706698
}
707699

700+
func checkLinkOwnership(ctx context.Context, link *Link, login string) error {
701+
if link == nil || link.Owner == "" {
702+
return nil
703+
}
704+
705+
linkOwnerExists, err := userExists(ctx, link.Owner)
706+
if err != nil {
707+
log.Printf("looking up tailnet user %q: %v", link.Owner, err)
708+
}
709+
// Don't allow deleting or updating links if the owner account still exists
710+
// or if we're unsure because an error occurred.
711+
if (linkOwnerExists && link.Owner != login) || err != nil {
712+
return fmt.Errorf("link owned by user %q", link.Owner)
713+
}
714+
return nil
715+
}
716+
708717
// serveExport prints a snapshot of the link database. Links are JSON encoded
709718
// and printed one per line. This format is used to restore link snapshots on
710719
// startup.

golink_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ func TestServeSave(t *testing.T) {
124124
t.Fatal(err)
125125
}
126126

127+
db.Save(&Link{Short: "link-owned-by-tagged-devices", Long: "/before", Owner: "tagged-devices"})
128+
127129
tests := []struct {
128130
name string
129131
short string
@@ -157,6 +159,13 @@ func TestServeSave(t *testing.T) {
157159
currentUser: func(*http.Request) (string, error) { return "[email protected]", nil },
158160
wantStatus: http.StatusForbidden,
159161
},
162+
{
163+
name: "allow editing link owned by tagged-devices",
164+
short: "link-owned-by-tagged-devices",
165+
long: "/after",
166+
currentUser: func(*http.Request) (string, error) { return "[email protected]", nil },
167+
wantStatus: http.StatusOK,
168+
},
160169
{
161170
name: "disallow unknown users",
162171
short: "who2",
@@ -211,6 +220,7 @@ func TestServeDelete(t *testing.T) {
211220
}
212221
db.Save(&Link{Short: "a", Owner: "[email protected]"})
213222
db.Save(&Link{Short: "foo", Owner: "[email protected]"})
223+
db.Save(&Link{Short: "link-owned-by-tagged-devices", Long: "/before", Owner: "tagged-devices"})
214224

215225
xsrf := func(short string) string {
216226
return xsrftoken.Generate(xsrfKey, "[email protected]", short)
@@ -238,6 +248,12 @@ func TestServeDelete(t *testing.T) {
238248
short: "a",
239249
wantStatus: http.StatusForbidden,
240250
},
251+
{
252+
name: "allow deleting link owned by tagged-devices",
253+
short: "link-owned-by-tagged-devices",
254+
xsrf: xsrf("link-owned-by-tagged-devices"),
255+
wantStatus: http.StatusOK,
256+
},
241257
{
242258
name: "invalid xsrf",
243259
short: "foo",

0 commit comments

Comments
 (0)