|
|
@@ -18,8 +18,6 @@ import (
|
|
|
"net/http"
|
|
|
"net/netip"
|
|
|
"net/url"
|
|
|
- "os"
|
|
|
- "path"
|
|
|
"reflect"
|
|
|
"runtime"
|
|
|
"slices"
|
|
|
@@ -31,7 +29,6 @@ import (
|
|
|
"golang.org/x/net/dns/dnsmessage"
|
|
|
"tailscale.com/client/tailscale/apitype"
|
|
|
"tailscale.com/clientupdate"
|
|
|
- "tailscale.com/drive"
|
|
|
"tailscale.com/envknob"
|
|
|
"tailscale.com/health/healthmsg"
|
|
|
"tailscale.com/hostinfo"
|
|
|
@@ -104,8 +101,6 @@ var handler = map[string]LocalAPIHandler{
|
|
|
"disconnect-control": (*Handler).disconnectControl,
|
|
|
"dns-osconfig": (*Handler).serveDNSOSConfig,
|
|
|
"dns-query": (*Handler).serveDNSQuery,
|
|
|
- "drive/fileserver-address": (*Handler).serveDriveServerAddr,
|
|
|
- "drive/shares": (*Handler).serveShares,
|
|
|
"goroutines": (*Handler).serveGoroutines,
|
|
|
"handle-push-message": (*Handler).serveHandlePushMessage,
|
|
|
"id-token": (*Handler).serveIDToken,
|
|
|
@@ -2661,124 +2656,6 @@ func (h *Handler) serveDNSQuery(w http.ResponseWriter, r *http.Request) {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-// serveDriveServerAddr handles updates of the Taildrive file server address.
|
|
|
-func (h *Handler) serveDriveServerAddr(w http.ResponseWriter, r *http.Request) {
|
|
|
- if r.Method != httpm.PUT {
|
|
|
- http.Error(w, "only PUT allowed", http.StatusMethodNotAllowed)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- b, err := io.ReadAll(r.Body)
|
|
|
- if err != nil {
|
|
|
- http.Error(w, err.Error(), http.StatusBadRequest)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- h.b.DriveSetServerAddr(string(b))
|
|
|
- w.WriteHeader(http.StatusCreated)
|
|
|
-}
|
|
|
-
|
|
|
-// serveShares handles the management of Taildrive shares.
|
|
|
-//
|
|
|
-// PUT - adds or updates an existing share
|
|
|
-// DELETE - removes a share
|
|
|
-// GET - gets a list of all shares, sorted by name
|
|
|
-// POST - renames an existing share
|
|
|
-func (h *Handler) serveShares(w http.ResponseWriter, r *http.Request) {
|
|
|
- if !h.b.DriveSharingEnabled() {
|
|
|
- http.Error(w, `taildrive sharing not enabled, please add the attribute "drive:share" to this node in your ACLs' "nodeAttrs" section`, http.StatusForbidden)
|
|
|
- return
|
|
|
- }
|
|
|
- switch r.Method {
|
|
|
- case httpm.PUT:
|
|
|
- var share drive.Share
|
|
|
- err := json.NewDecoder(r.Body).Decode(&share)
|
|
|
- if err != nil {
|
|
|
- http.Error(w, err.Error(), http.StatusBadRequest)
|
|
|
- return
|
|
|
- }
|
|
|
- share.Path = path.Clean(share.Path)
|
|
|
- fi, err := os.Stat(share.Path)
|
|
|
- if err != nil {
|
|
|
- http.Error(w, err.Error(), http.StatusBadRequest)
|
|
|
- return
|
|
|
- }
|
|
|
- if !fi.IsDir() {
|
|
|
- http.Error(w, "not a directory", http.StatusBadRequest)
|
|
|
- return
|
|
|
- }
|
|
|
- if drive.AllowShareAs() {
|
|
|
- // share as the connected user
|
|
|
- username, err := h.Actor.Username()
|
|
|
- if err != nil {
|
|
|
- http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
- return
|
|
|
- }
|
|
|
- share.As = username
|
|
|
- }
|
|
|
- err = h.b.DriveSetShare(&share)
|
|
|
- if err != nil {
|
|
|
- if errors.Is(err, drive.ErrInvalidShareName) {
|
|
|
- http.Error(w, "invalid share name", http.StatusBadRequest)
|
|
|
- return
|
|
|
- }
|
|
|
- http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
- return
|
|
|
- }
|
|
|
- w.WriteHeader(http.StatusCreated)
|
|
|
- case httpm.DELETE:
|
|
|
- b, err := io.ReadAll(r.Body)
|
|
|
- if err != nil {
|
|
|
- http.Error(w, err.Error(), http.StatusBadRequest)
|
|
|
- return
|
|
|
- }
|
|
|
- err = h.b.DriveRemoveShare(string(b))
|
|
|
- if err != nil {
|
|
|
- if os.IsNotExist(err) {
|
|
|
- http.Error(w, "share not found", http.StatusNotFound)
|
|
|
- return
|
|
|
- }
|
|
|
- http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
- return
|
|
|
- }
|
|
|
- w.WriteHeader(http.StatusNoContent)
|
|
|
- case httpm.POST:
|
|
|
- var names [2]string
|
|
|
- err := json.NewDecoder(r.Body).Decode(&names)
|
|
|
- if err != nil {
|
|
|
- http.Error(w, err.Error(), http.StatusBadRequest)
|
|
|
- return
|
|
|
- }
|
|
|
- err = h.b.DriveRenameShare(names[0], names[1])
|
|
|
- if err != nil {
|
|
|
- if os.IsNotExist(err) {
|
|
|
- http.Error(w, "share not found", http.StatusNotFound)
|
|
|
- return
|
|
|
- }
|
|
|
- if os.IsExist(err) {
|
|
|
- http.Error(w, "share name already used", http.StatusBadRequest)
|
|
|
- return
|
|
|
- }
|
|
|
- if errors.Is(err, drive.ErrInvalidShareName) {
|
|
|
- http.Error(w, "invalid share name", http.StatusBadRequest)
|
|
|
- return
|
|
|
- }
|
|
|
- http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
- return
|
|
|
- }
|
|
|
- w.WriteHeader(http.StatusNoContent)
|
|
|
- case httpm.GET:
|
|
|
- shares := h.b.DriveGetShares()
|
|
|
- err := json.NewEncoder(w).Encode(shares)
|
|
|
- if err != nil {
|
|
|
- http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
- return
|
|
|
- }
|
|
|
- default:
|
|
|
- http.Error(w, "unsupported method", http.StatusMethodNotAllowed)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
// serveSuggestExitNode serves a POST endpoint for returning a suggested exit node.
|
|
|
func (h *Handler) serveSuggestExitNode(w http.ResponseWriter, r *http.Request) {
|
|
|
if r.Method != httpm.GET {
|