Skip to content

Commit

Permalink
Simplify login process
Browse files Browse the repository at this point in the history
  • Loading branch information
kognise committed Aug 26, 2024
1 parent 75163fc commit cc12e8b
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 82 deletions.
17 changes: 0 additions & 17 deletions browser/browser_darwin.go

This file was deleted.

15 changes: 0 additions & 15 deletions browser/browser_linux.go

This file was deleted.

19 changes: 13 additions & 6 deletions libts/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package libts

import (
"context"
"runtime"

"tailscale.com/client/tailscale"
"tailscale.com/ipn"
Expand All @@ -16,13 +17,19 @@ func Status(ctx context.Context) (*ipnstate.Status, error) {
return ts.Status(ctx)
}

// Start an interactive login flow. This will automatically open the user's web browser.
// Note that this will NOT DO ANYTHING if the session has already started; i.e. an
// AuthURL is already populated in the state.
// Returns true if StartLoginInteractive will (probably) open the user's web browser.
// Can be used to decide whether to display UI elements related to interactive login.
func StartLoginInteractiveWillOpenBrowser() bool {
return runtime.GOOS == "darwin"
}

// Start an interactive login flow. On macOS, this will automatically open the user's web browser.
func StartLoginInteractive(ctx context.Context) error {
// Workaround for a Tailscale bug (?) where the AuthURL isn't populated when calling
// StartLoginInteractive the first time if the user is already logged in. For some reason,
// calling Start first with no options makes the AuthURL populate.
// Workaround for a Tailscale bug where Tailscale will go into the Starting... state
// without populating the AuthURL when reauthenticating. For some reason, calling
// Start first with no options makes the AuthURL populate.
//
// We need AuthURL so we can display UI elements related to the login process.
err := ts.Start(ctx, ipn.Options{})
if err != nil {
return err
Expand Down
10 changes: 2 additions & 8 deletions menus.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,14 +259,8 @@ func (m *model) updateMenus() {

&ui.LabeledSubmenuItem{
Label: reauthenticateButtonLabel,
OnActivate: func() tea.Msg {
// Reauthenticating is basically the same as the first-time login flow.
err := libts.StartLoginInteractive(ctx)
if err != nil {
return errorMsg(err)
}
return successMsg("Starting reauthentication. This may take a few seconds.")
},
// Reauthenticating is basically the same as the first-time login flow.
OnActivate: startLoginInteractive,
},

&ui.LabeledSubmenuItem{
Expand Down
44 changes: 13 additions & 31 deletions update.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"time"

tea "github.com/charmbracelet/bubbletea"
"github.com/neuralinkcorp/tsui/browser"
"github.com/neuralinkcorp/tsui/libts"
"github.com/neuralinkcorp/tsui/ui"
"github.com/neuralinkcorp/tsui/version"
Expand Down Expand Up @@ -56,6 +55,15 @@ func updateState() tea.Msg {
return stateMsg(state)
}

// Command that starts the interactive login flow.
func startLoginInteractive() tea.Msg {
err := libts.StartLoginInteractive(ctx)
if err != nil {
return errorMsg(err)
}
return successMsg("Starting login flow. This may take a few seconds.")
}

// Creates a command to gets the current latency of the specified peers. Takes some time.
func makeDoPings(peers []*ipnstate.PeerStatus) tea.Cmd {
return func() tea.Msg {
Expand Down Expand Up @@ -158,39 +166,13 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {

// If we need to login...
case ipn.NeedsLogin:
if m.state.AuthURL == "" {
// If we haven't started the login flow yet, do so.
// Tailscale will open their browser for us.
return m, func() tea.Msg {
err := libts.StartLoginInteractive(ctx)
if err != nil {
return errorMsg(err)
}
return successMsg("Starting login flow. This may take a few seconds.")
}
} else if browser.IsSupported() {
// If the auth flow has already started, we need to open the browser ourselves.
return m, func() tea.Msg {
err := browser.OpenURL(m.state.AuthURL)
if err != nil {
return errorMsg(err)
}
return nil
}
}
return m, startLoginInteractive

case ipn.Starting:
// If we have an AuthURL in the Starting state, that means the user is reauthenticating
// and we also need to open the browser!
// (But not if we're root on Linux.)
if m.state.AuthURL != "" && browser.IsSupported() {
return m, func() tea.Msg {
err := browser.OpenURL(m.state.AuthURL)
if err != nil {
return errorMsg(err)
}
return nil
}
// and we want to open the browser for them (if supported).
if m.state.AuthURL != "" && libts.StartLoginInteractiveWillOpenBrowser() {
return m, startLoginInteractive
}
}
}
Expand Down
11 changes: 6 additions & 5 deletions view.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"strings"

"github.com/charmbracelet/lipgloss"
"github.com/neuralinkcorp/tsui/browser"
"github.com/neuralinkcorp/tsui/libts"
"github.com/neuralinkcorp/tsui/ui"
"tailscale.com/ipn"
)
Expand Down Expand Up @@ -269,8 +269,7 @@ func (m model) View() string {
lines = append(lines,
fmt.Sprintf(`Login URL: %s`, styledAuthUrl),
)
if browser.IsSupported() {
// We can't open the browser for them if running as the root user on Linux.
if libts.StartLoginInteractiveWillOpenBrowser() {
lines = append(lines,
``,
`Press . to open in browser.`,
Expand All @@ -294,15 +293,17 @@ func (m model) View() string {
if m.state.AuthURL == "" {
middle = renderMiddleBanner(&m, middleHeight, ui.PoggersAnimationFrame(m.animationT))
} else {
// If we have an AuthURL in the Starting state, that means the user is reauthenticating!
// If we have an AuthURL in the Starting state, that means the user is reauthenticating.
// TODO: This case only seems to show up sometimes, and may not anymore (?) in the latest
// version of Tailscale.
lines := []string{
lipgloss.NewStyle().
Bold(true).
Render(`Reauthenticate with Tailscale`),
``,
fmt.Sprintf(`Login URL: %s`, styledAuthUrl),
}
if browser.IsSupported() {
if libts.StartLoginInteractiveWillOpenBrowser() {
// We can't open the browser for them if running as the root user on Linux.
lines = append(lines,
``,
Expand Down

0 comments on commit cc12e8b

Please sign in to comment.