Repair Tailscale authorization flow

This commit is contained in:
David Heinemeier Hansson
2026-07-17 10:20:08 -07:00
parent 16b5f2157f
commit fe48e83222
8 changed files with 167 additions and 9 deletions
+9
View File
@@ -59,6 +59,14 @@ function accountLabel(account) {
return String(account.id || "Unknown account")
}
function loginPlan(needsLogin, authUrl) {
var url = String(authUrl || "").trim()
if (needsLogin === true && /^https?:\/\//.test(url)) {
return { authUrl: url, command: [] }
}
return { authUrl: "", command: ["tailscale", "up"] }
}
function peerFromStatus(id, peer) {
return {
id: id,
@@ -270,6 +278,7 @@ if (typeof module !== "undefined") {
displayHostName: displayHostName,
osIcon: osIcon,
accountLabel: accountLabel,
loginPlan: loginPlan,
isMullvadPeer: isMullvadPeer,
peerFromStatus: peerFromStatus,
parseExitNodeList: parseExitNodeList,
+50
View File
@@ -498,6 +498,56 @@ Panel {
}
}
CursorSurface {
id: connectionRow
visible: tailscale.installed && !tailscale.running
width: parent.width
implicitHeight: connectionText.implicitHeight + Style.spacing.rowPaddingX
hasCursor: root.cursorActive && root.focusSection === "header"
foreground: root.foreground
fill: root.hoverFill
MouseArea {
anchors.fill: parent
hoverEnabled: true
enabled: !tailscale.busy
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onEntered: {
root.cursorActive = true
root.focusSection = "header"
}
onClicked: tailscale.loginOrUp()
}
Column {
id: connectionText
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Style.space(12)
anchors.rightMargin: Style.space(12)
spacing: Style.space(2)
Text {
width: parent.width
text: tailscale.needsLogin ? "Authorize this device" : "Connect Tailscale"
color: root.foreground
font.family: root.fontFamily
font.pixelSize: Style.font.body
font.weight: Font.Medium
}
Text {
width: parent.width
text: tailscale.needsLogin ? "Open Tailscale to restore this device's access" : "Reconnect with the current Tailscale settings"
color: root.dim
font.family: root.fontFamily
font.pixelSize: Style.font.caption
wrapMode: Text.WordWrap
}
}
}
Text {
visible: tailscale.actionStatus !== "" || tailscale.lastError !== ""
width: parent.width
+8 -6
View File
@@ -244,15 +244,19 @@ Item {
function loginOrUp() {
if (!installed || loginProcess.running) return
var plan = Model.loginPlan(needsLogin, authUrl)
if (plan.authUrl !== "") {
_loginUrlOpened = false
openAuthUrlFrom(plan.authUrl, true)
return
}
_loginOutput = ""
_loginError = ""
actionStatus = needsLogin ? "Starting Tailscale login…" : "Turning Tailscale on…"
_loginInProgress = needsLogin
_loginUrlOpened = false
_preLoginAuthUrl = authUrl
var command = ["tailscale", "up"]
if (needsLogin) command.push("--force-reauth")
loginProcess.command = command
loginProcess.command = plan.command
loginProcess.running = true
if (needsLogin) loginTimeoutTimer.restart()
}
@@ -317,9 +321,7 @@ Item {
_loginUrlOpened = true
_loginInProgress = false
loginTimeoutTimer.stop()
Qt.openUrlExternally(url)
actionStatus = "Opened login link"
actionStatusTimer.restart()
Quickshell.execDetached(["omarchy-launch-browser", url])
return true
}
return false