mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-18 16:17:03 +00:00
GODT-1366: Simple lookup of index and select current user
This commit is contained in:
@ -41,6 +41,7 @@ const (
|
|||||||
NoActiveKeyForRecipientEvent = "noActiveKeyForRecipient"
|
NoActiveKeyForRecipientEvent = "noActiveKeyForRecipient"
|
||||||
UpgradeApplicationEvent = "upgradeApplication"
|
UpgradeApplicationEvent = "upgradeApplication"
|
||||||
TLSCertIssue = "tlsCertPinningIssue"
|
TLSCertIssue = "tlsCertPinningIssue"
|
||||||
|
UserChangeDone = "QMLUserChangedDone"
|
||||||
|
|
||||||
// LogoutEventTimeout is the minimum time to permit between logout events being sent.
|
// LogoutEventTimeout is the minimum time to permit between logout events being sent.
|
||||||
LogoutEventTimeout = 3 * time.Minute
|
LogoutEventTimeout = 3 * time.Minute
|
||||||
@ -55,4 +56,5 @@ func SetupEvents(listener listener.Listener) {
|
|||||||
listener.SetBuffer(UpgradeApplicationEvent)
|
listener.SetBuffer(UpgradeApplicationEvent)
|
||||||
listener.SetBuffer(TLSCertIssue)
|
listener.SetBuffer(TLSCertIssue)
|
||||||
listener.SetBuffer(UserRefreshEvent)
|
listener.SetBuffer(UserRefreshEvent)
|
||||||
|
listener.Book(UserChangeDone)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -236,22 +236,29 @@ ColumnLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
Button {
|
Button {
|
||||||
colorScheme: root.colorScheme
|
colorScheme: root.colorScheme
|
||||||
text: "Login Finished"
|
text: "Login Finished"
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.backend.loginFinished()
|
root.backend.loginFinished(0+loginFinishedIndex.text)
|
||||||
user.resetLoginRequests()
|
user.resetLoginRequests()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TextField {
|
||||||
|
id: loginFinishedIndex
|
||||||
|
colorScheme: root.colorScheme
|
||||||
|
label: "Index:"
|
||||||
|
text: "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
TextField {
|
TextField {
|
||||||
colorScheme: root.colorScheme
|
colorScheme: root.colorScheme
|
||||||
label: "used:"
|
label: "used:"
|
||||||
text: user && user.usedBytes ? user.usedBytes : 0
|
text: user && user.usedBytes ? user.usedBytes : 0
|
||||||
validator: DoubleValidator {bottom: 1; top: 1024*1024*1024*1024*1024}
|
|
||||||
onEditingFinished: {
|
onEditingFinished: {
|
||||||
user.usedBytes = parseFloat(text)
|
user.usedBytes = parseFloat(text)
|
||||||
}
|
}
|
||||||
@ -261,7 +268,6 @@ ColumnLayout {
|
|||||||
colorScheme: root.colorScheme
|
colorScheme: root.colorScheme
|
||||||
label: "total:"
|
label: "total:"
|
||||||
text: user && user.totalBytes ? user.totalBytes : 0
|
text: user && user.totalBytes ? user.totalBytes : 0
|
||||||
validator: DoubleValidator {bottom: 1; top: 1024*1024*1024*1024*1024}
|
|
||||||
onEditingFinished: {
|
onEditingFinished: {
|
||||||
user.totalBytes = parseFloat(text)
|
user.totalBytes = parseFloat(text)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -670,7 +670,7 @@ Window {
|
|||||||
signal login2PasswordRequested()
|
signal login2PasswordRequested()
|
||||||
signal login2PasswordError(string errorMsg)
|
signal login2PasswordError(string errorMsg)
|
||||||
signal login2PasswordErrorAbort(string errorMsg)
|
signal login2PasswordErrorAbort(string errorMsg)
|
||||||
signal loginFinished()
|
signal loginFinished(int index)
|
||||||
|
|
||||||
signal internetOff()
|
signal internetOff()
|
||||||
signal internetOn()
|
signal internetOn()
|
||||||
@ -847,7 +847,7 @@ Window {
|
|||||||
console.debug("<- login2PasswordErrorAbort")
|
console.debug("<- login2PasswordErrorAbort")
|
||||||
}
|
}
|
||||||
onLoginFinished: {
|
onLoginFinished: {
|
||||||
console.debug("<- loginFinished")
|
console.debug("<- loginFinished", index)
|
||||||
}
|
}
|
||||||
|
|
||||||
onInternetOff: {
|
onInternetOff: {
|
||||||
|
|||||||
@ -159,7 +159,6 @@ Item {
|
|||||||
|
|
||||||
model: root.backend.users
|
model: root.backend.users
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
|
|
||||||
width: leftBar.width - 2*accounts._leftRightMargins
|
width: leftBar.width - 2*accounts._leftRightMargins
|
||||||
implicitHeight: children[0].implicitHeight + children[0].anchors.topMargin + children[0].anchors.bottomMargin
|
implicitHeight: children[0].implicitHeight + children[0].anchors.topMargin + children[0].anchors.bottomMargin
|
||||||
implicitWidth: children[0].implicitWidth + children[0].anchors.leftMargin + children[0].anchors.rightMargin
|
implicitWidth: children[0].implicitWidth + children[0].anchors.leftMargin + children[0].anchors.rightMargin
|
||||||
@ -359,7 +358,13 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showAccount () { rightContent.currentIndex = 0 }
|
function showAccount(index) {
|
||||||
|
if (index !== undefined && index >= 0){
|
||||||
|
accounts.currentIndex = index
|
||||||
|
}
|
||||||
|
rightContent.currentIndex = 0
|
||||||
|
}
|
||||||
|
|
||||||
function showSignIn () { rightContent.currentIndex = 1 }
|
function showSignIn () { rightContent.currentIndex = 1 }
|
||||||
function showGeneralSettings () { rightContent.currentIndex = 2 }
|
function showGeneralSettings () { rightContent.currentIndex = 2 }
|
||||||
function showPortSettings () { rightContent.currentIndex = 3 }
|
function showPortSettings () { rightContent.currentIndex = 3 }
|
||||||
@ -371,7 +376,7 @@ Item {
|
|||||||
Connections {
|
Connections {
|
||||||
target: root.backend
|
target: root.backend
|
||||||
|
|
||||||
onLoginFinished: rightContent.showAccount()
|
onLoginFinished: rightContent.showAccount(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,6 +85,10 @@ ApplicationWindow {
|
|||||||
onShowMainWindow: {
|
onShowMainWindow: {
|
||||||
root.showAndRise()
|
root.showAndRise()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onLoginFinished: {
|
||||||
|
console.debug("Login finished", index)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StackLayout {
|
StackLayout {
|
||||||
|
|||||||
@ -22,7 +22,9 @@ package qt
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||||
"github.com/ProtonMail/proton-bridge/internal/users"
|
"github.com/ProtonMail/proton-bridge/internal/users"
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||||
)
|
)
|
||||||
@ -138,14 +140,40 @@ func (f *FrontendQt) finishLogin() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := f.bridge.FinishLogin(f.authClient, f.auth, f.password)
|
done := make(chan string)
|
||||||
|
f.eventListener.Add(events.UserChangeDone, done)
|
||||||
|
defer f.eventListener.Remove(events.UserChangeDone, done)
|
||||||
|
|
||||||
|
user, err := f.bridge.FinishLogin(f.authClient, f.auth, f.password)
|
||||||
if err != nil && err != users.ErrUserAlreadyConnected {
|
if err != nil && err != users.ErrUserAlreadyConnected {
|
||||||
f.log.WithError(err).Errorf("Finish login failed")
|
f.log.WithError(err).Errorf("Finish login failed")
|
||||||
f.qml.Login2PasswordErrorAbort(err.Error())
|
f.qml.Login2PasswordErrorAbort(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer f.qml.LoginFinished()
|
// The user changed should be triggerd by FinishLogin but it is not
|
||||||
|
// guaranteed when this is going to happen. Therefore we should wait
|
||||||
|
// until we receive the signal from userChanged function.
|
||||||
|
f.waitForUserChangeDone(done, user.ID())
|
||||||
|
|
||||||
|
index := f.qml.Users().indexByID(user.ID())
|
||||||
|
f.log.WithField("index", index).Debug("Login finished")
|
||||||
|
|
||||||
|
defer f.qml.LoginFinished(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FrontendQt) waitForUserChangeDone(done <-chan string, userID string) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case changedID := <-done:
|
||||||
|
if changedID == userID {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(2 * time.Second):
|
||||||
|
f.log.WithField("ID", userID).Warning("Login finished but user not added within 2 seconds")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FrontendQt) loginAbort(username string) {
|
func (f *FrontendQt) loginAbort(username string) {
|
||||||
|
|||||||
@ -64,7 +64,7 @@ type QMLBackend struct {
|
|||||||
_ func() `signal:"login2PasswordRequested"`
|
_ func() `signal:"login2PasswordRequested"`
|
||||||
_ func(errorMsg string) `signal:"login2PasswordError"`
|
_ func(errorMsg string) `signal:"login2PasswordError"`
|
||||||
_ func(errorMsg string) `signal:"login2PasswordErrorAbort"`
|
_ func(errorMsg string) `signal:"login2PasswordErrorAbort"`
|
||||||
_ func() `signal:"loginFinished"`
|
_ func(index int) `signal:"loginFinished"`
|
||||||
|
|
||||||
_ func() `signal:"internetOff"`
|
_ func() `signal:"internetOff"`
|
||||||
_ func() `signal:"internetOn"`
|
_ func() `signal:"internetOn"`
|
||||||
|
|||||||
@ -23,6 +23,7 @@ package qt
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||||
"github.com/ProtonMail/proton-bridge/internal/frontend/types"
|
"github.com/ProtonMail/proton-bridge/internal/frontend/types"
|
||||||
"github.com/therecipe/qt/core"
|
"github.com/therecipe/qt/core"
|
||||||
)
|
)
|
||||||
@ -174,6 +175,8 @@ func (um *QMLUserModel) load() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (um *QMLUserModel) userChanged(userID string) {
|
func (um *QMLUserModel) userChanged(userID string) {
|
||||||
|
defer um.f.eventListener.Emit(events.UserChangeDone, userID)
|
||||||
|
|
||||||
index := um.indexByIDNotSafe(userID)
|
index := um.indexByIDNotSafe(userID)
|
||||||
user, err := um.f.bridge.GetUser(userID)
|
user, err := um.f.bridge.GetUser(userID)
|
||||||
|
|
||||||
|
|||||||
@ -46,6 +46,18 @@ func (mr *MockListenerMockRecorder) Add(arg0, arg1 interface{}) *gomock.Call {
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockListener)(nil).Add), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockListener)(nil).Add), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Book mocks base method.
|
||||||
|
func (m *MockListener) Book(arg0 string) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
m.ctrl.Call(m, "Book", arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Book indicates an expected call of Book.
|
||||||
|
func (mr *MockListenerMockRecorder) Book(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Book", reflect.TypeOf((*MockListener)(nil).Book), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
// Emit mocks base method.
|
// Emit mocks base method.
|
||||||
func (m *MockListener) Emit(arg0, arg1 string) {
|
func (m *MockListener) Emit(arg0, arg1 string) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
|||||||
@ -46,6 +46,18 @@ func (mr *MockListenerMockRecorder) Add(arg0, arg1 interface{}) *gomock.Call {
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockListener)(nil).Add), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockListener)(nil).Add), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Book mocks base method.
|
||||||
|
func (m *MockListener) Book(arg0 string) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
m.ctrl.Call(m, "Book", arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Book indicates an expected call of Book.
|
||||||
|
func (mr *MockListenerMockRecorder) Book(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Book", reflect.TypeOf((*MockListener)(nil).Book), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
// Emit mocks base method.
|
// Emit mocks base method.
|
||||||
func (m *MockListener) Emit(arg0, arg1 string) {
|
func (m *MockListener) Emit(arg0, arg1 string) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
|||||||
@ -219,7 +219,7 @@ func (u *Users) FinishLogin(client pmapi.Client, auth *pmapi.Auth, password []by
|
|||||||
logrus.WithError(err).Warn("Failed to delete new auth session")
|
logrus.WithError(err).Warn("Failed to delete new auth session")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, ErrUserAlreadyConnected
|
return user, ErrUserAlreadyConnected
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the user's credentials with the latest auth used to connect this user.
|
// Update the user's credentials with the latest auth used to connect this user.
|
||||||
|
|||||||
@ -35,6 +35,7 @@ type Listener interface {
|
|||||||
Emit(eventName string, data string)
|
Emit(eventName string, data string)
|
||||||
SetBuffer(eventName string)
|
SetBuffer(eventName string)
|
||||||
RetryEmit(eventName string)
|
RetryEmit(eventName string)
|
||||||
|
Book(eventName string)
|
||||||
}
|
}
|
||||||
|
|
||||||
type listener struct {
|
type listener struct {
|
||||||
@ -56,6 +57,19 @@ func New() Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Book wil create the list of channels for specific eventName. This should be
|
||||||
|
// used when there is not always listening channel available and it should not
|
||||||
|
// be logged when no channel is awaiting an emitted event.
|
||||||
|
func (l *listener) Book(eventName string) {
|
||||||
|
if l.channels == nil {
|
||||||
|
l.channels = make(map[string][]chan<- string)
|
||||||
|
}
|
||||||
|
if _, ok := l.channels[eventName]; !ok {
|
||||||
|
l.channels[eventName] = []chan<- string{}
|
||||||
|
}
|
||||||
|
log.WithField("name", eventName).Debug("Channel booked")
|
||||||
|
}
|
||||||
|
|
||||||
// SetLimit sets the limit for the `eventName`. When the same event (name and data)
|
// SetLimit sets the limit for the `eventName`. When the same event (name and data)
|
||||||
// is emitted within last time duration (`limit`), event is dropped. Zero limit clears
|
// is emitted within last time duration (`limit`), event is dropped. Zero limit clears
|
||||||
// the limit for the specific `eventName`.
|
// the limit for the specific `eventName`.
|
||||||
|
|||||||
@ -59,6 +59,9 @@ func TestAddAndRemove(t *testing.T) {
|
|||||||
|
|
||||||
channel := make(chan string)
|
channel := make(chan string)
|
||||||
listener.Add("event", channel)
|
listener.Add("event", channel)
|
||||||
|
listener.Emit("event", "hello!")
|
||||||
|
checkChannelEmitted(t, channel, "hello!")
|
||||||
|
|
||||||
listener.Remove("event", channel)
|
listener.Remove("event", channel)
|
||||||
listener.Emit("event", "hello!")
|
listener.Emit("event", "hello!")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user