Make verification modal wait for confirmation

This commit is contained in:
Tulir Asokan 2020-07-25 18:40:31 +03:00
parent 341f8829d6
commit ead7e0bf1d
4 changed files with 68 additions and 18 deletions

2
go.mod
View File

@ -27,3 +27,5 @@ require (
maunium.net/go/mauview v0.1.1 maunium.net/go/mauview v0.1.1
maunium.net/go/tcell v0.2.0 maunium.net/go/tcell v0.2.0
) )
replace maunium.net/go/mautrix => github.com/nikofil/mautrix-go v0.5.2-0.20200725145808-be3336827da7

8
go.sum
View File

@ -1,9 +1,11 @@
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI= github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
github.com/alecthomas/chroma v0.7.3 h1:NfdAERMy+esYQs8OXk0I868/qDxxCEo7FMz1WIqMAeI= github.com/alecthomas/chroma v0.7.3 h1:NfdAERMy+esYQs8OXk0I868/qDxxCEo7FMz1WIqMAeI=
github.com/alecthomas/chroma v0.7.3/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM= github.com/alecthomas/chroma v0.7.3/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0= github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE= github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ= github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ= github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk= github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -28,6 +30,9 @@ github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/nikofil/mautrix-go v0.5.2-0.20200725145808-be3336827da7 h1:w5IiIpetgAwalLPFkxiVbxBXJtcB9zLhoGLkyouQb4k=
github.com/nikofil/mautrix-go v0.5.2-0.20200725145808-be3336827da7/go.mod h1:Va/74MijqaS0DQ3aUqxmFO54/PMfr1LVsCOcGRHbYmo=
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
@ -70,7 +75,10 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw= golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM= golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

View File

@ -498,18 +498,20 @@ func cmdVerify(cmd *Command) {
if device == nil { if device == nil {
return return
} }
if device.Trust == crypto.TrustStateVerified {
cmd.Reply("That device is already verified")
return
}
if len(cmd.Args) == 2 { if len(cmd.Args) == 2 {
mach := cmd.Matrix.Crypto().(*crypto.OlmMachine) mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
timeout := 60 * time.Second mach.DefaultSASTimeout = 120 * time.Second
err := mach.NewSASVerificationWith(device, "", timeout, true) modal := NewVerificationModal(cmd.MainView, device, mach.DefaultSASTimeout)
cmd.MainView.ShowModal(modal)
err := mach.NewSimpleSASVerificationWith(device, modal)
if err != nil { if err != nil {
cmd.Reply("Failed to start interactive verification: %v", err) cmd.Reply("Failed to start interactive verification: %v", err)
return return
} }
modal := NewVerificationModal(cmd.MainView, device, timeout)
mach.VerifySASEmojisMatch = modal.VerifyEmojisMatch
mach.VerifySASNumbersMatch = modal.VerifyNumbersMatch
cmd.MainView.ShowModal(modal)
} else { } else {
fingerprint := strings.Join(cmd.Args[2:], "") fingerprint := strings.Join(cmd.Args[2:], "")
if string(device.SigningKey) != fingerprint { if string(device.SigningKey) != fingerprint {
@ -547,6 +549,10 @@ func cmdBlacklist(cmd *Command) {
if device == nil { if device == nil {
return return
} }
if device.Trust == crypto.TrustStateBlacklisted {
cmd.Reply("That device is already blacklisted")
return
}
action := "blacklisted" action := "blacklisted"
if device.Trust == crypto.TrustStateVerified { if device.Trust == crypto.TrustStateVerified {
action = "unverified and blacklisted" action = "unverified and blacklisted"

View File

@ -27,6 +27,7 @@ import (
"maunium.net/go/gomuks/debug" "maunium.net/go/gomuks/debug"
"maunium.net/go/mautrix/crypto" "maunium.net/go/mautrix/crypto"
"maunium.net/go/mautrix/event"
) )
type EmojiView struct { type EmojiView struct {
@ -59,6 +60,8 @@ func (e *EmojiView) Draw(screen mauview.Screen) {
type VerificationModal struct { type VerificationModal struct {
mauview.Component mauview.Component
device *crypto.DeviceIdentity
container *mauview.Box container *mauview.Box
waitingBar *mauview.ProgressBar waitingBar *mauview.ProgressBar
@ -68,6 +71,7 @@ type VerificationModal struct {
stopWaiting chan struct{} stopWaiting chan struct{}
confirmChan chan bool confirmChan chan bool
done bool
parent *MainView parent *MainView
} }
@ -75,8 +79,10 @@ type VerificationModal struct {
func NewVerificationModal(mainView *MainView, device *crypto.DeviceIdentity, timeout time.Duration) *VerificationModal { func NewVerificationModal(mainView *MainView, device *crypto.DeviceIdentity, timeout time.Duration) *VerificationModal {
vm := &VerificationModal{ vm := &VerificationModal{
parent: mainView, parent: mainView,
device: device,
stopWaiting: make(chan struct{}), stopWaiting: make(chan struct{}),
confirmChan: make(chan bool), confirmChan: make(chan bool),
done: false,
} }
progress := int(timeout.Seconds()) progress := int(timeout.Seconds())
@ -115,8 +121,6 @@ func (vm *VerificationModal) decrementWaitingBar(progress int) {
select { select {
case <-time.Tick(time.Second): case <-time.Tick(time.Second):
if progress <= 0 { if progress <= 0 {
vm.parent.HideModal()
vm.parent.parent.Render()
return return
} }
progress-- progress--
@ -124,13 +128,14 @@ func (vm *VerificationModal) decrementWaitingBar(progress int) {
vm.parent.parent.Render() vm.parent.parent.Render()
case <-vm.stopWaiting: case <-vm.stopWaiting:
vm.waitingBar.SetIndeterminate(true) vm.waitingBar.SetIndeterminate(true)
break vm.parent.parent.app.SetRedrawTicker(100 * time.Millisecond)
return
} }
} }
} }
func (vm *VerificationModal) VerifyEmojisMatch(emojis [7]crypto.VerificationEmoji, _ *crypto.DeviceIdentity) bool { func (vm *VerificationModal) VerifyEmojisMatch(emojis [7]crypto.VerificationEmoji) bool {
vm.infoText.SetText("Check if the other device is showing the same emojis as below, then type \"yes\" to accept, or \"no\" to reject") vm.infoText.SetText("Check if the other device is showing the\nsame emojis as below, then type \"yes\" to\naccept, or \"no\" to reject")
vm.inputBar. vm.inputBar.
SetTextColor(tcell.ColorWhite). SetTextColor(tcell.ColorWhite).
SetBackgroundColor(tcell.ColorDarkCyan). SetBackgroundColor(tcell.ColorDarkCyan).
@ -140,14 +145,14 @@ func (vm *VerificationModal) VerifyEmojisMatch(emojis [7]crypto.VerificationEmoj
vm.parent.parent.Render() vm.parent.parent.Render()
vm.stopWaiting <- struct{}{} vm.stopWaiting <- struct{}{}
confirm := <-vm.confirmChan confirm := <-vm.confirmChan
// TODO this should hook into cancel/success of the verification and display a success message instead of just closing vm.emojiText.Emojis = nil
vm.parent.HideModal() vm.infoText.SetText(fmt.Sprintf("Waiting for %s to accept", vm.device.UserID))
vm.parent.parent.Render() vm.parent.parent.Render()
return confirm return confirm
} }
func (vm *VerificationModal) VerifyNumbersMatch(numbers [3]uint, _ *crypto.DeviceIdentity) bool { func (vm *VerificationModal) VerifyNumbersMatch(numbers [3]uint) bool {
vm.infoText.SetText("Check if the other device is showing the same numbers as below, then type \"yes\" to accept, or \"no\" to reject") vm.infoText.SetText("Check if the other device is showing the\nsame numbers as below, then type \"yes\" to\naccept, or \"no\" to reject")
vm.inputBar. vm.inputBar.
SetTextColor(tcell.ColorWhite). SetTextColor(tcell.ColorWhite).
SetBackgroundColor(tcell.ColorDarkCyan). SetBackgroundColor(tcell.ColorDarkCyan).
@ -157,14 +162,42 @@ func (vm *VerificationModal) VerifyNumbersMatch(numbers [3]uint, _ *crypto.Devic
vm.parent.parent.Render() vm.parent.parent.Render()
vm.stopWaiting <- struct{}{} vm.stopWaiting <- struct{}{}
confirm := <-vm.confirmChan confirm := <-vm.confirmChan
// TODO this should hook into cancel/success of the verification and display a success message instead of just closing vm.emojiText.Numbers = nil
vm.parent.HideModal() vm.infoText.SetText(fmt.Sprintf("Waiting for %s to accept", vm.device.UserID))
vm.parent.parent.Render() vm.parent.parent.Render()
return confirm return confirm
} }
func (vm *VerificationModal) OnCancel(cancelledByUs bool, reason string, _ event.VerificationCancelCode) {
vm.waitingBar.SetIndeterminate(false).SetMax(100).SetProgress(100)
vm.parent.parent.app.SetRedrawTicker(1 * time.Minute)
if cancelledByUs {
vm.infoText.SetText(fmt.Sprintf("Verification failed: %s", reason))
} else {
vm.infoText.SetText(fmt.Sprintf("Verification cancelled by %s: %s", vm.device.UserID, reason))
}
vm.inputBar.SetPlaceholder("Press enter to close dialog")
vm.done = true
vm.parent.parent.Render()
}
func (vm *VerificationModal) OnSuccess() {
vm.waitingBar.SetIndeterminate(false).SetMax(100).SetProgress(100)
vm.parent.parent.app.SetRedrawTicker(1 * time.Minute)
vm.infoText.SetText(fmt.Sprintf("Successfully verified %s (%s) of %s", vm.device.Name, vm.device.DeviceID, vm.device.UserID))
vm.inputBar.SetPlaceholder("Press enter to close dialog")
vm.done = true
vm.parent.parent.Render()
}
func (vm *VerificationModal) OnKeyEvent(event mauview.KeyEvent) bool { func (vm *VerificationModal) OnKeyEvent(event mauview.KeyEvent) bool {
if vm.emojiText.Emojis == nil && vm.emojiText.Numbers == nil { if vm.done {
if event.Key() == tcell.KeyEnter || event.Key() == tcell.KeyEsc {
vm.parent.HideModal()
return true
}
return false
} else if vm.emojiText.Emojis == nil && vm.emojiText.Numbers == nil {
debug.Print("Ignoring pre-emoji key event") debug.Print("Ignoring pre-emoji key event")
return false return false
} }
@ -177,6 +210,7 @@ func (vm *VerificationModal) OnKeyEvent(event mauview.KeyEvent) bool {
debug.Print("Rejecting verification") debug.Print("Rejecting verification")
vm.confirmChan <- false vm.confirmChan <- false
} }
vm.inputBar.SetTextAndMoveCursor("")
return true return true
} else { } else {
return vm.inputBar.OnKeyEvent(event) return vm.inputBar.OnKeyEvent(event)