reauthentication dialog

This commit is contained in:
Gaelle Braud 2024-08-22 14:31:28 +02:00
parent 204d7d66c8
commit 5adf150d2d
13 changed files with 308 additions and 32 deletions

View file

@ -77,6 +77,7 @@
#include "tool/providers/AvatarProvider.hpp"
#include "tool/providers/ImageProvider.hpp"
#include "tool/providers/ScreenProvider.hpp"
#include "tool/request/AuthenticationDialog.hpp"
#include "tool/request/RequestDialog.hpp"
#include "tool/thread/Thread.hpp"
@ -167,6 +168,35 @@ void App::setSelf(QSharedPointer<App>(me)) {
}
});
});
mCoreModelConnection->makeConnectToModel(
&CoreModel::authenticationRequested,
[this](const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::AuthInfo> &authInfo,
linphone::AuthMethod method) {
mCoreModelConnection->invokeToCore([this, core, authInfo, method]() {
if (method == linphone::AuthMethod::HttpDigest) {
auto window = App::getInstance()->getMainWindow();
auto username = authInfo->getUsername();
auto domain = authInfo->getDomain();
AuthenticationDialog *obj = new AuthenticationDialog(Utils::coreStringToAppString(username),
Utils::coreStringToAppString(domain));
connect(obj, &AuthenticationDialog::result, this, [this, obj, authInfo, core](QString password) {
mCoreModelConnection->invokeToModel([this, core, authInfo, password] {
mustBeInLinphoneThread("[App] reauthenticate");
if (password.isEmpty()) {
lDebug() << "ERROR : empty password";
} else {
lDebug() << "reset password for" << authInfo->getUsername();
authInfo->setPassword(Utils::appStringToCoreString(password));
core->addAuthInfo(authInfo);
core->refreshRegisters();
}
});
obj->deleteLater();
});
QMetaObject::invokeMethod(window, "reauthenticateAccount", QVariant::fromValue(obj));
}
});
});
//---------------------------------------------------------------------------------------------
mCliModelConnection = QSharedPointer<SafeConnection<App, CliModel>>(
new SafeConnection<App, CliModel>(me, CliModel::getInstance()), &QObject::deleteLater);
@ -364,6 +394,8 @@ void App::initCppInterfaces() {
qmlRegisterUncreatableType<RequestDialog>(Constants::MainQmlUri, 1, 0, "RequestDialog",
QLatin1String("Uncreatable"));
qmlRegisterUncreatableType<AuthenticationDialog>(Constants::MainQmlUri, 1, 0, "AuthenticationDialogCpp",
QLatin1String("Uncreatable"));
LinphoneEnums::registerMetaTypes();
}

View file

@ -40,7 +40,7 @@ public:
const QString &password,
QString displayName = QString(),
QString domain = QString(),
LinphoneEnums::TransportType transportType = LinphoneEnums::TransportType::Udp);
LinphoneEnums::TransportType transportType = LinphoneEnums::TransportType::Tcp);
linphone::RegistrationState getRegistrationState() const;
void setRegistrationState(linphone::RegistrationState status);

View file

@ -24,6 +24,7 @@
#include <QCoreApplication>
#include <QDir>
#include <QFile>
#include <QQuickWindow>
#include <QSysInfo>
#include <QTimer>

View file

@ -14,6 +14,7 @@ list(APPEND _LINPHONEAPP_SOURCES
tool/native/DesktopTools.hpp
tool/request/RequestDialog.cpp
tool/request/AuthenticationDialog.cpp
)
if (APPLE)

View file

@ -0,0 +1,25 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AuthenticationDialog.hpp"
AuthenticationDialog::AuthenticationDialog(QString username, QString domain, QObject *parent)
: QObject(parent), mUsername(username), mDomain(domain) {
}

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AUTHENTICATION_DIALOG_H_
#define AUTHENTICATION_DIALOG_H_
#include <QDebug>
#include <QObject>
#include <QString>
class AuthenticationDialog : public QObject {
Q_OBJECT
Q_PROPERTY(QString username MEMBER mUsername NOTIFY usernameChanged)
Q_PROPERTY(QString domain MEMBER mDomain NOTIFY domainChanged)
public:
AuthenticationDialog(QString username, QString domain, QObject *parent = nullptr);
QString mUsername;
QString mDomain;
signals:
void usernameChanged();
void domainChanged();
void result(QString password);
};
#endif

View file

@ -39,6 +39,20 @@ ApplicationWindow {
}
}
Component {
id: authenticationPopupComp
AuthenticationDialog{
property var authenticationDialog
property var callback: authenticationDialog.result
identity: authenticationDialog.username
domain: authenticationDialog.domain
onAccepted: {
authenticationDialog ? authenticationDialog.result(password) : callback(password)
close()
}
}
}
Popup {
id: startCallPopup
property FriendGui contact
@ -214,13 +228,19 @@ ApplicationWindow {
}
function showConfirmationLambdaPopup(title,details,callback){
console.log("Showing confirmation popup")
console.log("Showing confirmation lambda popup")
var popup = confirmPopupComp.createObject(popupLayout, {"text": title, "details":details,"callback":callback})
popup.index = popupLayout.popupList.length
popupLayout.popupList.push(popup)
popup.open()
popup.closePopup.connect(removeFromPopupLayout)
}
function reauthenticateAccount(authenticationDialog){
console.log("Showing authentication dialog")
var popup = authenticationPopupComp.createObject(mainWindow, {"authenticationDialog": authenticationDialog})
popup.open()
}
ColumnLayout {
id: popupLayout

View file

@ -28,6 +28,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
view/App/Layout/Account/AccountSettingsParametersLayout.qml
view/Item/Account/Accounts.qml
view/Item/Account/AuthenticationDialog.qml
view/Item/Call/CallContactsLists.qml
view/Item/Call/InCallSettingsPanel.qml

View file

@ -0,0 +1,105 @@
import QtCore
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as Control
import QtQuick.Dialogs
import Linphone
import UtilsCpp
import SettingsCpp
Dialog {
id: mainItem
property string identity
property string domain
readonly property string password: passwordEdit.text
onRejected: close()
modal: true
closePolicy: Popup.NoAutoClose
topPadding: 20 * DefaultStyle.dp
bottomPadding: 20 * DefaultStyle.dp
leftPadding: 20 * DefaultStyle.dp
rightPadding: 20 * DefaultStyle.dp
content: ColumnLayout {
spacing: 20 * DefaultStyle.dp
id: contentLayout
Text {
Layout.fillWidth: true
Layout.preferredWidth: 250 * DefaultStyle.dp
Layout.alignment: Qt.AlignHCenter
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
text: qsTr("Impossible de vous authentifier. Merci de vérifier votre mot de passe.")
font.pixelSize: 16 * DefaultStyle.dp
}
ColumnLayout {
spacing: 10 * DefaultStyle.dp
FormItemLayout {
Layout.fillWidth: true
label: qsTr("Identité")
contentItem: TextField {
enabled: false
customWidth: parent.width
initialText: mainItem.identity
}
}
FormItemLayout {
Layout.fillWidth: true
label: qsTr("Domaine")
contentItem: TextField {
enabled: false
initialText: mainItem.domain
}
}
FormItemLayout {
Layout.fillWidth: true
label: qsTr("Nom d'utilisateur (optionnel)")
contentItem: TextField {
id: usernameEdit
KeyNavigation.down: passwordEdit
}
}
FormItemLayout {
id: password
Layout.fillWidth: true
label: qsTr("Mot de passe")
enableErrorText: true
mandatory: true
contentItem: TextField {
id: passwordEdit
hidden: true
isError: password.errorTextVisible
KeyNavigation.up: usernameEdit
KeyNavigation.down: cancelButton
}
}
}
}
buttons: [
Button {
id: cancelButton
Layout.topMargin: 10 * DefaultStyle.dp
text: qsTr("Annuler")
inversedColors: true
onClicked: mainItem.rejected()
KeyNavigation.up: passwordEdit
KeyNavigation.right: connectButton
},
Button {
id: connectButton
Layout.topMargin: 10 * DefaultStyle.dp
text: qsTr("Se connecter")
KeyNavigation.up: passwordEdit
KeyNavigation.right: cancelButton
onClicked: {
password.errorMessage = ""
if (passwordEdit.text.length == 0) {
password.errorMessage = qsTr("Veuillez saisir un mot de passe")
return
}
mainItem.accepted()
}
}
]
}

View file

@ -84,6 +84,7 @@ RightPanelLayout {
Layout.preferredHeight: 17 * DefaultStyle.dp
iconSource: AppIcons.camera
iconSize: 17 * DefaultStyle.dp
backgroundColor: "transparent"
text: qsTr("Ajouter une image")
KeyNavigation.down: editButton.visible ? editButton : givenNameEdit
onClicked: fileDialog.open()
@ -97,6 +98,7 @@ RightPanelLayout {
Layout.preferredHeight: 17 * DefaultStyle.dp
iconSource: AppIcons.pencil
iconSize: 17 * DefaultStyle.dp
backgroundColor: "transparent"
text: qsTr("Modifier")
KeyNavigation.down: givenNameEdit
onClicked: fileDialog.open()
@ -118,6 +120,7 @@ RightPanelLayout {
Layout.preferredWidth: width
iconSize: 17 * DefaultStyle.dp
iconSource: AppIcons.trashCan
backgroundColor: "transparent"
text: qsTr("Supprimer")
KeyNavigation.down: givenNameEdit
onClicked: mainItem.contact.core.pictureUri = ""

View file

@ -21,12 +21,14 @@ Control.TextField {
}
selectByMouse: true
activeFocusOnTab: true
KeyNavigation.right: eyeButton
property bool controlIsDown: false
property bool hidden: false
property bool isError: false
property bool backgroundVisible: true
property color backgroundColor: DefaultStyle.grey_100
property color disabledBackgroundColor: DefaultStyle.grey_200
property color backgroundBorderColor: DefaultStyle.grey_200
property string initialText
property int pixelSize: 14 * DefaultStyle.dp
@ -47,7 +49,7 @@ Control.TextField {
visible: mainItem.backgroundVisible
anchors.fill: parent
radius: 79 * DefaultStyle.dp
color: mainItem.backgroundColor
color: mainItem.enabled ? mainItem.backgroundColor : mainItem.disabledBackgroundColor
border.color: mainItem.isError
? DefaultStyle.danger_500main
: mainItem.activeFocus
@ -105,6 +107,7 @@ Control.TextField {
Button {
id: eyeButton
KeyNavigation.left: mainItem
property int rightMargin: 15 * DefaultStyle.dp
z: 1
visible: mainItem.hidden

View file

@ -17,6 +17,7 @@ LoginLayout {
visible: !SettingsCpp.assistantHideThirdPartyAccount
spacing: 21 * DefaultStyle.dp
Button {
id: backButton
Layout.preferredHeight: 24 * DefaultStyle.dp
Layout.preferredWidth: 24 * DefaultStyle.dp
icon.source: AppIcons.leftArrow
@ -81,20 +82,47 @@ LoginLayout {
id: firstItem
ColumnLayout {
spacing: 0
Text {
Layout.fillWidth: true
Layout.preferredWidth: rootStackView.width
wrapMode: Text.WordWrap
color: DefaultStyle.main2_600
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400* DefaultStyle.dp
ColumnLayout {
Text {
Layout.fillWidth: true
Layout.preferredWidth: rootStackView.width
wrapMode: Text.WordWrap
color: DefaultStyle.main2_600
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400* DefaultStyle.dp
}
text: "Certaines fonctionnalités nécessitent un compte Linphone, comme la messagerie de groupe, les vidéoconférences...
Ces fonctionnalités sont cachées lorsque vous vous enregistrez avec un compte SIP tiers.
Pour les activer dans un projet commercial, veuillez nous contacter. "
}
Text {
Layout.fillWidth: true
Layout.preferredWidth: rootStackView.width
wrapMode: Text.WordWrap
color: DefaultStyle.main2_600
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400* DefaultStyle.dp
}
text:"Ces fonctionnalités sont cachées lorsque vous vous enregistrez avec un compte SIP tiers."
}
Text {
Layout.fillWidth: true
Layout.preferredWidth: rootStackView.width
wrapMode: Text.WordWrap
color: DefaultStyle.main2_600
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400* DefaultStyle.dp
}
text: "Pour les activer dans un projet commercial, veuillez nous contacter. "
}
text: "<p>Some features require a Linphone account, such as group messaging, video conferences...</p>
<p>These features are hidden when you register with a third party SIP account.</p>
<p>To enable it in a commercial projet, please contact us. </p>"
}
Button {
id: openLinkButton
Layout.alignment: Qt.AlignCenter
Layout.topMargin: 18 * DefaultStyle.dp
text: "linphone.org/contact"
@ -107,12 +135,15 @@ LoginLayout {
onClicked: {
Qt.openUrlExternally(ConstantsCpp.ContactUrl)
}
KeyNavigation.up: backButton
KeyNavigation.down: createAccountButton
}
Button {
id: createAccountButton
Layout.topMargin: 85 * DefaultStyle.dp
Layout.fillWidth: true
inversedColors: true
text: qsTr("I prefer creating an account")
text: qsTr("Créer un compte linphone")
leftPadding: 20 * DefaultStyle.dp
rightPadding: 20 * DefaultStyle.dp
topPadding: 11 * DefaultStyle.dp
@ -121,11 +152,14 @@ LoginLayout {
console.debug("[SIPLoginPage] User: click register")
mainItem.goToRegister()
}
KeyNavigation.up: openLinkButton
KeyNavigation.down: continueButton
}
Button {
id: continueButton
Layout.topMargin: 20 * DefaultStyle.dp
Layout.fillWidth: true
text: qsTr("I understand")
text: qsTr("Je comprends")
leftPadding: 20 * DefaultStyle.dp
rightPadding: 20 * DefaultStyle.dp
topPadding: 11 * DefaultStyle.dp
@ -133,6 +167,7 @@ LoginLayout {
onClicked: {
rootStackView.replace(secondItem)
}
KeyNavigation.up: createAccountButton
}
Item {
Layout.fillHeight: true
@ -154,6 +189,7 @@ LoginLayout {
id: usernameEdit
isError: username.errorTextVisible
Layout.preferredWidth: 360 * DefaultStyle.dp
KeyNavigation.down: passwordEdit
}
}
FormItemLayout {
@ -166,6 +202,8 @@ LoginLayout {
isError: password.errorTextVisible
hidden: true
Layout.preferredWidth: 360 * DefaultStyle.dp
KeyNavigation.up: usernameEdit
KeyNavigation.down: domainEdit
}
}
FormItemLayout {
@ -177,6 +215,8 @@ LoginLayout {
id: domainEdit
isError: domain.errorTextVisible
Layout.preferredWidth: 360 * DefaultStyle.dp
KeyNavigation.up: passwordEdit
KeyNavigation.down: displayName
}
}
FormItemLayout {
@ -184,6 +224,8 @@ LoginLayout {
contentItem: TextField {
id: displayName
Layout.preferredWidth: 360 * DefaultStyle.dp
KeyNavigation.up: domainEdit
KeyNavigation.down: transportCbox
}
}
FormItemLayout {
@ -289,6 +331,7 @@ LoginLayout {
else if(password.activeFocus) domain.forceActiveFocus()
}
onPressed: connectionButton.trigger()
KeyNavigation.up: transportCbox
}
Item {
Layout.fillHeight: true

View file

@ -58,15 +58,19 @@ AbstractMainPage {
aggregationFlag: LinphoneEnums.MagicSearchAggregation.Friend
}
Dialog {
id: dialog
property var contact
text: (contact ? contact.core.displayName : "Contact") + " is about to be deleted. Do you want to continue ?"
onAccepted: {
var name = contact.core.displayName
contact.core.remove()
UtilsCpp.showInformationPopup(qsTr("Supprimé"), qsTr("%1 a été supprimé").arg(name))
}
function deleteContact(contact) {
if (!contact) return
var mainWin = UtilsCpp.getMainWindow()
mainWin.showConfirmationLambdaPopup(
contact.core.displayName + qsTr("sera supprimé des contacts. Voulez-vous continuer ?"),
"",
function (confirmed) {
if (confirmed) {
var name = contact.core.displayName
contact.core.remove()
UtilsCpp.showInformationPopup(qsTr("Supprimé"), qsTr("%1 a été supprimé").arg(name)) }
}
)
}
Popup {
@ -279,8 +283,7 @@ AbstractMainPage {
mainItem.selectedContact = selectedContact
}
onContactDeletionRequested: (contact) => {
dialog.contact = contact
dialog.open()
mainItem.deleteContact(contact)
}
}
}
@ -344,8 +347,7 @@ AbstractMainPage {
mainItem.selectedContact = selectedContact
}
onContactDeletionRequested: (contact) => {
dialog.contact = contact
dialog.open()
mainItem.deleteContact(contact)
}
}
}
@ -782,9 +784,7 @@ AbstractMainPage {
color: DefaultStyle.danger_500main
text: qsTr("Delete this contact")
onClicked: {
// mainItem.selectedContact.core.remove()
dialog.contact = mainItem.selectedContact
dialog.open()
mainItem.deleteContact(contact)
}
}
}