mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 04:36:43 +00:00
Other(refactor): Remove bridgeWrap from frontend interface
This commit is contained in:
@ -85,6 +85,8 @@ Proton Mail Bridge includes the following 3rd party software:
|
|||||||
* [grpc](https://google.golang.org/grpc) available under [license](https://github.com/grpc/grpc-go/blob/master/LICENSE)
|
* [grpc](https://google.golang.org/grpc) available under [license](https://github.com/grpc/grpc-go/blob/master/LICENSE)
|
||||||
* [protobuf](https://google.golang.org/protobuf) available under [license](https://github.com/protocolbuffers/protobuf/blob/main/LICENSE)
|
* [protobuf](https://google.golang.org/protobuf) available under [license](https://github.com/protocolbuffers/protobuf/blob/main/LICENSE)
|
||||||
* [plist](https://howett.net/plist) available under [license](https://github.com/DHowett/go-plist/blob/main/LICENSE)
|
* [plist](https://howett.net/plist) available under [license](https://github.com/DHowett/go-plist/blob/main/LICENSE)
|
||||||
|
* [juniper](https://github.com/bradenaw/juniper) available under [license](https://github.com/bradenaw/juniper/blob/master/LICENSE)
|
||||||
|
* [exp](https://golang.org/x/exp) available under [license](https://cs.opensource.google/go/x/exp/+/master:LICENSE)
|
||||||
* [go-mime](https://github.com/ProtonMail/go-mime) available under [license](https://github.com/ProtonMail/go-mime/blob/master/LICENSE)
|
* [go-mime](https://github.com/ProtonMail/go-mime) available under [license](https://github.com/ProtonMail/go-mime/blob/master/LICENSE)
|
||||||
* [cascadia](https://github.com/andybalholm/cascadia) available under [license](https://github.com/andybalholm/cascadia/blob/master/LICENSE)
|
* [cascadia](https://github.com/andybalholm/cascadia) available under [license](https://github.com/andybalholm/cascadia/blob/master/LICENSE)
|
||||||
* [antlr4](https://github.com/antlr/antlr4) available under [license](https://github.com/antlr/antlr4/blob/master/LICENSE)
|
* [antlr4](https://github.com/antlr/antlr4) available under [license](https://github.com/antlr/antlr4/blob/master/LICENSE)
|
||||||
@ -109,7 +111,6 @@ Proton Mail Bridge includes the following 3rd party software:
|
|||||||
github.com/shurcooL/sanitized_anchor_name
|
github.com/shurcooL/sanitized_anchor_name
|
||||||
* [pflag](https://github.com/spf13/pflag) available under [license](https://github.com/spf13/pflag/blob/master/LICENSE)
|
* [pflag](https://github.com/spf13/pflag) available under [license](https://github.com/spf13/pflag/blob/master/LICENSE)
|
||||||
* [tagparser](https://github.com/vmihailenco/tagparser) available under [license](https://github.com/vmihailenco/tagparser/blob/master/LICENSE)
|
* [tagparser](https://github.com/vmihailenco/tagparser) available under [license](https://github.com/vmihailenco/tagparser/blob/master/LICENSE)
|
||||||
* [xerrors](https://golang.org/x/xerrors) available under [license](https://cs.opensource.google/go/x/xerrors/+/master:LICENSE)
|
|
||||||
* [genproto](https://google.golang.org/genproto)
|
* [genproto](https://google.golang.org/genproto)
|
||||||
gopkg.in/yaml.v3
|
gopkg.in/yaml.v3
|
||||||
* [docker-credential-helpers](https://github.com/ProtonMail/docker-credential-helpers) available under [license](https://github.com/ProtonMail/docker-credential-helpers/blob/master/LICENSE)
|
* [docker-credential-helpers](https://github.com/ProtonMail/docker-credential-helpers) available under [license](https://github.com/ProtonMail/docker-credential-helpers/blob/master/LICENSE)
|
||||||
|
|||||||
10
go.mod
10
go.mod
@ -44,7 +44,7 @@ require (
|
|||||||
github.com/go-resty/resty/v2 v2.6.0
|
github.com/go-resty/resty/v2 v2.6.0
|
||||||
github.com/godbus/dbus v4.1.0+incompatible
|
github.com/godbus/dbus v4.1.0+incompatible
|
||||||
github.com/golang/mock v1.4.4
|
github.com/golang/mock v1.4.4
|
||||||
github.com/google/go-cmp v0.5.6
|
github.com/google/go-cmp v0.5.8
|
||||||
github.com/google/uuid v1.1.2
|
github.com/google/uuid v1.1.2
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e // indirect
|
github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.0
|
github.com/hashicorp/go-multierror v1.1.0
|
||||||
@ -67,13 +67,18 @@ require (
|
|||||||
go.etcd.io/bbolt v1.3.6
|
go.etcd.io/bbolt v1.3.6
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
|
||||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4
|
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4
|
||||||
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f
|
||||||
golang.org/x/text v0.3.7
|
golang.org/x/text v0.3.7
|
||||||
google.golang.org/grpc v1.46.2
|
google.golang.org/grpc v1.46.2
|
||||||
google.golang.org/protobuf v1.28.0
|
google.golang.org/protobuf v1.28.0
|
||||||
howett.net/plist v1.0.0
|
howett.net/plist v1.0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/bradenaw/juniper v0.7.0
|
||||||
|
golang.org/x/exp v0.0.0-20220823124025-807a23277127
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f // indirect
|
github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f // indirect
|
||||||
github.com/andybalholm/cascadia v1.1.0 // indirect
|
github.com/andybalholm/cascadia v1.1.0 // indirect
|
||||||
@ -99,7 +104,6 @@ require (
|
|||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/vmihailenco/tagparser v0.1.2 // indirect
|
github.com/vmihailenco/tagparser v0.1.2 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
12
go.sum
12
go.sum
@ -75,6 +75,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
|||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||||
|
github.com/bradenaw/juniper v0.7.0 h1:8JaJpY2Sm+EheEows6ZsS7s8ZM86Fa3yfaq5xXQH4SI=
|
||||||
|
github.com/bradenaw/juniper v0.7.0/go.mod h1:Z2B7aJlQ7xbfWsnMLROj5t/5FQ94/MkIdKC30J4WvzI=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
@ -221,8 +223,9 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||||
|
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
@ -500,6 +503,8 @@ golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxT
|
|||||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||||
|
golang.org/x/exp v0.0.0-20220823124025-807a23277127 h1:S4NrSKDfihhl3+4jSTgwoIevKxX9p7Iv9x++OEIptDo=
|
||||||
|
golang.org/x/exp v0.0.0-20220823124025-807a23277127/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
@ -593,8 +598,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b h1:2n253B2r0pYSmEV+UNCQoPfU/FiaizQEK5Gu4Bq4JE8=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
|
||||||
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@ -632,7 +637,6 @@ golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapK
|
|||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/v2/internal/frontend/types"
|
"github.com/ProtonMail/proton-bridge/v2/internal/users"
|
||||||
"github.com/abiosoft/ishell"
|
"github.com/abiosoft/ishell"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -35,9 +35,13 @@ func (f *frontendCLI) completeUsernames(args []string) (usernames []string) {
|
|||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
arg = args[0]
|
arg = args[0]
|
||||||
}
|
}
|
||||||
for _, user := range f.bridge.GetUsers() {
|
for _, userID := range f.bridge.GetUserIDs() {
|
||||||
if strings.HasPrefix(strings.ToLower(user.Username()), strings.ToLower(arg)) {
|
user, err := f.bridge.GetUserInfo(userID)
|
||||||
usernames = append(usernames, user.Username())
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(strings.ToLower(user.Username), strings.ToLower(arg)) {
|
||||||
|
usernames = append(usernames, user.Username)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -46,7 +50,7 @@ func (f *frontendCLI) completeUsernames(args []string) (usernames []string) {
|
|||||||
// noAccountWrapper is a decorator for functions which need any account to be properly functional.
|
// noAccountWrapper is a decorator for functions which need any account to be properly functional.
|
||||||
func (f *frontendCLI) noAccountWrapper(callback func(*ishell.Context)) func(*ishell.Context) {
|
func (f *frontendCLI) noAccountWrapper(callback func(*ishell.Context)) func(*ishell.Context) {
|
||||||
return func(c *ishell.Context) {
|
return func(c *ishell.Context) {
|
||||||
users := f.bridge.GetUsers()
|
users := f.bridge.GetUserIDs()
|
||||||
if len(users) == 0 {
|
if len(users) == 0 {
|
||||||
f.Println("No active accounts. Please add account to continue.")
|
f.Println("No active accounts. Please add account to continue.")
|
||||||
} else {
|
} else {
|
||||||
@ -55,46 +59,54 @@ func (f *frontendCLI) noAccountWrapper(callback func(*ishell.Context)) func(*ish
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *frontendCLI) askUserByIndexOrName(c *ishell.Context) types.User {
|
func (f *frontendCLI) askUserByIndexOrName(c *ishell.Context) users.UserInfo {
|
||||||
user := f.getUserByIndexOrName("")
|
user := f.getUserByIndexOrName("")
|
||||||
if user != nil {
|
if user.ID != "" {
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
numberOfAccounts := len(f.bridge.GetUsers())
|
numberOfAccounts := len(f.bridge.GetUserIDs())
|
||||||
indexRange := fmt.Sprintf("number between 0 and %d", numberOfAccounts-1)
|
indexRange := fmt.Sprintf("number between 0 and %d", numberOfAccounts-1)
|
||||||
if len(c.Args) == 0 {
|
if len(c.Args) == 0 {
|
||||||
f.Printf("Please choose %s or username.\n", indexRange)
|
f.Printf("Please choose %s or username.\n", indexRange)
|
||||||
return nil
|
return users.UserInfo{}
|
||||||
}
|
}
|
||||||
arg := c.Args[0]
|
arg := c.Args[0]
|
||||||
user = f.getUserByIndexOrName(arg)
|
user = f.getUserByIndexOrName(arg)
|
||||||
if user == nil {
|
if user.ID == "" {
|
||||||
f.Printf("Wrong input '%s'. Choose %s or username.\n", bold(arg), indexRange)
|
f.Printf("Wrong input '%s'. Choose %s or username.\n", bold(arg), indexRange)
|
||||||
return nil
|
return users.UserInfo{}
|
||||||
}
|
}
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *frontendCLI) getUserByIndexOrName(arg string) types.User {
|
func (f *frontendCLI) getUserByIndexOrName(arg string) users.UserInfo {
|
||||||
users := f.bridge.GetUsers()
|
userIDs := f.bridge.GetUserIDs()
|
||||||
numberOfAccounts := len(users)
|
numberOfAccounts := len(userIDs)
|
||||||
if numberOfAccounts == 0 {
|
if numberOfAccounts == 0 {
|
||||||
return nil
|
return users.UserInfo{}
|
||||||
|
}
|
||||||
|
res := make([]users.UserInfo, len(userIDs))
|
||||||
|
for idx, userID := range userIDs {
|
||||||
|
user, err := f.bridge.GetUserInfo(userID)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
res[idx] = user
|
||||||
}
|
}
|
||||||
if numberOfAccounts == 1 {
|
if numberOfAccounts == 1 {
|
||||||
return users[0]
|
return res[0]
|
||||||
}
|
}
|
||||||
if index, err := strconv.Atoi(arg); err == nil {
|
if index, err := strconv.Atoi(arg); err == nil {
|
||||||
if index < 0 || index >= numberOfAccounts {
|
if index < 0 || index >= numberOfAccounts {
|
||||||
return nil
|
return users.UserInfo{}
|
||||||
}
|
}
|
||||||
return users[index]
|
return res[index]
|
||||||
}
|
}
|
||||||
for _, user := range users {
|
for _, user := range res {
|
||||||
if user.Username() == arg {
|
if user.Username == arg {
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return users.UserInfo{}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,48 +23,52 @@ import (
|
|||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/v2/internal/bridge"
|
"github.com/ProtonMail/proton-bridge/v2/internal/bridge"
|
||||||
"github.com/ProtonMail/proton-bridge/v2/internal/config/settings"
|
"github.com/ProtonMail/proton-bridge/v2/internal/config/settings"
|
||||||
"github.com/ProtonMail/proton-bridge/v2/internal/frontend/types"
|
"github.com/ProtonMail/proton-bridge/v2/internal/users"
|
||||||
"github.com/abiosoft/ishell"
|
"github.com/abiosoft/ishell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (f *frontendCLI) listAccounts(c *ishell.Context) {
|
func (f *frontendCLI) listAccounts(c *ishell.Context) {
|
||||||
spacing := "%-2d: %-20s (%-15s, %-15s)\n"
|
spacing := "%-2d: %-20s (%-15s, %-15s)\n"
|
||||||
f.Printf(bold(strings.ReplaceAll(spacing, "d", "s")), "#", "account", "status", "address mode")
|
f.Printf(bold(strings.ReplaceAll(spacing, "d", "s")), "#", "account", "status", "address mode")
|
||||||
for idx, user := range f.bridge.GetUsers() {
|
for idx, userID := range f.bridge.GetUserIDs() {
|
||||||
|
user, err := f.bridge.GetUserInfo(userID)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
connected := "disconnected"
|
connected := "disconnected"
|
||||||
if user.IsConnected() {
|
if user.Connected {
|
||||||
connected = "connected"
|
connected = "connected"
|
||||||
}
|
}
|
||||||
mode := "split"
|
mode := "split"
|
||||||
if user.IsCombinedAddressMode() {
|
if user.Mode == users.CombinedMode {
|
||||||
mode = "combined"
|
mode = "combined"
|
||||||
}
|
}
|
||||||
f.Printf(spacing, idx, user.Username(), connected, mode)
|
f.Printf(spacing, idx, user.Username, connected, mode)
|
||||||
}
|
}
|
||||||
f.Println()
|
f.Println()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *frontendCLI) showAccountInfo(c *ishell.Context) {
|
func (f *frontendCLI) showAccountInfo(c *ishell.Context) {
|
||||||
user := f.askUserByIndexOrName(c)
|
user := f.askUserByIndexOrName(c)
|
||||||
if user == nil {
|
if user.ID == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.IsConnected() {
|
if !user.Connected {
|
||||||
f.Printf("Please login to %s to get email client configuration.\n", bold(user.Username()))
|
f.Printf("Please login to %s to get email client configuration.\n", bold(user.Username))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.IsCombinedAddressMode() {
|
if user.Mode == users.CombinedMode {
|
||||||
f.showAccountAddressInfo(user, user.GetPrimaryAddress())
|
f.showAccountAddressInfo(user, user.Addresses[user.Primary])
|
||||||
} else {
|
} else {
|
||||||
for _, address := range user.GetAddresses() {
|
for _, address := range user.Addresses {
|
||||||
f.showAccountAddressInfo(user, address)
|
f.showAccountAddressInfo(user, address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *frontendCLI) showAccountAddressInfo(user types.User, address string) {
|
func (f *frontendCLI) showAccountAddressInfo(user users.UserInfo, address string) {
|
||||||
smtpSecurity := "STARTTLS"
|
smtpSecurity := "STARTTLS"
|
||||||
if f.bridge.GetBool(settings.SMTPSSLKey) {
|
if f.bridge.GetBool(settings.SMTPSSLKey) {
|
||||||
smtpSecurity = "SSL"
|
smtpSecurity = "SSL"
|
||||||
@ -74,7 +78,7 @@ func (f *frontendCLI) showAccountAddressInfo(user types.User, address string) {
|
|||||||
bridge.Host,
|
bridge.Host,
|
||||||
f.bridge.GetInt(settings.IMAPPortKey),
|
f.bridge.GetInt(settings.IMAPPortKey),
|
||||||
address,
|
address,
|
||||||
user.GetBridgePassword(),
|
user.Password,
|
||||||
"STARTTLS",
|
"STARTTLS",
|
||||||
)
|
)
|
||||||
f.Println("")
|
f.Println("")
|
||||||
@ -82,7 +86,7 @@ func (f *frontendCLI) showAccountAddressInfo(user types.User, address string) {
|
|||||||
bridge.Host,
|
bridge.Host,
|
||||||
f.bridge.GetInt(settings.SMTPPortKey),
|
f.bridge.GetInt(settings.SMTPPortKey),
|
||||||
address,
|
address,
|
||||||
user.GetBridgePassword(),
|
user.Password,
|
||||||
smtpSecurity,
|
smtpSecurity,
|
||||||
)
|
)
|
||||||
f.Println("")
|
f.Println("")
|
||||||
@ -95,8 +99,8 @@ func (f *frontendCLI) loginAccount(c *ishell.Context) { //nolint:funlen
|
|||||||
loginName := ""
|
loginName := ""
|
||||||
if len(c.Args) > 0 {
|
if len(c.Args) > 0 {
|
||||||
user := f.getUserByIndexOrName(c.Args[0])
|
user := f.getUserByIndexOrName(c.Args[0])
|
||||||
if user != nil {
|
if user.ID != "" {
|
||||||
loginName = user.GetPrimaryAddress()
|
loginName = user.Addresses[user.Primary]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,14 +147,19 @@ func (f *frontendCLI) loginAccount(c *ishell.Context) { //nolint:funlen
|
|||||||
}
|
}
|
||||||
|
|
||||||
f.Println("Adding account ...")
|
f.Println("Adding account ...")
|
||||||
user, err := f.bridge.FinishLogin(client, auth, []byte(mailboxPassword))
|
userID, err := f.bridge.FinishLogin(client, auth, []byte(mailboxPassword))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithField("username", loginName).WithError(err).Error("Login was unsuccessful")
|
log.WithField("username", loginName).WithError(err).Error("Login was unsuccessful")
|
||||||
f.Println("Adding account was unsuccessful:", err)
|
f.Println("Adding account was unsuccessful:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f.Printf("Account %s was added successfully.\n", bold(user.Username()))
|
user, err := f.bridge.GetUserInfo(userID)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Printf("Account %s was added successfully.\n", bold(user.Username))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *frontendCLI) logoutAccount(c *ishell.Context) {
|
func (f *frontendCLI) logoutAccount(c *ishell.Context) {
|
||||||
@ -158,11 +167,11 @@ func (f *frontendCLI) logoutAccount(c *ishell.Context) {
|
|||||||
defer f.ShowPrompt(true)
|
defer f.ShowPrompt(true)
|
||||||
|
|
||||||
user := f.askUserByIndexOrName(c)
|
user := f.askUserByIndexOrName(c)
|
||||||
if user == nil {
|
if user.ID == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if f.yesNoQuestion("Are you sure you want to logout account " + bold(user.Username())) {
|
if f.yesNoQuestion("Are you sure you want to logout account " + bold(user.Username)) {
|
||||||
if err := user.Logout(); err != nil {
|
if err := f.bridge.LogoutUser(user.ID); err != nil {
|
||||||
f.printAndLogError("Logging out failed: ", err)
|
f.printAndLogError("Logging out failed: ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,12 +182,12 @@ func (f *frontendCLI) deleteAccount(c *ishell.Context) {
|
|||||||
defer f.ShowPrompt(true)
|
defer f.ShowPrompt(true)
|
||||||
|
|
||||||
user := f.askUserByIndexOrName(c)
|
user := f.askUserByIndexOrName(c)
|
||||||
if user == nil {
|
if user.ID == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if f.yesNoQuestion("Are you sure you want to " + bold("remove account "+user.Username())) {
|
if f.yesNoQuestion("Are you sure you want to " + bold("remove account "+user.Username)) {
|
||||||
clearCache := f.yesNoQuestion("Do you want to remove cache for this account")
|
clearCache := f.yesNoQuestion("Do you want to remove cache for this account")
|
||||||
if err := f.bridge.DeleteUser(user.ID(), clearCache); err != nil {
|
if err := f.bridge.DeleteUser(user.ID, clearCache); err != nil {
|
||||||
f.printAndLogError("Cannot delete account: ", err)
|
f.printAndLogError("Cannot delete account: ", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -193,9 +202,13 @@ func (f *frontendCLI) deleteAccounts(c *ishell.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, user := range f.bridge.GetUsers() {
|
for _, userID := range f.bridge.GetUserIDs() {
|
||||||
if err := f.bridge.DeleteUser(user.ID(), false); err != nil {
|
user, err := f.bridge.GetUserInfo(userID)
|
||||||
f.printAndLogError("Cannot delete account ", user.Username(), ": ", err)
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if err := f.bridge.DeleteUser(user.ID, false); err != nil {
|
||||||
|
f.printAndLogError("Cannot delete account ", user.Username, ": ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,19 +235,25 @@ func (f *frontendCLI) deleteEverything(c *ishell.Context) {
|
|||||||
|
|
||||||
func (f *frontendCLI) changeMode(c *ishell.Context) {
|
func (f *frontendCLI) changeMode(c *ishell.Context) {
|
||||||
user := f.askUserByIndexOrName(c)
|
user := f.askUserByIndexOrName(c)
|
||||||
if user == nil {
|
if user.ID == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
newMode := "combined mode"
|
var targetMode users.AddressMode
|
||||||
if user.IsCombinedAddressMode() {
|
|
||||||
newMode = "split mode"
|
if user.Mode == users.CombinedMode {
|
||||||
|
targetMode = users.SplitMode
|
||||||
|
} else {
|
||||||
|
targetMode = users.CombinedMode
|
||||||
}
|
}
|
||||||
if !f.yesNoQuestion("Are you sure you want to change the mode for account " + bold(user.Username()) + " to " + bold(newMode)) {
|
|
||||||
|
if !f.yesNoQuestion("Are you sure you want to change the mode for account " + bold(user.Username) + " to " + bold(targetMode)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := user.SwitchAddressMode(); err != nil {
|
|
||||||
|
if err := f.bridge.SetAddressMode(user.ID, targetMode); err != nil {
|
||||||
f.printAndLogError("Cannot switch address mode:", err)
|
f.printAndLogError("Cannot switch address mode:", err)
|
||||||
}
|
}
|
||||||
f.Printf("Address mode for account %s changed to %s\n", user.Username(), newMode)
|
|
||||||
|
f.Printf("Address mode for account %s changed to %s\n", user.Username, targetMode)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -307,11 +307,11 @@ func (f *frontendCLI) watchEvents() {
|
|||||||
case address := <-addressChangedLogoutCh:
|
case address := <-addressChangedLogoutCh:
|
||||||
f.notifyLogout(address)
|
f.notifyLogout(address)
|
||||||
case userID := <-logoutCh:
|
case userID := <-logoutCh:
|
||||||
user, err := f.bridge.GetUser(userID)
|
user, err := f.bridge.GetUserInfo(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
f.notifyLogout(user.Username())
|
f.notifyLogout(user.Username)
|
||||||
case <-certIssue:
|
case <-certIssue:
|
||||||
f.notifyCertIssue()
|
f.notifyCertIssue()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,7 +46,6 @@ func New(
|
|||||||
bridge *bridge.Bridge,
|
bridge *bridge.Bridge,
|
||||||
restarter types.Restarter,
|
restarter types.Restarter,
|
||||||
) Frontend {
|
) Frontend {
|
||||||
bridgeWrap := types.NewBridgeWrap(bridge)
|
|
||||||
switch frontendType {
|
switch frontendType {
|
||||||
case "grpc":
|
case "grpc":
|
||||||
return grpc.NewService(
|
return grpc.NewService(
|
||||||
@ -54,7 +53,7 @@ func New(
|
|||||||
panicHandler,
|
panicHandler,
|
||||||
eventListener,
|
eventListener,
|
||||||
updater,
|
updater,
|
||||||
bridgeWrap,
|
bridge,
|
||||||
restarter,
|
restarter,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -63,7 +62,7 @@ func New(
|
|||||||
panicHandler,
|
panicHandler,
|
||||||
eventListener,
|
eventListener,
|
||||||
updater,
|
updater,
|
||||||
bridgeWrap,
|
bridge,
|
||||||
restarter,
|
restarter,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ package grpc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
|
|
||||||
grpc "google.golang.org/grpc"
|
grpc "google.golang.org/grpc"
|
||||||
codes "google.golang.org/grpc/codes"
|
codes "google.golang.org/grpc/codes"
|
||||||
status "google.golang.org/grpc/status"
|
status "google.golang.org/grpc/status"
|
||||||
|
|||||||
@ -229,11 +229,11 @@ func (s *Service) watchEvents() { // nolint:funlen
|
|||||||
case address := <-addressChangedLogoutCh:
|
case address := <-addressChangedLogoutCh:
|
||||||
_ = s.SendEvent(NewMailAddressChangeLogoutEvent(address))
|
_ = s.SendEvent(NewMailAddressChangeLogoutEvent(address))
|
||||||
case userID := <-logoutCh:
|
case userID := <-logoutCh:
|
||||||
user, err := s.bridge.GetUser(userID)
|
user, err := s.bridge.GetUserInfo(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = s.SendEvent(NewUserDisconnectedEvent(user.Username()))
|
_ = s.SendEvent(NewUserDisconnectedEvent(user.Username))
|
||||||
case <-updateApplicationCh:
|
case <-updateApplicationCh:
|
||||||
s.updateForce()
|
s.updateForce()
|
||||||
case userID := <-userChangedCh:
|
case userID := <-userChangedCh:
|
||||||
@ -275,7 +275,7 @@ func (s *Service) finishLogin() {
|
|||||||
s.eventListener.Add(events.UserChangeDone, done)
|
s.eventListener.Add(events.UserChangeDone, done)
|
||||||
defer s.eventListener.Remove(events.UserChangeDone, done)
|
defer s.eventListener.Remove(events.UserChangeDone, done)
|
||||||
|
|
||||||
user, err := s.bridge.FinishLogin(s.authClient, s.auth, s.password)
|
userID, err := s.bridge.FinishLogin(s.authClient, s.auth, s.password)
|
||||||
|
|
||||||
if err != nil && err != users.ErrUserAlreadyConnected {
|
if err != nil && err != users.ErrUserAlreadyConnected {
|
||||||
s.log.WithError(err).Errorf("Finish login failed")
|
s.log.WithError(err).Errorf("Finish login failed")
|
||||||
@ -286,14 +286,14 @@ func (s *Service) finishLogin() {
|
|||||||
// The user changed should be triggered by FinishLogin, but it is not
|
// The user changed should be triggered by FinishLogin, but it is not
|
||||||
// guaranteed when this is going to happen. Therefor we should wait
|
// guaranteed when this is going to happen. Therefor we should wait
|
||||||
// until we receive the signal from userChanged function.
|
// until we receive the signal from userChanged function.
|
||||||
s.waitForUserChangeDone(done, user.ID())
|
s.waitForUserChangeDone(done, userID)
|
||||||
|
|
||||||
s.log.WithField("userID", user.ID()).Debug("Login finished")
|
s.log.WithField("userID", userID).Debug("Login finished")
|
||||||
_ = s.SendEvent(NewLoginFinishedEvent(user.ID()))
|
_ = s.SendEvent(NewLoginFinishedEvent(userID))
|
||||||
|
|
||||||
if err == users.ErrUserAlreadyConnected {
|
if err == users.ErrUserAlreadyConnected {
|
||||||
s.log.WithError(err).Error("User already logged in")
|
s.log.WithError(err).Error("User already logged in")
|
||||||
_ = s.SendEvent(NewLoginAlreadyLoggedInEvent(user.ID()))
|
_ = s.SendEvent(NewLoginAlreadyLoggedInEvent(userID))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ProtonMail/proton-bridge/v2/internal/users"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
"google.golang.org/protobuf/types/known/emptypb"
|
"google.golang.org/protobuf/types/known/emptypb"
|
||||||
@ -30,11 +32,15 @@ import (
|
|||||||
func (s *Service) GetUserList(context.Context, *emptypb.Empty) (*UserListResponse, error) {
|
func (s *Service) GetUserList(context.Context, *emptypb.Empty) (*UserListResponse, error) {
|
||||||
s.log.Info("GetUserList")
|
s.log.Info("GetUserList")
|
||||||
|
|
||||||
users := s.bridge.GetUsers()
|
var userList []*User
|
||||||
|
|
||||||
userList := make([]*User, len(users))
|
for idx, userID := range s.bridge.GetUserIDs() {
|
||||||
for i, user := range users {
|
user, err := s.bridge.GetUserInfo(userID)
|
||||||
userList[i] = grpcUserFromBridge(user)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userList[idx] = grpcUserFromInfo(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are no active accounts.
|
// If there are no active accounts.
|
||||||
@ -48,18 +54,18 @@ func (s *Service) GetUserList(context.Context, *emptypb.Empty) (*UserListRespons
|
|||||||
func (s *Service) GetUser(_ context.Context, userID *wrapperspb.StringValue) (*User, error) {
|
func (s *Service) GetUser(_ context.Context, userID *wrapperspb.StringValue) (*User, error) {
|
||||||
s.log.WithField("userID", userID).Info("GetUser")
|
s.log.WithField("userID", userID).Info("GetUser")
|
||||||
|
|
||||||
user, err := s.bridge.GetUser(userID.Value)
|
user, err := s.bridge.GetUserInfo(userID.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Errorf(codes.NotFound, "user not found %v", userID.Value)
|
return nil, status.Errorf(codes.NotFound, "user not found %v", userID.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
return grpcUserFromBridge(user), nil
|
return grpcUserFromInfo(user), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) SetUserSplitMode(_ context.Context, splitMode *UserSplitModeRequest) (*emptypb.Empty, error) {
|
func (s *Service) SetUserSplitMode(_ context.Context, splitMode *UserSplitModeRequest) (*emptypb.Empty, error) {
|
||||||
s.log.WithField("UserID", splitMode.UserID).WithField("Active", splitMode.Active).Info("SetUserSplitMode")
|
s.log.WithField("UserID", splitMode.UserID).WithField("Active", splitMode.Active).Info("SetUserSplitMode")
|
||||||
|
|
||||||
user, err := s.bridge.GetUser(splitMode.UserID)
|
user, err := s.bridge.GetUserInfo(splitMode.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Errorf(codes.NotFound, "user not found %v", splitMode.UserID)
|
return nil, status.Errorf(codes.NotFound, "user not found %v", splitMode.UserID)
|
||||||
}
|
}
|
||||||
@ -67,8 +73,17 @@ func (s *Service) SetUserSplitMode(_ context.Context, splitMode *UserSplitModeRe
|
|||||||
go func() {
|
go func() {
|
||||||
defer s.panicHandler.HandlePanic()
|
defer s.panicHandler.HandlePanic()
|
||||||
defer func() { _ = s.SendEvent(NewUserToggleSplitModeFinishedEvent(splitMode.UserID)) }()
|
defer func() { _ = s.SendEvent(NewUserToggleSplitModeFinishedEvent(splitMode.UserID)) }()
|
||||||
if splitMode.Active == user.IsCombinedAddressMode() {
|
|
||||||
_ = user.SwitchAddressMode() // check for errors
|
var targetMode users.AddressMode
|
||||||
|
|
||||||
|
if splitMode.Active && user.Mode == users.CombinedMode {
|
||||||
|
targetMode = users.SplitMode
|
||||||
|
} else if !splitMode.Active && user.Mode == users.SplitMode {
|
||||||
|
targetMode = users.CombinedMode
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.bridge.SetAddressMode(user.ID, targetMode); err != nil {
|
||||||
|
logrus.WithError(err).Error("Failed to set address mode")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -78,14 +93,16 @@ func (s *Service) SetUserSplitMode(_ context.Context, splitMode *UserSplitModeRe
|
|||||||
func (s *Service) LogoutUser(_ context.Context, userID *wrapperspb.StringValue) (*emptypb.Empty, error) {
|
func (s *Service) LogoutUser(_ context.Context, userID *wrapperspb.StringValue) (*emptypb.Empty, error) {
|
||||||
s.log.WithField("UserID", userID.Value).Info("LogoutUser")
|
s.log.WithField("UserID", userID.Value).Info("LogoutUser")
|
||||||
|
|
||||||
user, err := s.bridge.GetUser(userID.Value)
|
if _, err := s.bridge.GetUserInfo(userID.Value); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.NotFound, "user not found %v", userID.Value)
|
return nil, status.Errorf(codes.NotFound, "user not found %v", userID.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer s.panicHandler.HandlePanic()
|
defer s.panicHandler.HandlePanic()
|
||||||
_ = user.Logout()
|
|
||||||
|
if err := s.bridge.LogoutUser(userID.Value); err != nil {
|
||||||
|
logrus.WithError(err).Error("Failed to log user out")
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return &emptypb.Empty{}, nil
|
return &emptypb.Empty{}, nil
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/v2/internal/frontend/types"
|
"github.com/ProtonMail/proton-bridge/v2/internal/users"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -57,19 +57,19 @@ func getInitials(fullName string) string {
|
|||||||
return strings.ToUpper(initials)
|
return strings.ToUpper(initials)
|
||||||
}
|
}
|
||||||
|
|
||||||
// grpcUserFromBridge converts a bridge user to a gRPC user.
|
// grpcUserFromInfo converts a bridge user to a gRPC user.
|
||||||
func grpcUserFromBridge(user types.User) *User {
|
func grpcUserFromInfo(user users.UserInfo) *User {
|
||||||
return &User{
|
return &User{
|
||||||
Id: user.ID(),
|
Id: user.ID,
|
||||||
Username: user.Username(),
|
Username: user.Username,
|
||||||
AvatarText: getInitials(user.Username()),
|
AvatarText: getInitials(user.Username),
|
||||||
LoggedIn: user.IsConnected(),
|
LoggedIn: user.Connected,
|
||||||
SplitMode: !user.IsCombinedAddressMode(),
|
SplitMode: user.Mode == users.SplitMode,
|
||||||
SetupGuideSeen: true, // users listed have already seen the setup guide.
|
SetupGuideSeen: true, // users listed have already seen the setup guide.
|
||||||
UsedBytes: user.UsedBytes(),
|
UsedBytes: user.UsedBytes,
|
||||||
TotalBytes: user.TotalBytes(),
|
TotalBytes: user.TotalBytes,
|
||||||
Password: user.GetBridgePassword(),
|
Password: user.Password,
|
||||||
Addresses: user.GetAddresses(),
|
Addresses: user.Addresses,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,9 +21,9 @@ package types
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/v2/internal/bridge"
|
|
||||||
"github.com/ProtonMail/proton-bridge/v2/internal/config/settings"
|
"github.com/ProtonMail/proton-bridge/v2/internal/config/settings"
|
||||||
"github.com/ProtonMail/proton-bridge/v2/internal/updater"
|
"github.com/ProtonMail/proton-bridge/v2/internal/updater"
|
||||||
|
"github.com/ProtonMail/proton-bridge/v2/internal/users"
|
||||||
"github.com/ProtonMail/proton-bridge/v2/pkg/pmapi"
|
"github.com/ProtonMail/proton-bridge/v2/pkg/pmapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -45,39 +45,22 @@ type Updater interface {
|
|||||||
CanInstall(updater.VersionInfo) bool
|
CanInstall(updater.VersionInfo) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserManager is an interface of users needed by frontend.
|
// Bridger is an interface of bridge needed by frontend.
|
||||||
type UserManager interface {
|
type Bridger interface {
|
||||||
Login(username string, password []byte) (pmapi.Client, *pmapi.Auth, error)
|
Login(username string, password []byte) (pmapi.Client, *pmapi.Auth, error)
|
||||||
FinishLogin(client pmapi.Client, auth *pmapi.Auth, mailboxPassword []byte) (User, error)
|
FinishLogin(client pmapi.Client, auth *pmapi.Auth, mailboxPassword []byte) (string, error)
|
||||||
GetUsers() []User
|
|
||||||
GetUser(query string) (User, error)
|
GetUserIDs() []string
|
||||||
|
GetUserInfo(string) (users.UserInfo, error)
|
||||||
|
LogoutUser(userID string) error
|
||||||
DeleteUser(userID string, clearCache bool) error
|
DeleteUser(userID string, clearCache bool) error
|
||||||
|
SetAddressMode(userID string, split users.AddressMode) error
|
||||||
|
|
||||||
ClearData() error
|
ClearData() error
|
||||||
ClearUsers() error
|
ClearUsers() error
|
||||||
FactoryReset()
|
FactoryReset()
|
||||||
}
|
|
||||||
|
|
||||||
// User is an interface of user needed by frontend.
|
|
||||||
type User interface {
|
|
||||||
ID() string
|
|
||||||
UsedBytes() int64
|
|
||||||
TotalBytes() int64
|
|
||||||
Username() string
|
|
||||||
IsConnected() bool
|
|
||||||
IsCombinedAddressMode() bool
|
|
||||||
GetPrimaryAddress() string
|
|
||||||
GetAddresses() []string
|
|
||||||
GetBridgePassword() string
|
|
||||||
SwitchAddressMode() error
|
|
||||||
Logout() error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bridger is an interface of bridge needed by frontend.
|
|
||||||
type Bridger interface {
|
|
||||||
UserManager
|
|
||||||
|
|
||||||
GetTLSConfig() (*tls.Config, error)
|
GetTLSConfig() (*tls.Config, error)
|
||||||
|
|
||||||
ProvideLogsPath() (string, error)
|
ProvideLogsPath() (string, error)
|
||||||
GetLicenseFilePath() string
|
GetLicenseFilePath() string
|
||||||
GetDependencyLicensesLink() string
|
GetDependencyLicensesLink() string
|
||||||
@ -115,29 +98,3 @@ type Bridger interface {
|
|||||||
IsAllMailVisible() bool
|
IsAllMailVisible() bool
|
||||||
SetIsAllMailVisible(bool)
|
SetIsAllMailVisible(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
type bridgeWrap struct {
|
|
||||||
*bridge.Bridge
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBridgeWrap wraps bridge struct into local bridgeWrap to implement local interface.
|
|
||||||
// The problem is that Bridge returns the bridge package's User type.
|
|
||||||
// Every method which returns User therefore has to be overridden to fulfill the interface.
|
|
||||||
func NewBridgeWrap(bridge *bridge.Bridge) *bridgeWrap { //nolint:revive
|
|
||||||
return &bridgeWrap{Bridge: bridge}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bridgeWrap) FinishLogin(client pmapi.Client, auth *pmapi.Auth, mailboxPassword []byte) (User, error) {
|
|
||||||
return b.Bridge.FinishLogin(client, auth, mailboxPassword)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bridgeWrap) GetUsers() (users []User) {
|
|
||||||
for _, user := range b.Bridge.GetUsers() {
|
|
||||||
users = append(users, user)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bridgeWrap) GetUser(query string) (User, error) {
|
|
||||||
return b.Bridge.GetUser(query)
|
|
||||||
}
|
|
||||||
|
|||||||
@ -46,3 +46,38 @@ type StoreMaker interface {
|
|||||||
New(user store.BridgeUser) (*store.Store, error)
|
New(user store.BridgeUser) (*store.Store, error)
|
||||||
Remove(userID string) error
|
Remove(userID string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserInfo struct {
|
||||||
|
ID string
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
|
||||||
|
Addresses []string
|
||||||
|
Primary int
|
||||||
|
|
||||||
|
UsedBytes int64
|
||||||
|
TotalBytes int64
|
||||||
|
|
||||||
|
Connected bool
|
||||||
|
Mode AddressMode
|
||||||
|
}
|
||||||
|
|
||||||
|
type AddressMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SplitMode AddressMode = iota
|
||||||
|
CombinedMode
|
||||||
|
)
|
||||||
|
|
||||||
|
func (mode AddressMode) String() string {
|
||||||
|
switch mode {
|
||||||
|
case SplitMode:
|
||||||
|
return "split mode"
|
||||||
|
|
||||||
|
case CombinedMode:
|
||||||
|
return "combined mode"
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "unknown mode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -30,9 +30,11 @@ import (
|
|||||||
"github.com/ProtonMail/proton-bridge/v2/pkg/keychain"
|
"github.com/ProtonMail/proton-bridge/v2/pkg/keychain"
|
||||||
"github.com/ProtonMail/proton-bridge/v2/pkg/listener"
|
"github.com/ProtonMail/proton-bridge/v2/pkg/listener"
|
||||||
"github.com/ProtonMail/proton-bridge/v2/pkg/pmapi"
|
"github.com/ProtonMail/proton-bridge/v2/pkg/pmapi"
|
||||||
|
"github.com/bradenaw/juniper/xslices"
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
logrus "github.com/sirupsen/logrus"
|
logrus "github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -215,10 +217,10 @@ func (u *Users) Login(username string, password []byte) (authClient pmapi.Client
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FinishLogin finishes the login procedure and adds the user into the credentials store.
|
// FinishLogin finishes the login procedure and adds the user into the credentials store.
|
||||||
func (u *Users) FinishLogin(client pmapi.Client, auth *pmapi.Auth, password []byte) (user *User, err error) { //nolint:funlen
|
func (u *Users) FinishLogin(client pmapi.Client, auth *pmapi.Auth, password []byte) (userID string, err error) { //nolint:funlen
|
||||||
apiUser, passphrase, err := getAPIUser(context.Background(), client, password)
|
apiUser, passphrase, err := getAPIUser(context.Background(), client, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if user, ok := u.hasUser(apiUser.ID); ok {
|
if user, ok := u.hasUser(apiUser.ID); ok {
|
||||||
@ -227,39 +229,39 @@ 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 user, ErrUserAlreadyConnected
|
return user.ID(), 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.
|
||||||
if _, err := u.credStorer.UpdateToken(auth.UserID, auth.UID, auth.RefreshToken); err != nil {
|
if _, err := u.credStorer.UpdateToken(auth.UserID, auth.UID, auth.RefreshToken); err != nil {
|
||||||
notifyKeychainRepair(u.events, err)
|
notifyKeychainRepair(u.events, err)
|
||||||
return nil, errors.Wrap(err, "failed to load user credentials")
|
return "", errors.Wrap(err, "failed to load user credentials")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the password in case the user changed it.
|
// Update the password in case the user changed it.
|
||||||
creds, err := u.credStorer.UpdatePassword(apiUser.ID, passphrase)
|
creds, err := u.credStorer.UpdatePassword(apiUser.ID, passphrase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
notifyKeychainRepair(u.events, err)
|
notifyKeychainRepair(u.events, err)
|
||||||
return nil, errors.Wrap(err, "failed to update password of user in credentials store")
|
return "", errors.Wrap(err, "failed to update password of user in credentials store")
|
||||||
}
|
}
|
||||||
|
|
||||||
// will go and unlock cache if not already done
|
// will go and unlock cache if not already done
|
||||||
if err := user.connect(client, creds); err != nil {
|
if err := user.connect(client, creds); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to reconnect existing user")
|
return "", errors.Wrap(err, "failed to reconnect existing user")
|
||||||
}
|
}
|
||||||
|
|
||||||
u.events.Emit(events.UserRefreshEvent, apiUser.ID)
|
u.events.Emit(events.UserRefreshEvent, apiUser.ID)
|
||||||
|
|
||||||
return user, nil
|
return user.ID(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := u.addNewUser(client, apiUser, auth, passphrase); err != nil {
|
if err := u.addNewUser(client, apiUser, auth, passphrase); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to add new user")
|
return "", errors.Wrap(err, "failed to add new user")
|
||||||
}
|
}
|
||||||
|
|
||||||
u.events.Emit(events.UserRefreshEvent, apiUser.ID)
|
u.events.Emit(events.UserRefreshEvent, apiUser.ID)
|
||||||
|
|
||||||
return u.GetUser(apiUser.ID)
|
return apiUser.ID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// addNewUser adds a new user.
|
// addNewUser adds a new user.
|
||||||
@ -322,6 +324,16 @@ func (u *Users) GetUsers() []*User {
|
|||||||
return u.users
|
return u.users
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUserIDs returns IDs of all added users into keychain (even logged out users).
|
||||||
|
func (u *Users) GetUserIDs() []string {
|
||||||
|
u.lock.RLock()
|
||||||
|
defer u.lock.RUnlock()
|
||||||
|
|
||||||
|
return xslices.Map(u.users, func(user *User) string {
|
||||||
|
return user.ID()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// GetUser returns a user by `query` which is compared to users' ID, username or any attached e-mail address.
|
// GetUser returns a user by `query` which is compared to users' ID, username or any attached e-mail address.
|
||||||
func (u *Users) GetUser(query string) (*User, error) {
|
func (u *Users) GetUser(query string) (*User, error) {
|
||||||
u.crashBandicoot(query)
|
u.crashBandicoot(query)
|
||||||
@ -343,6 +355,44 @@ func (u *Users) GetUser(query string) (*User, error) {
|
|||||||
return nil, errors.New("user " + query + " not found")
|
return nil, errors.New("user " + query + " not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUserInfo returns user about the user with the given ID.
|
||||||
|
func (u *Users) GetUserInfo(userID string) (UserInfo, error) {
|
||||||
|
u.lock.RLock()
|
||||||
|
defer u.lock.RUnlock()
|
||||||
|
|
||||||
|
idx := slices.IndexFunc(u.users, func(user *User) bool {
|
||||||
|
return user.userID == userID
|
||||||
|
})
|
||||||
|
if idx < 0 {
|
||||||
|
return UserInfo{}, errors.New("no such user")
|
||||||
|
}
|
||||||
|
|
||||||
|
user := u.users[idx]
|
||||||
|
|
||||||
|
var mode AddressMode
|
||||||
|
|
||||||
|
if user.IsCombinedAddressMode() {
|
||||||
|
mode = CombinedMode
|
||||||
|
} else {
|
||||||
|
mode = SplitMode
|
||||||
|
}
|
||||||
|
|
||||||
|
return UserInfo{
|
||||||
|
ID: userID,
|
||||||
|
Username: user.Username(),
|
||||||
|
Password: user.GetBridgePassword(),
|
||||||
|
|
||||||
|
Addresses: user.GetAddresses(),
|
||||||
|
Primary: slices.Index(user.GetAddresses(), user.GetPrimaryAddress()),
|
||||||
|
|
||||||
|
UsedBytes: user.UsedBytes(),
|
||||||
|
TotalBytes: user.TotalBytes(),
|
||||||
|
|
||||||
|
Connected: user.IsConnected(),
|
||||||
|
Mode: mode,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ClearData closes all connections (to release db files and so on) and clears all data.
|
// ClearData closes all connections (to release db files and so on) and clears all data.
|
||||||
func (u *Users) ClearData() error {
|
func (u *Users) ClearData() error {
|
||||||
var result error
|
var result error
|
||||||
@ -364,6 +414,42 @@ func (u *Users) ClearData() error {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *Users) LogoutUser(userID string) error {
|
||||||
|
u.lock.RLock()
|
||||||
|
defer u.lock.RUnlock()
|
||||||
|
|
||||||
|
idx := slices.IndexFunc(u.users, func(user *User) bool {
|
||||||
|
return user.userID == userID
|
||||||
|
})
|
||||||
|
if idx < 0 {
|
||||||
|
return errors.New("no such user")
|
||||||
|
}
|
||||||
|
|
||||||
|
return u.users[idx].Logout()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Users) SetAddressMode(userID string, mode AddressMode) error {
|
||||||
|
u.lock.RLock()
|
||||||
|
defer u.lock.RUnlock()
|
||||||
|
|
||||||
|
idx := slices.IndexFunc(u.users, func(user *User) bool {
|
||||||
|
return user.userID == userID
|
||||||
|
})
|
||||||
|
if idx < 0 {
|
||||||
|
return errors.New("no such user")
|
||||||
|
}
|
||||||
|
|
||||||
|
if mode == CombinedMode && u.users[idx].IsCombinedAddressMode() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if mode == SplitMode && !u.users[idx].IsCombinedAddressMode() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return u.users[idx].SwitchAddressMode()
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteUser deletes user completely; it logs user out from the API, stops any
|
// DeleteUser deletes user completely; it logs user out from the API, stops any
|
||||||
// active connection, deletes from credentials store and removes from the Bridge struct.
|
// active connection, deletes from credentials store and removes from the Bridge struct.
|
||||||
func (u *Users) DeleteUser(userID string, clearStore bool) error {
|
func (u *Users) DeleteUser(userID string, clearStore bool) error {
|
||||||
|
|||||||
@ -117,16 +117,16 @@ func checkUsersFinishLogin(t *testing.T, m mocks, auth *pmapi.Auth, mailboxPassw
|
|||||||
users := testNewUsers(t, m)
|
users := testNewUsers(t, m)
|
||||||
defer cleanUpUsersData(users)
|
defer cleanUpUsersData(users)
|
||||||
|
|
||||||
user, err := users.FinishLogin(m.pmapiClient, auth, mailboxPassword)
|
userID, err := users.FinishLogin(m.pmapiClient, auth, mailboxPassword)
|
||||||
|
|
||||||
r.Equal(t, expectedErr, err)
|
r.Equal(t, expectedErr, err)
|
||||||
|
|
||||||
if expectedUserID != "" {
|
if expectedUserID != "" {
|
||||||
r.Equal(t, expectedUserID, user.ID())
|
r.Equal(t, expectedUserID, userID)
|
||||||
r.Equal(t, 1, len(users.users))
|
r.Equal(t, 1, len(users.users))
|
||||||
r.Equal(t, expectedUserID, users.users[0].ID())
|
r.Equal(t, expectedUserID, users.users[0].ID())
|
||||||
} else {
|
} else {
|
||||||
r.Equal(t, (*User)(nil), user)
|
r.Equal(t, "", userID)
|
||||||
r.Equal(t, 0, len(users.users))
|
r.Equal(t, 0, len(users.users))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,12 +52,14 @@ func (ctx *TestContext) LoginUser(username string, password, mailboxPassword []b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := ctx.users.FinishLogin(client, auth, mailboxPassword)
|
userID, err := ctx.users.FinishLogin(client, auth, mailboxPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to finish login")
|
return errors.Wrap(err, "failed to finish login")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.addCleanupChecked(user.Logout, "Logging out user")
|
ctx.addCleanupChecked(func() error {
|
||||||
|
return ctx.bridge.LogoutUser(userID)
|
||||||
|
}, "Logging out user")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -73,12 +75,14 @@ func (ctx *TestContext) FinishLogin(client pmapi.Client, mailboxPassword []byte)
|
|||||||
return errors.New("cannot get current auth tokens from client")
|
return errors.New("cannot get current auth tokens from client")
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := ctx.users.FinishLogin(client, c.GetCurrentAuth(), mailboxPassword)
|
userID, err := ctx.users.FinishLogin(client, c.GetCurrentAuth(), mailboxPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to finish login")
|
return errors.Wrap(err, "failed to finish login")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.addCleanupChecked(user.Logout, "Logging out user")
|
ctx.addCleanupChecked(func() error {
|
||||||
|
return ctx.bridge.LogoutUser(userID)
|
||||||
|
}, "Logging out user")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user