mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 04:36:43 +00:00
fix(BRIDGE-107): improved human verification UX
This commit is contained in:
@ -723,3 +723,13 @@ func (bridge *Bridge) PushDistinctObservabilityMetrics(errType observability.Dis
|
||||
func (bridge *Bridge) ModifyObservabilityHeartbeatInterval(duration time.Duration) {
|
||||
bridge.observabilityService.ModifyHeartbeatInterval(duration)
|
||||
}
|
||||
|
||||
func (bridge *Bridge) ReportMessageWithContext(message string, messageCtx reporter.Context) {
|
||||
if err := bridge.reporter.ReportMessageWithContext(message, messageCtx); err != nil {
|
||||
logPkg.WithFields(logrus.Fields{
|
||||
"err": err,
|
||||
"sentryMessage": message,
|
||||
"messageCtx": messageCtx,
|
||||
}).Info("Error occurred when sending Report to Sentry")
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ using namespace bridgepp;
|
||||
namespace {
|
||||
|
||||
QString const defaultKeychain = "defaultKeychain"; ///< The default keychain.
|
||||
QString const HV_ERROR_TEMPLATE = "failed to create new API client: 422 POST https://mail-api.proton.me/auth/v4: CAPTCHA validation failed (Code=12087, Status=422)";
|
||||
QString const HV_ERROR_TEMPLATE = "Human verification failed. Please try again.";
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@ FocusScope {
|
||||
property alias username: usernameTextField.text
|
||||
property var wizard
|
||||
property string hvLinkUrl: ""
|
||||
property bool hvLinkClicked: false
|
||||
|
||||
signal loginAbort(string username, bool wasSignedOut)
|
||||
|
||||
@ -49,6 +50,7 @@ FocusScope {
|
||||
}
|
||||
passwordTextField.hidePassword();
|
||||
secondPasswordTextField.hidePassword();
|
||||
hvLinkClicked = false;
|
||||
}
|
||||
function resetViaHv() {
|
||||
usernameTextField.enabled = false;
|
||||
@ -56,6 +58,7 @@ FocusScope {
|
||||
signInButton.loading = true;
|
||||
secondPasswordButton.loading = false;
|
||||
secondPasswordTextField.enabled = true;
|
||||
hvLinkClicked = false;
|
||||
totpLayout.reset();
|
||||
}
|
||||
|
||||
@ -562,6 +565,7 @@ FocusScope {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
Qt.openUrlExternally(hvLinkUrl);
|
||||
hvLinkClicked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -574,7 +578,8 @@ FocusScope {
|
||||
id: hVContinueButton
|
||||
Layout.fillWidth: true
|
||||
colorScheme: wizard.colorScheme
|
||||
text: qsTr("Continue")
|
||||
text: qsTr("I’ve completed the verification")
|
||||
enabled: hvLinkClicked
|
||||
|
||||
function checkAndSignInHv() {
|
||||
console.assert(stackLayout.currentIndex === Login.RootStack.HV || stackLayout.currentIndex === Login.RootStack.MailboxPassword, "Unexpected checkInAndSignInHv")
|
||||
|
||||
@ -159,7 +159,10 @@ func (f *frontendCLI) loginAccount(c *ishell.Context) {
|
||||
hvDetails, hvErr := hv.VerifyAndExtractHvRequest(err)
|
||||
if hvErr != nil || hvDetails != nil {
|
||||
if hvErr != nil {
|
||||
f.printAndLogError("Cannot login", hvErr)
|
||||
f.printAndLogError("Cannot login:", hv.ExtractionErrorMsg)
|
||||
f.bridge.ReportMessageWithContext("Unable to extract HV request details", map[string]any{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
f.promptHvURL(hvDetails)
|
||||
|
||||
@ -465,7 +465,7 @@ func (s *Service) finishLogin() {
|
||||
|
||||
if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Code == proton.HumanValidationInvalidToken {
|
||||
s.hvDetails = nil
|
||||
_ = s.SendEvent(NewLoginError(LoginErrorType_HV_ERROR, err.Error()))
|
||||
_ = s.SendEvent(NewLoginError(LoginErrorType_HV_ERROR, hv.VerificationFailedErrorMsg))
|
||||
return
|
||||
}
|
||||
|
||||
@ -643,7 +643,10 @@ func (s *Service) monitorParentPID() {
|
||||
func (s *Service) handleHvRequest(err error) {
|
||||
hvDet, hvErr := hv.VerifyAndExtractHvRequest(err)
|
||||
if hvErr != nil {
|
||||
_ = s.SendEvent(NewLoginError(LoginErrorType_HV_ERROR, hvErr.Error()))
|
||||
_ = s.SendEvent(NewLoginError(LoginErrorType_HV_ERROR, hv.ExtractionErrorMsg))
|
||||
s.bridge.ReportMessageWithContext("Unable to extract HV request details", map[string]any{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@ import (
|
||||
"github.com/ProtonMail/proton-bridge/v3/internal/constants"
|
||||
"github.com/ProtonMail/proton-bridge/v3/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/v3/internal/frontend/theme"
|
||||
"github.com/ProtonMail/proton-bridge/v3/internal/hv"
|
||||
"github.com/ProtonMail/proton-bridge/v3/internal/kb"
|
||||
"github.com/ProtonMail/proton-bridge/v3/internal/safe"
|
||||
"github.com/ProtonMail/proton-bridge/v3/internal/service"
|
||||
@ -468,7 +469,7 @@ func (s *Service) Login(_ context.Context, login *LoginRequest) (*emptypb.Empty,
|
||||
|
||||
case proton.HumanValidationInvalidToken:
|
||||
s.hvDetails = nil
|
||||
_ = s.SendEvent(NewLoginError(LoginErrorType_HV_ERROR, err.Error()))
|
||||
_ = s.SendEvent(NewLoginError(LoginErrorType_HV_ERROR, hv.VerificationFailedErrorMsg))
|
||||
|
||||
default:
|
||||
_ = s.SendEvent(NewLoginError(LoginErrorType_USERNAME_PASSWORD_ERROR, err.Error()))
|
||||
|
||||
@ -21,6 +21,11 @@ import (
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
)
|
||||
|
||||
const (
|
||||
ExtractionErrorMsg = "Human verification requested, but an issue occurred. Please try again."
|
||||
VerificationFailedErrorMsg = "Human verification failed. Please try again."
|
||||
)
|
||||
|
||||
// VerifyAndExtractHvRequest expects an error request as input
|
||||
// determines whether the given error is a Proton human verification request; if it isn't then it returns -> nil, nil (no details, no error)
|
||||
// if it is a HV req. then it tries to parse the json data and verify that the captcha method is included; if either fails -> nil, err
|
||||
@ -34,7 +39,7 @@ func VerifyAndExtractHvRequest(err error) (*proton.APIHVDetails, error) {
|
||||
if errors.As(err, &protonErr) && protonErr.IsHVError() {
|
||||
hvDetails, hvErr := protonErr.GetHVDetails()
|
||||
if hvErr != nil {
|
||||
return nil, fmt.Errorf("received HV request, but can't decode HV details")
|
||||
return nil, hvErr
|
||||
}
|
||||
return hvDetails, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user