forked from Silverfish/proton-bridge
GODT-1553: RPC definition and mocks
WIP: updates WIP: cache on disk and autostart. WIP: mail, keychain and more. WIP: updated grpc version in go mod file. WIP: user list. WIP: RPC service placeholder WIP: test C++ RPC client skeleton. Other: missing license script update. WIP: use Qt test framework. WIP: test for app and login calls. WIP: test for update & cache on disk calls. WIP: tests for mail settings calls. WIP: all client tests. WIP: linter fixes. WIP: fix missing license link. WIP: update dependency_license script for gRPC and protobuf. WIP: removed unused file. WIP: app & login event streaming tests. WIP: update event stream tests. WIP: completed event streaming tests.
This commit is contained in:
@ -31,6 +31,7 @@ import (
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/frontend"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/frontend/types"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/imap"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/rpc"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/smtp"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/store"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/store/cache"
|
||||
@ -138,6 +139,11 @@ func mailLoop(b *base.Base, c *cli.Context) error { //nolint:funlen
|
||||
smtpPort, useSSL, tlsConfig, smtpBackend, b.Listener).ListenAndServe()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer b.CrashHandler.HandlePanic()
|
||||
rpc.NewServer().ListenAndServe()
|
||||
}()
|
||||
|
||||
// We want to remove old versions if the app exits successfully.
|
||||
b.AddTeardownAction(b.Versioner.RemoveOldVersions)
|
||||
|
||||
|
||||
5104
internal/rpc/bridge_rpc.pb.go
Normal file
5104
internal/rpc/bridge_rpc.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
428
internal/rpc/bridge_rpc.proto
Normal file
428
internal/rpc/bridge_rpc.proto
Normal file
@ -0,0 +1,428 @@
|
||||
// Copyright (c) 2022 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
|
||||
option go_package = "github.com/ProtonMail/proton-bridge/internal/rpc";
|
||||
|
||||
package bridgerpc; // ignored by Go, used as namespace name in C++.
|
||||
|
||||
//**********************************************************************************************************************
|
||||
// Service Declaration
|
||||
//**********************************************************************************************************************
|
||||
service BridgeRpc {
|
||||
|
||||
// App related calls
|
||||
rpc GetCursorPos (google.protobuf.Empty) returns (PointResponse); // May be unnecessary
|
||||
rpc GuiReady (google.protobuf.Empty) returns (google.protobuf.Empty);
|
||||
rpc Quit (google.protobuf.Empty) returns (google.protobuf.Empty);
|
||||
rpc Restart (google.protobuf.Empty) returns (google.protobuf.Empty);
|
||||
rpc SetShowOnStartup(google.protobuf.BoolValue) returns (google.protobuf.Empty);
|
||||
rpc ShowOnStartup(google.protobuf.Empty) returns (google.protobuf.BoolValue);
|
||||
rpc SetShowSplashScreen(google.protobuf.BoolValue) returns (google.protobuf.Empty);
|
||||
rpc ShowSplashScreen(google.protobuf.Empty) returns (google.protobuf.BoolValue);
|
||||
rpc SetDockIconVisible(google.protobuf.BoolValue) returns (google.protobuf.Empty);
|
||||
rpc DockIconVisible(google.protobuf.Empty) returns (google.protobuf.BoolValue);
|
||||
rpc SetIsFirstGuiStart(google.protobuf.BoolValue) returns (google.protobuf.Empty);
|
||||
rpc IsFirstGuiStart(google.protobuf.Empty) returns (google.protobuf.BoolValue);
|
||||
rpc SetIsAutostartOn(google.protobuf.BoolValue) returns (google.protobuf.Empty);
|
||||
rpc IsAutostartOn(google.protobuf.Empty) returns (google.protobuf.BoolValue);
|
||||
rpc SetIsBetaEnabled(google.protobuf.BoolValue) returns (google.protobuf.Empty);
|
||||
rpc IsBetaEnabled(google.protobuf.Empty) returns (google.protobuf.BoolValue);
|
||||
rpc GoOs(google.protobuf.Empty) returns (google.protobuf.StringValue);
|
||||
rpc TriggerReset(google.protobuf.Empty) returns (google.protobuf.Empty);
|
||||
rpc Version(google.protobuf.Empty) returns (google.protobuf.StringValue);
|
||||
rpc LogPath(google.protobuf.Empty) returns (google.protobuf.StringValue);
|
||||
rpc LicensePath(google.protobuf.Empty) returns (google.protobuf.StringValue);
|
||||
rpc ReleaseNotesLink(google.protobuf.Empty) returns (google.protobuf.StringValue);
|
||||
rpc LandingPageLink(google.protobuf.Empty) returns (google.protobuf.StringValue);
|
||||
rpc SetColorSchemeName(google.protobuf.StringValue) returns (google.protobuf.Empty);
|
||||
rpc ColorSchemeName(google.protobuf.Empty) returns (google.protobuf.StringValue);
|
||||
rpc SetCurrentEmailClient(google.protobuf.StringValue) returns (google.protobuf.Empty);
|
||||
rpc CurrentEmailClient(google.protobuf.Empty) returns (google.protobuf.StringValue);
|
||||
rpc ReportBug(ReportBugRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// login
|
||||
rpc Login(LoginRequest) returns (google.protobuf.Empty);
|
||||
rpc Login2FA(LoginRequest) returns (google.protobuf.Empty);
|
||||
rpc Login2Passwords(LoginRequest) returns (google.protobuf.Empty);
|
||||
rpc LoginAbort(LoginAbortRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// update
|
||||
rpc CheckUpdate(google.protobuf.Empty) returns (google.protobuf.Empty);
|
||||
rpc InstallUpdate(google.protobuf.Empty) returns (google.protobuf.Empty);
|
||||
rpc SetIsAutomaticUpdateOn(google.protobuf.BoolValue) returns (google.protobuf.Empty);
|
||||
rpc IsAutomaticUpdateOn(google.protobuf.Empty) returns (google.protobuf.BoolValue);
|
||||
|
||||
// cache
|
||||
rpc SetIsCacheOnDiskEnabled (google.protobuf.BoolValue) returns (google.protobuf.Empty);
|
||||
rpc IsCacheOnDiskEnabled (google.protobuf.Empty) returns (google.protobuf.BoolValue);
|
||||
rpc SetDiskCachePath (google.protobuf.StringValue) returns (google.protobuf.Empty);
|
||||
rpc DiskCachePath(google.protobuf.Empty) returns (google.protobuf.StringValue);
|
||||
rpc ChangeLocalCache(ChangeLocalCacheRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// mail
|
||||
rpc SetIsDoHEnabled(google.protobuf.BoolValue) returns (google.protobuf.Empty);
|
||||
rpc IsDoHEnabled(google.protobuf.Empty) returns (google.protobuf.BoolValue);
|
||||
rpc SetUseSslForSmtp(google.protobuf.BoolValue) returns (google.protobuf.Empty);
|
||||
rpc UseSslForSmtp(google.protobuf.Empty) returns (google.protobuf.BoolValue);
|
||||
rpc Hostname(google.protobuf.Empty) returns (google.protobuf.StringValue);
|
||||
rpc SetImapPort(google.protobuf.Int32Value) returns (google.protobuf.Empty);
|
||||
rpc ImapPort(google.protobuf.Empty) returns (google.protobuf.Int32Value);
|
||||
rpc SetSmtpPort(google.protobuf.Int32Value) returns (google.protobuf.Empty);
|
||||
rpc SmtpPort(google.protobuf.Empty) returns (google.protobuf.Int32Value);
|
||||
rpc ChangePorts(ChangePortsRequest) returns (google.protobuf.Empty);
|
||||
rpc IsPortFree(google.protobuf.Int32Value) returns (google.protobuf.BoolValue);
|
||||
|
||||
// keychain
|
||||
rpc AvailableKeychains(google.protobuf.Empty) returns (AvailableKeychainsResponse);
|
||||
rpc SetCurrentKeychain(google.protobuf.StringValue) returns (google.protobuf.Empty);
|
||||
rpc CurrentKeychain(google.protobuf.Empty) returns (google.protobuf.StringValue);
|
||||
|
||||
// User & user list
|
||||
rpc GetUserList(google.protobuf.Empty) returns (UserListResponse);
|
||||
rpc GetUser(google.protobuf.Empty) returns (User);
|
||||
rpc SetUserSplitMode(UserSplitModeRequest) returns (google.protobuf.Empty);
|
||||
rpc LogoutUser(google.protobuf.StringValue) returns (google.protobuf.Empty);
|
||||
rpc RemoveUser(google.protobuf.StringValue) returns (google.protobuf.Empty);
|
||||
rpc ConfigureUserAppleMail(ConfigureAppleMailRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// Server -> Client event stream
|
||||
rpc GetEvents(google.protobuf.Empty) returns (stream StreamEvent);
|
||||
}
|
||||
|
||||
//**********************************************************************************************************************
|
||||
// RPC calls requests and replies messages
|
||||
//**********************************************************************************************************************
|
||||
|
||||
//**********************************************************
|
||||
// GUI related messages
|
||||
//**********************************************************
|
||||
message PointResponse {
|
||||
int32 x = 1;
|
||||
int32 y = 2;
|
||||
};
|
||||
|
||||
message ReportBugRequest {
|
||||
string description = 1;
|
||||
string address = 2;
|
||||
string emailClient = 3;
|
||||
bool includeLogs = 4;
|
||||
|
||||
}
|
||||
|
||||
// login related messages
|
||||
|
||||
message LoginRequest {
|
||||
string username = 1;
|
||||
string password = 2;
|
||||
}
|
||||
|
||||
message LoginAbortRequest {
|
||||
string username = 1;
|
||||
}
|
||||
|
||||
//**********************************************************
|
||||
// Cache on disk related messages
|
||||
//**********************************************************
|
||||
message ChangeLocalCacheRequest {
|
||||
bool enableDiskCache = 1;
|
||||
string diskCachePath = 2;
|
||||
}
|
||||
|
||||
//**********************************************************
|
||||
// Cache on disk related messages
|
||||
//**********************************************************
|
||||
message ChangePortsRequest {
|
||||
int32 imapPort = 1;
|
||||
int32 smtpPort = 2;
|
||||
}
|
||||
|
||||
//**********************************************************
|
||||
// Cache on disk related messages
|
||||
//**********************************************************
|
||||
message AvailableKeychainsResponse {
|
||||
repeated string keychains = 1;
|
||||
}
|
||||
|
||||
//**********************************************************
|
||||
// Cache on disk related messages
|
||||
//**********************************************************
|
||||
message User {
|
||||
string id = 1;
|
||||
string username = 2;
|
||||
string avatarText = 3;
|
||||
bool loggedIn = 4;
|
||||
bool splitMode = 5;
|
||||
bool setupGuideSeen = 6;
|
||||
int64 usedBytes = 7;
|
||||
int64 totalBytes = 8;
|
||||
string password = 9;
|
||||
repeated string addresses = 10;
|
||||
}
|
||||
|
||||
message UserSplitModeRequest {
|
||||
string userID = 1;
|
||||
bool active = 2;
|
||||
}
|
||||
|
||||
message UserListResponse {
|
||||
repeated User users = 1;
|
||||
}
|
||||
|
||||
message ConfigureAppleMailRequest {
|
||||
string userID = 1;
|
||||
string address = 2;
|
||||
}
|
||||
|
||||
//**********************************************************************************************************************
|
||||
// Event stream messages
|
||||
//**********************************************************************************************************************
|
||||
message StreamEvent {
|
||||
oneof event {
|
||||
AppEvent app = 1;
|
||||
LoginEvent login = 2;
|
||||
UpdateEvent update = 3;
|
||||
CacheEvent cache = 4;
|
||||
MailSettingsEvent mailSettings = 5;
|
||||
KeychainEvent keychain = 6;
|
||||
MailEvent mail = 7;
|
||||
UserEvent user = 8;
|
||||
}
|
||||
}
|
||||
|
||||
//**********************************************************
|
||||
// App related events
|
||||
//**********************************************************
|
||||
message AppEvent {
|
||||
oneof event {
|
||||
InternetStatusEvent internetStatus = 1;
|
||||
AutostartFinishedEvent autostartFinished = 2;
|
||||
ResetFinishedEvent resetFinished = 3;
|
||||
ReportBugFinishedEvent reportBugFinished = 4;
|
||||
ReportBugSuccessEvent reportBugSuccess = 5;
|
||||
ReportBugErrorEvent reportBugError = 6;
|
||||
ShowMainWindowEvent showMainWindow = 7;
|
||||
}
|
||||
}
|
||||
|
||||
message InternetStatusEvent {
|
||||
bool connected = 1;
|
||||
}
|
||||
|
||||
message AutostartFinishedEvent {}
|
||||
message ResetFinishedEvent {}
|
||||
message ReportBugFinishedEvent {}
|
||||
message ReportBugSuccessEvent {}
|
||||
message ReportBugErrorEvent {}
|
||||
message ShowMainWindowEvent {}
|
||||
|
||||
//**********************************************************
|
||||
// Login related events
|
||||
//**********************************************************
|
||||
message LoginEvent {
|
||||
oneof event {
|
||||
LoginErrorEvent error = 1;
|
||||
LoginTfaRequestedEvent tfaRequested = 2;
|
||||
LoginTwoPasswordsRequestedEvent twoPasswordRequested = 3;
|
||||
LoginFinishedEvent finished = 4;
|
||||
}
|
||||
}
|
||||
|
||||
enum LoginErrorType {
|
||||
USERNAME_PASSWORD_ERROR = 0;
|
||||
FREE_USER = 1;
|
||||
CONNECTION_ERROR = 2;
|
||||
TFA_ERROR = 3;
|
||||
TFA_ABORT = 4;
|
||||
TWO_PASSWORDS_ERROR = 5;
|
||||
TWO_PASSWORDS_ABORT = 6;
|
||||
}
|
||||
|
||||
message LoginErrorEvent {
|
||||
LoginErrorType type = 1;
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
message LoginTfaRequestedEvent {
|
||||
string username = 1;
|
||||
}
|
||||
|
||||
message LoginTwoPasswordsRequestedEvent {}
|
||||
|
||||
message LoginFinishedEvent {
|
||||
bool wasAlreadyLoggedIn = 1;
|
||||
}
|
||||
|
||||
//**********************************************************
|
||||
// Update related events
|
||||
//**********************************************************
|
||||
message UpdateEvent {
|
||||
oneof event {
|
||||
UpdateErrorEvent error = 1;
|
||||
UpdateManualReadyEvent manualReady = 2;
|
||||
UpdateManualRestartNeededEvent manualRestartNeeded = 3;
|
||||
UpdateForceEvent force = 4;
|
||||
UpdateSilentRestartNeeded silentRestartNeeded = 5;
|
||||
UpdateIsLatestVersion isLatestVersion = 6;
|
||||
UpdateCheckFinished checkFinished = 7;
|
||||
}
|
||||
}
|
||||
|
||||
enum UpdateErrorType {
|
||||
UPDATE_MANUAL_ERROR = 0;
|
||||
UPDATE_FORCE_ERROR = 1;
|
||||
UPDATE_SILENT_ERROR = 2;
|
||||
}
|
||||
|
||||
message UpdateErrorEvent {
|
||||
UpdateErrorType type = 1;
|
||||
}
|
||||
|
||||
message UpdateManualReadyEvent {
|
||||
string version = 1;
|
||||
}
|
||||
|
||||
message UpdateManualRestartNeededEvent {};
|
||||
|
||||
message UpdateForceEvent {
|
||||
string version = 1;
|
||||
}
|
||||
|
||||
message UpdateSilentRestartNeeded {}
|
||||
|
||||
message UpdateIsLatestVersion {}
|
||||
|
||||
message UpdateCheckFinished {}
|
||||
|
||||
//**********************************************************
|
||||
// Cache on disk related events
|
||||
//**********************************************************
|
||||
message CacheEvent {
|
||||
oneof event {
|
||||
CacheErrorEvent error = 1;
|
||||
CacheLocationChangeSuccessEvent locationChangedSuccess = 2;
|
||||
ChangeLocalCacheFinishedEvent changeLocalCacheFinished = 3;
|
||||
}
|
||||
}
|
||||
|
||||
enum CacheErrorType {
|
||||
CACHE_UNAVAILABLE_ERROR = 0;
|
||||
CACHE_CANT_MOVE_ERROR = 1;
|
||||
DISK_FULL = 2;
|
||||
};
|
||||
|
||||
message CacheErrorEvent {
|
||||
CacheErrorType type = 1;
|
||||
}
|
||||
|
||||
message CacheLocationChangeSuccessEvent {};
|
||||
|
||||
message ChangeLocalCacheFinishedEvent {};
|
||||
|
||||
//**********************************************************
|
||||
// Mail settings related events
|
||||
//**********************************************************
|
||||
message MailSettingsEvent {
|
||||
oneof event {
|
||||
MailSettingsErrorEvent error = 1;
|
||||
UseSslForSmtpFinishedEvent useSslForSmtpFinished = 2;
|
||||
ChangePortsFinishedEvent changePortsFinished = 3;
|
||||
}
|
||||
}
|
||||
|
||||
enum MailSettingsErrorType {
|
||||
IMAP_PORT_ISSUE = 0;
|
||||
SMTP_PORT_ISSUE = 1;
|
||||
}
|
||||
|
||||
message MailSettingsErrorEvent {
|
||||
MailSettingsErrorType type = 1;
|
||||
}
|
||||
|
||||
message UseSslForSmtpFinishedEvent {}
|
||||
|
||||
message ChangePortsFinishedEvent {}
|
||||
|
||||
//**********************************************************
|
||||
// keychain related events
|
||||
//**********************************************************
|
||||
message KeychainEvent {
|
||||
oneof event {
|
||||
ChangeKeychainFinishedEvent changeKeychainFinished = 1;
|
||||
HasNoKeychainEvent hasNoKeychain = 2;
|
||||
RebuildKeychainEvent rebuildKeychain = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message ChangeKeychainFinishedEvent {}
|
||||
message HasNoKeychainEvent {}
|
||||
message RebuildKeychainEvent {}
|
||||
|
||||
//**********************************************************
|
||||
// Mail related events
|
||||
//**********************************************************
|
||||
message MailEvent {
|
||||
oneof event {
|
||||
NoActiveKeyForRecipientEvent noActiveKeyForRecipientEvent = 1;
|
||||
AddressChangedEvent addressChanged = 2;
|
||||
AddressChangedLogoutEvent addressChangedLogout = 3;
|
||||
ApiCertIssueEvent apiCertIssue = 6;
|
||||
}
|
||||
}
|
||||
|
||||
message NoActiveKeyForRecipientEvent {
|
||||
string email = 1;
|
||||
}
|
||||
|
||||
message AddressChangedEvent {
|
||||
string address = 1; // TODO: user event ?
|
||||
}
|
||||
|
||||
message AddressChangedLogoutEvent {
|
||||
string address = 1; // TODO: user event ?
|
||||
}
|
||||
|
||||
message ApiCertIssueEvent {}
|
||||
|
||||
//**********************************************************
|
||||
// User list related event
|
||||
//**********************************************************
|
||||
|
||||
message UserEvent {
|
||||
oneof event {
|
||||
ToggleSplitModeFinishedEvent toggleSplitModeFinished= 1;
|
||||
UserDisconnectedEvent userDisconnected = 2;
|
||||
UserChangedEvent userChanged = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message ToggleSplitModeFinishedEvent {
|
||||
string userID = 1;
|
||||
}
|
||||
|
||||
message UserDisconnectedEvent {
|
||||
string username = 1; // TODO: isn't it userID ?
|
||||
}
|
||||
|
||||
message UserChangedEvent {
|
||||
User user = 1;
|
||||
}
|
||||
|
||||
2347
internal/rpc/bridge_rpc_grpc.pb.go
Normal file
2347
internal/rpc/bridge_rpc_grpc.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
121
internal/rpc/server.go
Normal file
121
internal/rpc/server.go
Normal file
@ -0,0 +1,121 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
)
|
||||
|
||||
//go:generate protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative bridge_rpc.proto
|
||||
|
||||
//goland:noinspection SpellCheckingInspection
|
||||
const (
|
||||
serverCert = `-----BEGIN CERTIFICATE-----
|
||||
MIIC5TCCAc2gAwIBAgIJAJL2PajH8kFjMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
|
||||
BAMMCWxvY2FsaG9zdDAeFw0yMjA1MTAwNjEzMzdaFw0yMjA2MDkwNjEzMzdaMBQx
|
||||
EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
||||
ggEBAKyb48XL+08YI8m4X/eeD9TQshV+vybKbU7MOG7BnH3Hv7kUH0aVP7OPnU51
|
||||
eYRgUu+bkJ8qWhxD7wOLVJBcU5T1lgd+k6St83ix25P02nUc3UeU4MCxMwhjMjYu
|
||||
R5F9bfSG0UlCCGAEjjmGh+CfnZkS+rgCwE/xGswFnVrynTMvrLQyN02dz/r4zJPp
|
||||
yyVhTOmjdsUDs0zGDbubLf+ypR8VCXg55qYMw7Abpe+rx3BF+NCEjKlATjMeIZNx
|
||||
iS0dl0OGjJZ+bfHGhnPiQxP8HxyJ0NjFNtWgblQev2sHmIq65Rry3RP1gbDAW3sk
|
||||
MiIfjbnp4gGspYrmHWeWXH8g6WMCAwEAAaM6MDgwFAYDVR0RBA0wC4IJbG9jYWxo
|
||||
b3N0MAsGA1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0B
|
||||
AQsFAAOCAQEAO2WDYnzy9SkaS9VU2jw3nd9MEaILZsXFcVU2+52TKwRBty7b0A1x
|
||||
zyxT6nT0pN0Im7DcT5/TvwFuVBJUTFs4c2gW09WUvtfuN8HVFOeX/1Pt10lMPJjR
|
||||
I+wTAUQrXJHt57JE9x13gQEOW/mGUDNuoUH2cE9C1f+TrO0LaRj8dubS/gHMuV1i
|
||||
aTyxu7hgbLAYq0NGD86CSOwvUvTvs6o628xvfmqqdzlpWIlQq18t2GZYFVWjrISY
|
||||
LWw3OCormKSASOPrW1FXhrgwoyDXHNmZT1MHL3Rh9U5qyCwV5kDAcY956sc9lD3G
|
||||
XHtSxOHLE1eDKGCUKRcYop/99inTGjJ6Xg==
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
serverKey = `-----BEGIN PRIVATE KEY-----
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCsm+PFy/tPGCPJ
|
||||
uF/3ng/U0LIVfr8mym1OzDhuwZx9x7+5FB9GlT+zj51OdXmEYFLvm5CfKlocQ+8D
|
||||
i1SQXFOU9ZYHfpOkrfN4sduT9Np1HN1HlODAsTMIYzI2LkeRfW30htFJQghgBI45
|
||||
hofgn52ZEvq4AsBP8RrMBZ1a8p0zL6y0MjdNnc/6+MyT6cslYUzpo3bFA7NMxg27
|
||||
my3/sqUfFQl4OeamDMOwG6Xvq8dwRfjQhIypQE4zHiGTcYktHZdDhoyWfm3xxoZz
|
||||
4kMT/B8cidDYxTbVoG5UHr9rB5iKuuUa8t0T9YGwwFt7JDIiH4256eIBrKWK5h1n
|
||||
llx/IOljAgMBAAECggEBAIgsaBKo7XelzL4cpiFc4pJ7nrMUjktVEc1DkhXWytX0
|
||||
W03xEQeHQX0whOLcDOUhdOyxZvQa3oJEGfFK34kQPaRb52O8OVCHJ3iFoHxmhF42
|
||||
SmBplLKQWXl5gKh79FxUfwWVwtCvtpnBnk7F0rakVhnofkHjccLfrMtedpjEpL42
|
||||
xuzcoMnGrDLtCsfyDZTpTA0+xQhYb3qlkX4V1gVS/Sp3zLotUqE9THjCbTVcl0Ux
|
||||
UKqMaMcqYX+GVBoPE5B2aelmvIKgvUYy1RNVsVdi5mvmO4fdm14/7vgxrWO3gV0Z
|
||||
RWLnJQ5ISktx/9YCRro3UTu5eR7JO3CKAYTAzQpdDSkCgYEA4SGa/WTBPImMJKnV
|
||||
aM9pK74Z4yZ3FEv3Le1BE63rduETVOXs8QhWsDt7upu2del6Pb8UI1kkgK2EshXW
|
||||
l61pzQmsAvUSUO7AW4KPRgwjDy4kRLAozq3kMbmdrSc7cfxXHiktUyZ8Rmt1VjsP
|
||||
d+/OzB2ZG4DdmGR8Kk8tzCHTjMcCgYEAxEavBi+Mw+EUz3X+8nSDyGO57iJvr63N
|
||||
poubJfRPrV20lkY1OoGm+c1jXohAI+afGZNJvp84eQwYCyZEczEncmPMYI6nyuJL
|
||||
i3fyoG9YTFa6edpdLowA9J14x6agh1y1q5ADrbL2L6Gf3to9q+E2RjKlJvlfYd5w
|
||||
URaQoZ5/CoUCgYBoV/IE9bjWPQ4WRBzkahVdr8tBy6cvYhIbWDZsT5St0Z3rIHIU
|
||||
OQAsyDUNhXQo7GC606AazgssFMBG5fZC8J3z6UKvUDUAC9hd0YJkPeXV+FXY/Ci9
|
||||
ujzkixo4kdFsgD9EfGNEgbbh0JZetBr0RNJ9Kk63P5/1LMWbun0IerkZKwKBgQC1
|
||||
DA4+QnYx6NjtVQZKVzeIDJVhF9q1zjg4O+Zs6CLm49zEERbgVN/U5KOYe03Oz9hK
|
||||
GxaXAv9wiLtU7YOOTfT5Cx1mo7Aa8QqGJ6piWtKz9/wikk4JtZLcELVsVEMXGWlq
|
||||
S3lZLA7yeL+jLOReO2t47RZyEOzuteQcqBfZPP4qkQKBgQDHkUXgMbqchcXeM6Nf
|
||||
LALiNkbf+4BeaWI+h3HteVjFkKRrRCMihDHcBg/nWF0SI/AoVoy+ybxYv7dME7z5
|
||||
kPas6sPvVg81i96xesKTry7lefM+3H6hSqrKBYZdu7XXItBYvHctuGLSin2gV+WU
|
||||
vwTpDMetrvhD7qmlwspJPwHaOw==
|
||||
-----END PRIVATE KEY-----`
|
||||
)
|
||||
|
||||
// Server is the RPC server struct.
|
||||
type Server struct {
|
||||
grpcServer *grpc.Server
|
||||
listener net.Listener
|
||||
log *logrus.Entry
|
||||
}
|
||||
|
||||
// NewServer returns a new RPC server.
|
||||
func NewServer() *Server {
|
||||
log := logrus.WithField("pkg", "rpc")
|
||||
|
||||
cert, err := tls.X509KeyPair([]byte(serverCert), []byte(serverKey))
|
||||
if err != nil {
|
||||
log.WithError(err).Error("could not create key pair")
|
||||
panic(err)
|
||||
}
|
||||
|
||||
grpcServer := grpc.NewServer(grpc.Creds(credentials.NewTLS(&tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
MinVersion: tls.VersionTLS13,
|
||||
})))
|
||||
|
||||
RegisterBridgeRpcServer(grpcServer, NewService(grpcServer, log))
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:9292") // Port should be configurable from the command-line.
|
||||
if err != nil {
|
||||
log.WithError(err).Error("could not create listener")
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &Server{grpcServer: grpcServer, listener: listener, log: log}
|
||||
}
|
||||
|
||||
// ListenAndServe provides the RPC service.
|
||||
func (s *Server) ListenAndServe() {
|
||||
err := s.grpcServer.Serve(s.listener)
|
||||
if err != nil {
|
||||
s.log.WithError(err).Error("error serving RPC")
|
||||
}
|
||||
}
|
||||
690
internal/rpc/service.go
Normal file
690
internal/rpc/service.go
Normal file
@ -0,0 +1,690 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
// Service is the RPC service struct.
|
||||
type Service struct {
|
||||
UnimplementedBridgeRpcServer
|
||||
grpcServer *grpc.Server
|
||||
log *logrus.Entry
|
||||
|
||||
showOnStartup bool
|
||||
showSplashScreen bool
|
||||
dockIconVisible bool
|
||||
isFirstGuiStart bool
|
||||
isAutostartOn bool
|
||||
isBetaEnabled bool
|
||||
colorSchemeName string
|
||||
currentEmailClient string
|
||||
isAutoUpdateOn bool
|
||||
isCacheOnDiskEnabled bool
|
||||
diskCachePath string
|
||||
isDohEnabled bool
|
||||
useSSLForSMTP bool
|
||||
hostname string
|
||||
imapPort uint16
|
||||
smtpPort uint16
|
||||
keychains []string
|
||||
currentKeychain string
|
||||
users []*User
|
||||
currentUser string
|
||||
}
|
||||
|
||||
// NewService returns a new instance of the service.
|
||||
func NewService(grpcServer *grpc.Server, log *logrus.Entry) *Service {
|
||||
service := Service{
|
||||
grpcServer: grpcServer,
|
||||
log: log,
|
||||
colorSchemeName: "aName",
|
||||
currentEmailClient: "aClient",
|
||||
hostname: "dummy.proton.me",
|
||||
imapPort: 143,
|
||||
smtpPort: 25,
|
||||
keychains: []string{uuid.New().String(), uuid.New().String(), uuid.New().String()},
|
||||
users: []*User{{
|
||||
Id: uuid.New().String(),
|
||||
Username: "user1",
|
||||
AvatarText: "avatarText1",
|
||||
LoggedIn: true,
|
||||
SplitMode: false,
|
||||
SetupGuideSeen: true,
|
||||
UsedBytes: 5000000000,
|
||||
TotalBytes: 1000000000,
|
||||
Password: "dummyPassword",
|
||||
Addresses: []string{"dummy@proton.me"},
|
||||
}, {
|
||||
Id: uuid.New().String(),
|
||||
Username: "user2",
|
||||
AvatarText: "avatarText2",
|
||||
LoggedIn: false,
|
||||
SplitMode: true,
|
||||
SetupGuideSeen: false,
|
||||
UsedBytes: 4000000000,
|
||||
TotalBytes: 2000000000,
|
||||
Password: "dummyPassword2",
|
||||
Addresses: []string{"dummy2@proton.me"},
|
||||
}},
|
||||
}
|
||||
service.currentKeychain = service.keychains[0]
|
||||
service.currentUser = service.users[0].Id
|
||||
|
||||
return &service
|
||||
}
|
||||
|
||||
func (s *Service) GetCursorPos(context.Context, *emptypb.Empty) (*PointResponse, error) {
|
||||
s.log.Info("GetCursorPos")
|
||||
return &PointResponse{X: 100, Y: 200}, nil
|
||||
}
|
||||
|
||||
func (s *Service) GuiReady(context.Context, *emptypb.Empty) (*emptypb.Empty, error) {
|
||||
s.log.Info("GuiReady")
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
func (s *Service) Quit(context.Context, *emptypb.Empty) (*emptypb.Empty, error) {
|
||||
s.log.Info("Quit")
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) Restart(context.Context, *emptypb.Empty) (*emptypb.Empty, error) {
|
||||
s.log.Info("Restart")
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
func (s *Service) SetShowOnStartup(_ context.Context, show *wrapperspb.BoolValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("show", show.Value).Info("SetShowOnStartup")
|
||||
s.showOnStartup = show.Value
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) ShowOnStartup(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) {
|
||||
s.log.Info("ShowOnStartup")
|
||||
return wrapperspb.Bool(s.showOnStartup), nil
|
||||
}
|
||||
|
||||
func (s *Service) SetShowSplashScreen(_ context.Context, show *wrapperspb.BoolValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("show", show.Value).Info("SetShowSplashScreen")
|
||||
s.showSplashScreen = show.Value
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) ShowSplashScreen(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) {
|
||||
s.log.Info("ShowSplashScreen")
|
||||
return wrapperspb.Bool(s.showSplashScreen), nil
|
||||
}
|
||||
|
||||
func (s *Service) SetDockIconVisible(_ context.Context, visible *wrapperspb.BoolValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("show", visible.Value).Info("SetDockIconVisible")
|
||||
s.dockIconVisible = visible.Value
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
func (s *Service) DockIconVisible(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) {
|
||||
s.log.Info("DockIconVisible")
|
||||
return wrapperspb.Bool(s.dockIconVisible), nil
|
||||
}
|
||||
func (s *Service) SetIsFirstGuiStart(_ context.Context, isFirst *wrapperspb.BoolValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("show", isFirst.Value).Info("SetIsFirstGuiStart")
|
||||
s.isFirstGuiStart = isFirst.Value
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) IsFirstGuiStart(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) {
|
||||
s.log.Info("IsFirstGuiStart")
|
||||
return wrapperspb.Bool(s.isFirstGuiStart), nil
|
||||
}
|
||||
|
||||
func (s *Service) SetIsAutostartOn(_ context.Context, isOn *wrapperspb.BoolValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("show", isOn.Value).Info("SetIsAutostartOn")
|
||||
s.isAutostartOn = isOn.Value
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) IsAutostartOn(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) {
|
||||
s.log.Info("IsAutostartOn")
|
||||
return wrapperspb.Bool(s.isAutostartOn), nil
|
||||
}
|
||||
|
||||
func (s *Service) SetIsBetaEnabled(_ context.Context, isEnabled *wrapperspb.BoolValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("show", isEnabled.Value).Info("SetIsBetaEnabled")
|
||||
s.isBetaEnabled = isEnabled.Value
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) IsBetaEnabled(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) {
|
||||
s.log.Info("IsBetaEnabled")
|
||||
return wrapperspb.Bool(s.isBetaEnabled), nil
|
||||
}
|
||||
|
||||
func (s *Service) GoOs(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) {
|
||||
s.log.Info("GoOs")
|
||||
return wrapperspb.String("DummyOsName"), nil
|
||||
}
|
||||
|
||||
func (s *Service) TriggerReset(context.Context, *emptypb.Empty) (*emptypb.Empty, error) {
|
||||
s.log.Info("TriggerReset")
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) Version(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) {
|
||||
s.log.Info("Version")
|
||||
return wrapperspb.String("1.0"), nil
|
||||
}
|
||||
|
||||
func (s *Service) LogPath(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) {
|
||||
s.log.Info("LogPath")
|
||||
return wrapperspb.String("/path/to/log"), nil
|
||||
}
|
||||
|
||||
func (s *Service) LicensePath(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) {
|
||||
s.log.Info("LicensePath")
|
||||
return wrapperspb.String("/path/to/license"), nil
|
||||
}
|
||||
|
||||
func (s *Service) ReleaseNotesLink(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) {
|
||||
s.log.Info("ReleaseNotesLink")
|
||||
return wrapperspb.String("https//proton.me/release/notes.html"), nil
|
||||
}
|
||||
|
||||
func (s *Service) LandingPageLink(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) {
|
||||
s.log.Info("LandingPageLink")
|
||||
return wrapperspb.String("https//proton.me"), nil
|
||||
}
|
||||
|
||||
func (s *Service) SetColorSchemeName(_ context.Context, name *wrapperspb.StringValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("ColorSchemeName", name.Value).Info("SetColorSchemeName")
|
||||
s.colorSchemeName = name.Value
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) ColorSchemeName(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) {
|
||||
s.log.Info("ColorSchemeName")
|
||||
return wrapperspb.String(s.colorSchemeName), nil
|
||||
}
|
||||
|
||||
func (s *Service) SetCurrentEmailClient(_ context.Context, client *wrapperspb.StringValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("CurrentEmailClient", client.Value).Info("SetCurrentEmailClient")
|
||||
s.currentEmailClient = client.Value
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) CurrentEmailClient(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) {
|
||||
s.log.Info("CurrentEmailClient")
|
||||
return wrapperspb.String(s.currentEmailClient), nil
|
||||
}
|
||||
|
||||
func (s *Service) ReportBug(_ context.Context, report *ReportBugRequest) (*emptypb.Empty, error) {
|
||||
s.log.WithField("description", report.Description).
|
||||
WithField("address", report.Address).
|
||||
WithField("emailClient", report.EmailClient).
|
||||
WithField("includeLogs", report.IncludeLogs).
|
||||
Info("ReportBug")
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) Login(_ context.Context, login *LoginRequest) (*emptypb.Empty, error) {
|
||||
s.log.
|
||||
WithField("username", login.Username).
|
||||
Info("Login")
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) Login2FA(_ context.Context, login *LoginRequest) (*emptypb.Empty, error) {
|
||||
s.log.
|
||||
WithField("username", login.Username).
|
||||
Info("Login2FA")
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) Login2Passwords(_ context.Context, login *LoginRequest) (*emptypb.Empty, error) {
|
||||
s.log.
|
||||
WithField("username", login.Username).
|
||||
Info("Login2Passwords")
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) LoginAbort(_ context.Context, loginAbort *LoginAbortRequest) (*emptypb.Empty, error) {
|
||||
s.log.
|
||||
WithField("username", loginAbort.Username).
|
||||
Info("LoginAbort")
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) CheckUpdate(context.Context, *emptypb.Empty) (*emptypb.Empty, error) {
|
||||
s.log.Info("CheckUpdate")
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) InstallUpdate(context.Context, *emptypb.Empty) (*emptypb.Empty, error) {
|
||||
s.log.Info("InstallUpdate")
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) SetIsAutomaticUpdateOn(_ context.Context, isOn *wrapperspb.BoolValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("isOn", isOn.Value).Info("SetIsAutomaticUpdateOn")
|
||||
s.isAutoUpdateOn = isOn.Value
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) IsAutomaticUpdateOn(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) {
|
||||
s.log.Info("IsAutomaticUpdateOn")
|
||||
return wrapperspb.Bool(s.isAutoUpdateOn), nil
|
||||
}
|
||||
|
||||
func (s *Service) SetIsCacheOnDiskEnabled(_ context.Context, isEnabled *wrapperspb.BoolValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("isOn", isEnabled.Value).Info("SetIsCacheOnDiskEnabled")
|
||||
s.isCacheOnDiskEnabled = isEnabled.Value
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) IsCacheOnDiskEnabled(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) {
|
||||
s.log.Info("IsCacheOnDiskEnabled")
|
||||
return wrapperspb.Bool(s.isCacheOnDiskEnabled), nil
|
||||
}
|
||||
|
||||
func (s *Service) SetDiskCachePath(_ context.Context, path *wrapperspb.StringValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("path", path.Value).Info("IsCacheOnDiskEnabled")
|
||||
s.diskCachePath = path.Value
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) DiskCachePath(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) {
|
||||
s.log.Info("DiskCachePath")
|
||||
return wrapperspb.String(s.diskCachePath), nil
|
||||
}
|
||||
|
||||
func (s *Service) ChangeLocalCache(_ context.Context, change *ChangeLocalCacheRequest) (*emptypb.Empty, error) {
|
||||
s.log.
|
||||
WithField("enableDiskCache", change.EnableDiskCache).
|
||||
WithField("diskCachePath", change.DiskCachePath).
|
||||
Info("DiskCachePath")
|
||||
s.isCacheOnDiskEnabled = change.EnableDiskCache
|
||||
s.diskCachePath = change.DiskCachePath
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) SetIsDoHEnabled(_ context.Context, isEnabled *wrapperspb.BoolValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("isEnabled", isEnabled.Value).Info("SetIsDohEnabled")
|
||||
s.isDohEnabled = isEnabled.Value
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) IsDoHEnabled(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) {
|
||||
s.log.Info("IsDohEnabled")
|
||||
return wrapperspb.Bool(s.isDohEnabled), nil
|
||||
}
|
||||
func (s *Service) SetUseSslForSmtp(_ context.Context, useSsl *wrapperspb.BoolValue) (*emptypb.Empty, error) { //nolint:revive,stylecheck
|
||||
s.log.WithField("useSsl", useSsl.Value).Info("SetUseSslForSmtp")
|
||||
s.useSSLForSMTP = useSsl.Value
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) UseSslForSmtp(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) { //nolint:revive,stylecheck
|
||||
s.log.Info("UseSslForSmtp")
|
||||
return wrapperspb.Bool(s.useSSLForSMTP), nil
|
||||
}
|
||||
|
||||
func (s *Service) Hostname(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) {
|
||||
s.log.Info("Hostname")
|
||||
return wrapperspb.String(s.hostname), nil
|
||||
}
|
||||
|
||||
func (s *Service) SetImapPort(_ context.Context, port *wrapperspb.Int32Value) (*emptypb.Empty, error) {
|
||||
s.log.WithField("port", port.Value).Info("SetImapPort")
|
||||
s.imapPort = uint16(port.Value)
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) ImapPort(context.Context, *emptypb.Empty) (*wrapperspb.Int32Value, error) {
|
||||
s.log.Info("ImapPort")
|
||||
return wrapperspb.Int32(int32(s.imapPort)), nil
|
||||
}
|
||||
|
||||
func (s *Service) SetSmtpPort(_ context.Context, port *wrapperspb.Int32Value) (*emptypb.Empty, error) { //nolint:revive,stylecheck
|
||||
s.log.WithField("port", port.Value).Info("SetSmtpPort")
|
||||
s.smtpPort = uint16(port.Value)
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) SmtpPort(context.Context, *emptypb.Empty) (*wrapperspb.Int32Value, error) { //nolint:revive,stylecheck
|
||||
s.log.Info("SmtpPort")
|
||||
return wrapperspb.Int32(int32(s.smtpPort)), nil
|
||||
}
|
||||
|
||||
func (s *Service) ChangePorts(_ context.Context, ports *ChangePortsRequest) (*emptypb.Empty, error) {
|
||||
s.log.WithField("imapPort", ports.ImapPort).WithField("smtpPort", ports.SmtpPort).Info("ChangePorts")
|
||||
s.imapPort = uint16(ports.ImapPort)
|
||||
s.smtpPort = uint16(ports.SmtpPort)
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) IsPortFree(context.Context, *wrapperspb.Int32Value) (*wrapperspb.BoolValue, error) {
|
||||
s.log.Info("IsPortFree")
|
||||
return wrapperspb.Bool(true), nil
|
||||
}
|
||||
|
||||
func (s *Service) AvailableKeychains(context.Context, *emptypb.Empty) (*AvailableKeychainsResponse, error) {
|
||||
s.log.Info("AvailableKeychains")
|
||||
return &AvailableKeychainsResponse{Keychains: s.keychains}, nil
|
||||
}
|
||||
|
||||
func (s *Service) SetCurrentKeychain(_ context.Context, keychain *wrapperspb.StringValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("keychain", keychain.Value).Info("SetCurrentKeyChain") // we do not check validity.
|
||||
s.currentKeychain = keychain.Value
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) CurrentKeychain(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) {
|
||||
s.log.Info("CurrentKeychain")
|
||||
return wrapperspb.String(s.currentKeychain), nil
|
||||
}
|
||||
|
||||
func (s *Service) GetUserList(context.Context, *emptypb.Empty) (*UserListResponse, error) {
|
||||
s.log.Info("GetUserList")
|
||||
return &UserListResponse{Users: s.users}, nil
|
||||
}
|
||||
func (s *Service) GetUser(context.Context, *emptypb.Empty) (*User, error) {
|
||||
s.log.Info("GetUser")
|
||||
return s.getCurrentUser(), nil
|
||||
}
|
||||
func (s *Service) SetUserSplitMode(_ context.Context, splitMode *UserSplitModeRequest) (*emptypb.Empty, error) {
|
||||
s.log.WithField("UserID", splitMode.UserID).WithField("Active", splitMode.Active).Info("SetUserSplitMode")
|
||||
user := s.findUser(splitMode.UserID) // we should return an error
|
||||
if user != nil {
|
||||
user.SplitMode = splitMode.Active
|
||||
}
|
||||
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) LogoutUser(_ context.Context, userID *wrapperspb.StringValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("UserID", userID.Value).Info("LogoutUser")
|
||||
user := s.findUser(userID.Value)
|
||||
if user != nil {
|
||||
user.LoggedIn = false
|
||||
}
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) RemoveUser(_ context.Context, userID *wrapperspb.StringValue) (*emptypb.Empty, error) {
|
||||
s.log.WithField("UserID", userID.Value).Info("RemoveUser")
|
||||
// we actually do nothing
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) ConfigureUserAppleMail(_ context.Context, request *ConfigureAppleMailRequest) (*emptypb.Empty, error) {
|
||||
s.log.WithField("UserID", request.UserID).WithField("Address", request.Address).Info("ConfigureUserAppleMail")
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetEvents(_ *emptypb.Empty, server BridgeRpc_GetEventsServer) error { // nolint:funlen
|
||||
s.log.Info("Starting Event stream")
|
||||
|
||||
events := []func() *StreamEvent{
|
||||
// app
|
||||
internetStatusEvent,
|
||||
autostartFinishedEvent,
|
||||
resetFinishedEvent,
|
||||
reportBugFinishedEvent,
|
||||
reportBugSuccessEvent,
|
||||
reportBugErrorEvent,
|
||||
showMainWindowEvent,
|
||||
|
||||
// login
|
||||
loginError,
|
||||
loginTfaRequestedEvent,
|
||||
loginTwoPasswordsRequestedEvent,
|
||||
loginFinishedEvent,
|
||||
|
||||
// update
|
||||
updateErrorEvent,
|
||||
updateManualReadyEvent,
|
||||
updateManualRestartNeededEvent,
|
||||
updateForceEvent,
|
||||
updateSilentRestartNeededEvent,
|
||||
updateIsLatestVersionEvent,
|
||||
updateCheckFinishedEvent,
|
||||
|
||||
// cache
|
||||
cacheErrorEvent,
|
||||
cacheLocationChangeSuccessEvent,
|
||||
cacheChangeLocalCacheFinishedEvent,
|
||||
|
||||
// mail settings
|
||||
mailSettingsErrorEvent,
|
||||
mailSettingsUseSslForSmtpFinishedEvent,
|
||||
mailSettingsChangePortFinishedEvent,
|
||||
|
||||
// keychain
|
||||
keychainChangeKeychainFinishedEvent,
|
||||
keychainHasNoKeychainEvent,
|
||||
keychainRebuildKeychainEvent,
|
||||
|
||||
// mail
|
||||
mailNoActiveKeyForRecipientEvent,
|
||||
mailAddressChangeEvent,
|
||||
mailAddressChangeLogoutEvent,
|
||||
mailApiCertIssue,
|
||||
|
||||
// user
|
||||
userToggleSplitModeFinishedEvent,
|
||||
userDisconnectedEvent,
|
||||
userChangedEvent,
|
||||
}
|
||||
|
||||
for _, eventFunc := range events {
|
||||
event := eventFunc()
|
||||
s.log.WithField("event", event).Info("Sending event")
|
||||
if err := server.Send(eventFunc()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
s.log.Info("Stop Event stream")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) getCurrentUser() *User {
|
||||
return s.findUser(s.currentUser)
|
||||
}
|
||||
|
||||
func (s *Service) findUser(userID string) *User {
|
||||
for _, u := range s.users {
|
||||
if u.Id == userID {
|
||||
return u
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func appEvent(appEvent *AppEvent) *StreamEvent {
|
||||
return &StreamEvent{Event: &StreamEvent_App{App: appEvent}}
|
||||
}
|
||||
|
||||
func internetStatusEvent() *StreamEvent {
|
||||
return appEvent(&AppEvent{Event: &AppEvent_InternetStatus{InternetStatus: &InternetStatusEvent{Connected: true}}})
|
||||
}
|
||||
|
||||
func autostartFinishedEvent() *StreamEvent {
|
||||
return appEvent(&AppEvent{Event: &AppEvent_AutostartFinished{AutostartFinished: &AutostartFinishedEvent{}}})
|
||||
}
|
||||
|
||||
func resetFinishedEvent() *StreamEvent {
|
||||
return appEvent(&AppEvent{Event: &AppEvent_ResetFinished{ResetFinished: &ResetFinishedEvent{}}})
|
||||
}
|
||||
|
||||
func reportBugFinishedEvent() *StreamEvent {
|
||||
return appEvent(&AppEvent{Event: &AppEvent_ReportBugFinished{ReportBugFinished: &ReportBugFinishedEvent{}}})
|
||||
}
|
||||
|
||||
func reportBugSuccessEvent() *StreamEvent {
|
||||
return appEvent(&AppEvent{Event: &AppEvent_ReportBugSuccess{ReportBugSuccess: &ReportBugSuccessEvent{}}})
|
||||
}
|
||||
|
||||
func reportBugErrorEvent() *StreamEvent {
|
||||
return appEvent(&AppEvent{Event: &AppEvent_ReportBugError{ReportBugError: &ReportBugErrorEvent{}}})
|
||||
}
|
||||
|
||||
func showMainWindowEvent() *StreamEvent {
|
||||
return appEvent(&AppEvent{Event: &AppEvent_ShowMainWindow{ShowMainWindow: &ShowMainWindowEvent{}}})
|
||||
}
|
||||
|
||||
func loginEvent(event *LoginEvent) *StreamEvent {
|
||||
return &StreamEvent{Event: &StreamEvent_Login{Login: event}}
|
||||
}
|
||||
|
||||
func loginError() *StreamEvent {
|
||||
return loginEvent(&LoginEvent{Event: &LoginEvent_Error{Error: &LoginErrorEvent{Type: LoginErrorType_FREE_USER}}})
|
||||
}
|
||||
|
||||
func loginTfaRequestedEvent() *StreamEvent {
|
||||
return loginEvent(&LoginEvent{Event: &LoginEvent_TfaRequested{TfaRequested: &LoginTfaRequestedEvent{Username: "dummy@proton.me"}}})
|
||||
}
|
||||
|
||||
func loginTwoPasswordsRequestedEvent() *StreamEvent {
|
||||
return loginEvent(&LoginEvent{Event: &LoginEvent_TwoPasswordRequested{}})
|
||||
}
|
||||
|
||||
func loginFinishedEvent() *StreamEvent {
|
||||
return loginEvent(&LoginEvent{Event: &LoginEvent_Finished{Finished: &LoginFinishedEvent{WasAlreadyLoggedIn: true}}})
|
||||
}
|
||||
|
||||
func updateEvent(event *UpdateEvent) *StreamEvent {
|
||||
return &StreamEvent{Event: &StreamEvent_Update{Update: event}}
|
||||
}
|
||||
|
||||
func updateErrorEvent() *StreamEvent {
|
||||
return updateEvent(&UpdateEvent{Event: &UpdateEvent_Error{Error: &UpdateErrorEvent{Type: UpdateErrorType_UPDATE_SILENT_ERROR}}})
|
||||
}
|
||||
|
||||
func updateManualReadyEvent() *StreamEvent {
|
||||
return updateEvent(&UpdateEvent{Event: &UpdateEvent_ManualReady{ManualReady: &UpdateManualReadyEvent{Version: "1.0"}}})
|
||||
}
|
||||
|
||||
func updateManualRestartNeededEvent() *StreamEvent {
|
||||
return updateEvent(&UpdateEvent{Event: &UpdateEvent_ManualRestartNeeded{ManualRestartNeeded: &UpdateManualRestartNeededEvent{}}})
|
||||
}
|
||||
|
||||
func updateForceEvent() *StreamEvent {
|
||||
return updateEvent(&UpdateEvent{Event: &UpdateEvent_Force{Force: &UpdateForceEvent{Version: " 2.0"}}})
|
||||
}
|
||||
|
||||
func updateSilentRestartNeededEvent() *StreamEvent {
|
||||
return updateEvent(&UpdateEvent{Event: &UpdateEvent_SilentRestartNeeded{SilentRestartNeeded: &UpdateSilentRestartNeeded{}}})
|
||||
}
|
||||
|
||||
func updateIsLatestVersionEvent() *StreamEvent {
|
||||
return updateEvent(&UpdateEvent{Event: &UpdateEvent_IsLatestVersion{IsLatestVersion: &UpdateIsLatestVersion{}}})
|
||||
}
|
||||
|
||||
func updateCheckFinishedEvent() *StreamEvent {
|
||||
return updateEvent(&UpdateEvent{Event: &UpdateEvent_CheckFinished{CheckFinished: &UpdateCheckFinished{}}})
|
||||
}
|
||||
|
||||
func cacheEvent(event *CacheEvent) *StreamEvent {
|
||||
return &StreamEvent{Event: &StreamEvent_Cache{Cache: event}}
|
||||
}
|
||||
|
||||
func cacheErrorEvent() *StreamEvent {
|
||||
return cacheEvent(&CacheEvent{Event: &CacheEvent_Error{Error: &CacheErrorEvent{Type: CacheErrorType_CACHE_UNAVAILABLE_ERROR}}})
|
||||
}
|
||||
|
||||
func cacheLocationChangeSuccessEvent() *StreamEvent {
|
||||
return cacheEvent(&CacheEvent{Event: &CacheEvent_LocationChangedSuccess{LocationChangedSuccess: &CacheLocationChangeSuccessEvent{}}})
|
||||
}
|
||||
|
||||
func cacheChangeLocalCacheFinishedEvent() *StreamEvent {
|
||||
return cacheEvent(&CacheEvent{Event: &CacheEvent_ChangeLocalCacheFinished{ChangeLocalCacheFinished: &ChangeLocalCacheFinishedEvent{}}})
|
||||
}
|
||||
|
||||
func mailSettingsEvent(event *MailSettingsEvent) *StreamEvent {
|
||||
return &StreamEvent{Event: &StreamEvent_MailSettings{MailSettings: event}}
|
||||
}
|
||||
|
||||
func mailSettingsErrorEvent() *StreamEvent {
|
||||
return mailSettingsEvent(&MailSettingsEvent{Event: &MailSettingsEvent_Error{Error: &MailSettingsErrorEvent{Type: MailSettingsErrorType_IMAP_PORT_ISSUE}}})
|
||||
}
|
||||
|
||||
func mailSettingsUseSslForSmtpFinishedEvent() *StreamEvent { //nolint:revive,stylecheck
|
||||
return mailSettingsEvent(&MailSettingsEvent{Event: &MailSettingsEvent_UseSslForSmtpFinished{UseSslForSmtpFinished: &UseSslForSmtpFinishedEvent{}}})
|
||||
}
|
||||
|
||||
func mailSettingsChangePortFinishedEvent() *StreamEvent {
|
||||
return mailSettingsEvent(&MailSettingsEvent{Event: &MailSettingsEvent_ChangePortsFinished{ChangePortsFinished: &ChangePortsFinishedEvent{}}})
|
||||
}
|
||||
|
||||
func keychainEvent(event *KeychainEvent) *StreamEvent {
|
||||
return &StreamEvent{Event: &StreamEvent_Keychain{Keychain: event}}
|
||||
}
|
||||
|
||||
func keychainChangeKeychainFinishedEvent() *StreamEvent {
|
||||
return keychainEvent(&KeychainEvent{Event: &KeychainEvent_ChangeKeychainFinished{ChangeKeychainFinished: &ChangeKeychainFinishedEvent{}}})
|
||||
}
|
||||
|
||||
func keychainHasNoKeychainEvent() *StreamEvent {
|
||||
return keychainEvent(&KeychainEvent{Event: &KeychainEvent_HasNoKeychain{HasNoKeychain: &HasNoKeychainEvent{}}})
|
||||
}
|
||||
|
||||
func keychainRebuildKeychainEvent() *StreamEvent {
|
||||
return keychainEvent(&KeychainEvent{Event: &KeychainEvent_RebuildKeychain{RebuildKeychain: &RebuildKeychainEvent{}}})
|
||||
}
|
||||
|
||||
func mailEvent(event *MailEvent) *StreamEvent {
|
||||
return &StreamEvent{Event: &StreamEvent_Mail{Mail: event}}
|
||||
}
|
||||
|
||||
func mailNoActiveKeyForRecipientEvent() *StreamEvent {
|
||||
return mailEvent(&MailEvent{Event: &MailEvent_NoActiveKeyForRecipientEvent{NoActiveKeyForRecipientEvent: &NoActiveKeyForRecipientEvent{Email: "dummy@proton.me"}}})
|
||||
}
|
||||
|
||||
func mailAddressChangeEvent() *StreamEvent {
|
||||
return mailEvent(&MailEvent{Event: &MailEvent_AddressChanged{AddressChanged: &AddressChangedEvent{Address: "dummy@proton.me"}}})
|
||||
}
|
||||
|
||||
func mailAddressChangeLogoutEvent() *StreamEvent {
|
||||
return mailEvent(&MailEvent{Event: &MailEvent_AddressChangedLogout{AddressChangedLogout: &AddressChangedLogoutEvent{Address: "dummy@proton.me"}}})
|
||||
}
|
||||
|
||||
func mailApiCertIssue() *StreamEvent { //nolint:revive,stylecheck
|
||||
return mailEvent(&MailEvent{Event: &MailEvent_ApiCertIssue{ApiCertIssue: &ApiCertIssueEvent{}}})
|
||||
}
|
||||
|
||||
func userEvent(event *UserEvent) *StreamEvent {
|
||||
return &StreamEvent{Event: &StreamEvent_User{User: event}}
|
||||
}
|
||||
|
||||
func userToggleSplitModeFinishedEvent() *StreamEvent {
|
||||
return userEvent(&UserEvent{Event: &UserEvent_ToggleSplitModeFinished{ToggleSplitModeFinished: &ToggleSplitModeFinishedEvent{UserID: "userID"}}})
|
||||
}
|
||||
|
||||
func userDisconnectedEvent() *StreamEvent {
|
||||
return userEvent(&UserEvent{Event: &UserEvent_UserDisconnected{UserDisconnected: &UserDisconnectedEvent{Username: "dummy@proton.me"}}})
|
||||
}
|
||||
|
||||
func userChangedEvent() *StreamEvent {
|
||||
return userEvent(&UserEvent{Event: &UserEvent_UserChanged{UserChanged: &UserChangedEvent{User: &User{}}}})
|
||||
}
|
||||
Reference in New Issue
Block a user