mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-12 13:48:01 +00:00
ipn/{ipnlocal,localapi}, cmd/tailscale: add logout command
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:

committed by
Brad Fitzpatrick

parent
11127666b2
commit
3167e55ddf
@@ -1961,19 +1961,28 @@ func (b *LocalBackend) requestEngineStatusAndWait() {
|
||||
// transitions the local engine to the logged-out state without
|
||||
// waiting for controlclient to be in that state.
|
||||
//
|
||||
// TODO(danderson): controlclient Logout does nothing useful, and we
|
||||
// shouldn't be transitioning to a state based on what we believe
|
||||
// controlclient may have done.
|
||||
//
|
||||
// NOTE(apenwarr): No easy way to persist logged-out status.
|
||||
// Maybe that's for the better; if someone logs out accidentally,
|
||||
// rebooting will fix it.
|
||||
func (b *LocalBackend) Logout() {
|
||||
b.logout(context.Background(), false)
|
||||
}
|
||||
|
||||
func (b *LocalBackend) LogoutSync(ctx context.Context) error {
|
||||
return b.logout(ctx, true)
|
||||
}
|
||||
|
||||
func (b *LocalBackend) logout(ctx context.Context, sync bool) error {
|
||||
b.mu.Lock()
|
||||
cc := b.cc
|
||||
b.setNetMapLocked(nil)
|
||||
b.mu.Unlock()
|
||||
|
||||
b.EditPrefs(&ipn.MaskedPrefs{
|
||||
WantRunningSet: true,
|
||||
Prefs: ipn.Prefs{WantRunning: true},
|
||||
})
|
||||
|
||||
if cc == nil {
|
||||
// Double Logout can happen via repeated IPN
|
||||
// connections to ipnserver making it repeatedly
|
||||
@@ -1982,16 +1991,22 @@ func (b *LocalBackend) Logout() {
|
||||
// on the transition to zero.
|
||||
// Previously this crashed when we asserted that c was non-nil
|
||||
// here.
|
||||
return
|
||||
return errors.New("no controlclient")
|
||||
}
|
||||
|
||||
cc.Logout()
|
||||
var err error
|
||||
if sync {
|
||||
err = cc.Logout(ctx)
|
||||
} else {
|
||||
cc.StartLogout()
|
||||
}
|
||||
|
||||
b.mu.Lock()
|
||||
b.setNetMapLocked(nil)
|
||||
b.mu.Unlock()
|
||||
|
||||
b.stateMachine()
|
||||
return err
|
||||
}
|
||||
|
||||
// assertClientLocked crashes if there is no controlclient in this backend.
|
||||
|
@@ -87,6 +87,8 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
h.serveGoroutines(w, r)
|
||||
case "/localapi/v0/status":
|
||||
h.serveStatus(w, r)
|
||||
case "/localapi/v0/logout":
|
||||
h.serveLogout(w, r)
|
||||
case "/localapi/v0/prefs":
|
||||
h.servePrefs(w, r)
|
||||
case "/localapi/v0/check-ip-forwarding":
|
||||
@@ -200,6 +202,23 @@ func (h *Handler) serveStatus(w http.ResponseWriter, r *http.Request) {
|
||||
e.Encode(st)
|
||||
}
|
||||
|
||||
func (h *Handler) serveLogout(w http.ResponseWriter, r *http.Request) {
|
||||
if !h.PermitWrite {
|
||||
http.Error(w, "logout access denied", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
if r.Method != "POST" {
|
||||
http.Error(w, "want POST", 400)
|
||||
return
|
||||
}
|
||||
err := h.b.LogoutSync(r.Context())
|
||||
if err == nil {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
http.Error(w, err.Error(), 500)
|
||||
}
|
||||
|
||||
func (h *Handler) servePrefs(w http.ResponseWriter, r *http.Request) {
|
||||
if !h.PermitRead {
|
||||
http.Error(w, "prefs access denied", http.StatusForbidden)
|
||||
|
Reference in New Issue
Block a user