mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 19:18:06 +00:00
Add popup for updating password
This commit is contained in:
parent
2b79b95079
commit
fe261f3127
9 changed files with 235 additions and 11 deletions
|
|
@ -251,15 +251,39 @@ class CoreContext: ObservableObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
}, onAuthenticationRequested: { (_: Core, authInfo: AuthInfo, method: AuthMethod) in
|
||||
guard let username = authInfo.username, let server = authInfo.authorizationServer, !server.isEmpty else {
|
||||
}, onAuthenticationRequested: { (core: Core, authInfo: AuthInfo, method: AuthMethod) in
|
||||
guard let username = authInfo.username, let domain = authInfo.domain, let realm = authInfo.realm else {
|
||||
Log.error("Authentication requested but either username [\(String(describing: authInfo.username))], domain [\(String(describing: authInfo.domain))] or server [\(String(describing: authInfo.authorizationServer))] is nil or empty!")
|
||||
return
|
||||
}
|
||||
|
||||
if method == .Bearer {
|
||||
Log.info("Authentication requested method is Bearer, starting Single Sign On activity with server URL \(server) and username \(username)")
|
||||
self.bearerAuthInfoPendingPasswordUpdate = authInfo
|
||||
SingleSignOnManager.shared.setUp(ssoUrl: server, user: username)
|
||||
if let server = authInfo.authorizationServer, !server.isEmpty {
|
||||
Log.info("Authentication requested method is Bearer, starting Single Sign On activity with server URL \(server) and username \(username)")
|
||||
self.bearerAuthInfoPendingPasswordUpdate = authInfo
|
||||
SingleSignOnManager.shared.setUp(ssoUrl: server, user: username)
|
||||
}
|
||||
}
|
||||
|
||||
if method == .HttpDigest {
|
||||
guard let accountFound = core.accountList.first(where: {
|
||||
$0.params?.identityAddress?.username == authInfo.username &&
|
||||
$0.params?.identityAddress?.domain == authInfo.domain
|
||||
}) else {
|
||||
Log.info("[CoreContext] Failed to find account matching auth info, aborting auth dialog")
|
||||
return
|
||||
}
|
||||
|
||||
let identity = "\(authInfo.username ?? "username")@\(authInfo.domain ?? "domain")"
|
||||
Log.info("[CoreContext] Authentication requested method is HttpDigest, showing dialog asking user for password for identity [\(identity)]")
|
||||
|
||||
DispatchQueue.main.async {
|
||||
NotificationCenter.default.post(
|
||||
name: NSNotification.Name("PasswordUpdate"),
|
||||
object: nil,
|
||||
userInfo: ["address": "sip:" + identity]
|
||||
)
|
||||
}
|
||||
}
|
||||
}, onTransferStateChanged: { (_: Core, transferred: Call, callState: Call.State) in
|
||||
Log.info("[CoreContext] Transferred call \(transferred.remoteAddress!.asStringUriOnly()) state changed \(callState)")
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@
|
|||
"account_settings_avpf_title" = "AVPF";
|
||||
"account_settings_conference_factory_uri_title" = "URI konfiguračního serveru konference";
|
||||
"account_settings_cpim_in_basic_conversations_title" = "Použít CPIM v \"základních\" konverzacích";
|
||||
"account_settings_dialog_invalid_password_title" = "Vyžadováno ověření";
|
||||
"account_settings_dialog_invalid_password_message" = "Připojení se nezdařilo, protože chybí nebo je neplatné ověření účtu\n%@.\n\nMůžete znovu zadat heslo nebo zkontrolovat nastavení účtu v konfiguraci.";
|
||||
"account_settings_dialog_invalid_password_hint" = "Nové heslo";
|
||||
"account_settings_enable_ice_title" = "Povolit ICE";
|
||||
"account_settings_enable_turn_title" = "Povolit TURN";
|
||||
"account_settings_expire_title" = "Platnost (v sekundách)";
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@
|
|||
"account_settings_ccmp_server_url_title" = "CCMP server URL";
|
||||
"account_settings_conference_factory_uri_title" = "Conference factory URI";
|
||||
"account_settings_cpim_in_basic_conversations_title" = "Use CPIM in \"basic\" conversations";
|
||||
"account_settings_dialog_invalid_password_title" = "Authentication needed";
|
||||
"account_settings_dialog_invalid_password_message" = "Connection failed because authentication is missing or invalid for account \n%@.\n\nYou can provide password again, or check your account configuration in the settings.";
|
||||
"account_settings_dialog_invalid_password_hint" = "Password";
|
||||
"account_settings_enable_ice_title" = "Enable ICE";
|
||||
"account_settings_enable_turn_title" = "Enable TURN";
|
||||
"account_settings_expire_title" = "Expire (in seconds)";
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@
|
|||
"account_settings_ccmp_server_url_title" = "URL du serveur CCMP";
|
||||
"account_settings_conference_factory_uri_title" = "URI du serveur de conversations";
|
||||
"account_settings_cpim_in_basic_conversations_title" = "Utiliser CPIM dans les conversations \"basiques\"";
|
||||
"account_settings_dialog_invalid_password_title" = "Autentification requise";
|
||||
"account_settings_dialog_invalid_password_message" = "La connexion a échoué pour le compte \n%@.\n\nVous pouvez renseigner votre mot de passe à nouveau ou bien vérifier les options de configuration de votre compte.";
|
||||
"account_settings_dialog_invalid_password_hint" = "Mot de passe";
|
||||
"account_settings_enable_ice_title" = "Activer ICE";
|
||||
"account_settings_enable_turn_title" = "Activer TURN";
|
||||
"account_settings_expire_title" = "Expiration (en secondes)";
|
||||
|
|
|
|||
|
|
@ -298,6 +298,9 @@
|
|||
"account_settings_bundle_mode_title" = "Режим об'єднання";
|
||||
"account_settings_ccmp_server_url_title" = "URL-адреса сервера CCMP";
|
||||
"account_settings_conference_factory_uri_title" = "URI ресурсу конференцій";
|
||||
"account_settings_dialog_invalid_password_title" = "Потрібна автентифікація";
|
||||
"account_settings_dialog_invalid_password_message" = "З’єднання не вдалося, оскільки автентифікація відсутня або недійсна для облікового запису\n%@.\n\nВи можете ввести пароль ще раз або перевірити конфігурацію облікового запису в налаштуваннях.";
|
||||
"account_settings_dialog_invalid_password_hint" = "Новий пароль";
|
||||
"account_settings_enable_ice_title" = "Увімкнути ICE";
|
||||
"account_settings_enable_turn_title" = "Увімкнути TURN";
|
||||
"account_settings_expire_title" = "Спливає (в секундах)";
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ struct ContentView: View {
|
|||
@State var isShowConversationInfoPopup: Bool = false
|
||||
@State var conversationInfoPopupText: String = ""
|
||||
|
||||
@State var isShowUpdatePasswordPopup: Bool = false
|
||||
@State var passwordUpdateAddress: String = ""
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { geometry in
|
||||
VStack(spacing: 0) {
|
||||
|
|
@ -1293,6 +1296,18 @@ struct ContentView: View {
|
|||
}
|
||||
}
|
||||
|
||||
if isShowUpdatePasswordPopup {
|
||||
PopupUpdatePassword(
|
||||
isShowUpdatePasswordPopup: $isShowUpdatePasswordPopup,
|
||||
passwordUpdateAddress: $passwordUpdateAddress
|
||||
)
|
||||
.background(.black.opacity(0.65))
|
||||
.zIndex(3)
|
||||
.onTapGesture {
|
||||
self.isShowUpdatePasswordPopup.toggle()
|
||||
}
|
||||
}
|
||||
|
||||
if telecomManager.meetingWaitingRoomDisplayed {
|
||||
MeetingWaitingRoomFragment()
|
||||
.zIndex(3)
|
||||
|
|
@ -1353,6 +1368,10 @@ struct ContentView: View {
|
|||
.onReceive(NotificationCenter.default.publisher(for: NSNotification.Name("CoreStarted"))) { _ in
|
||||
accountProfileViewModel.setAvatarModel()
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: NSNotification.Name("PasswordUpdate")).compactMap { $0.userInfo?["address"] as? String }) { address in
|
||||
passwordUpdateAddress = address
|
||||
isShowUpdatePasswordPopup = true
|
||||
}
|
||||
}
|
||||
.overlay {
|
||||
if isMenuOpen {
|
||||
|
|
|
|||
153
Linphone/UI/Main/Fragments/PopupUpdatePassword.swift
Normal file
153
Linphone/UI/Main/Fragments/PopupUpdatePassword.swift
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct PopupUpdatePassword: View {
|
||||
|
||||
@ObservedObject var sharedMainViewModel = SharedMainViewModel.shared
|
||||
|
||||
@Binding var isShowUpdatePasswordPopup: Bool
|
||||
@Binding var passwordUpdateAddress: String
|
||||
|
||||
@State private var passwordPopupText: String = ""
|
||||
@State private var isSecured: Bool = true
|
||||
|
||||
@FocusState var isPasswordFocused: Bool
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { geometry in
|
||||
VStack(alignment: .leading) {
|
||||
Text("account_settings_dialog_invalid_password_title")
|
||||
.default_text_style_800(styleSize: 16)
|
||||
.frame(alignment: .leading)
|
||||
.padding(.bottom, 2)
|
||||
|
||||
Text(String(format: String(localized: "account_settings_dialog_invalid_password_message"), passwordUpdateAddress))
|
||||
.default_text_style(styleSize: 15)
|
||||
.padding(.bottom, 20)
|
||||
|
||||
ZStack(alignment: .trailing) {
|
||||
Group {
|
||||
if isSecured {
|
||||
SecureField("account_settings_dialog_invalid_password_hint", text: $passwordPopupText)
|
||||
.default_text_style(styleSize: 15)
|
||||
.frame(height: 25)
|
||||
.focused($isPasswordFocused)
|
||||
} else {
|
||||
TextField("account_settings_dialog_invalid_password_hint", text: $passwordPopupText)
|
||||
.default_text_style(styleSize: 15)
|
||||
.disableAutocorrection(true)
|
||||
.autocapitalization(.none)
|
||||
.frame(height: 25)
|
||||
.focused($isPasswordFocused)
|
||||
}
|
||||
}
|
||||
|
||||
Button(action: {
|
||||
isSecured.toggle()
|
||||
}, label: {
|
||||
Image(self.isSecured ? "eye-slash" : "eye")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.grayMain2c500)
|
||||
.frame(width: 20, height: 20)
|
||||
})
|
||||
}
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.vertical, 15)
|
||||
.cornerRadius(60)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 60)
|
||||
.inset(by: 0.5)
|
||||
.stroke(isPasswordFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.padding(.bottom)
|
||||
|
||||
Button(action: {
|
||||
isShowUpdatePasswordPopup = false
|
||||
}, label: {
|
||||
Text("dialog_cancel")
|
||||
.default_text_style_orange_600(styleSize: 20)
|
||||
.frame(height: 35)
|
||||
.frame(maxWidth: .infinity)
|
||||
})
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.vertical, 10)
|
||||
.cornerRadius(60)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 60)
|
||||
.inset(by: 0.5)
|
||||
.stroke(Color.orangeMain500, lineWidth: 1)
|
||||
)
|
||||
.padding(.bottom, 10)
|
||||
|
||||
Button(action: {
|
||||
setNewPassword()
|
||||
isShowUpdatePasswordPopup = false
|
||||
}, label: {
|
||||
Text("dialog_ok")
|
||||
.default_text_style_white_600(styleSize: 20)
|
||||
.frame(height: 35)
|
||||
.frame(maxWidth: .infinity)
|
||||
})
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.vertical, 10)
|
||||
.background(passwordPopupText.isEmpty ? Color.orangeMain100 : Color.orangeMain500)
|
||||
.cornerRadius(60)
|
||||
.disabled(passwordPopupText.isEmpty)
|
||||
}
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.vertical, 20)
|
||||
.background(.white)
|
||||
.cornerRadius(20)
|
||||
.padding(.horizontal)
|
||||
.frame(maxHeight: .infinity)
|
||||
.shadow(color: Color.orangeMain500, radius: 0, x: 0, y: 2)
|
||||
.frame(maxWidth: SharedMainViewModel.shared.maxWidth)
|
||||
.position(x: geometry.size.width / 2, y: geometry.size.height / 2)
|
||||
}
|
||||
}
|
||||
|
||||
func setNewPassword() {
|
||||
CoreContext.shared.doOnCoreQueue { core in
|
||||
Log.info("[SetNewPassword] ---- \(core.defaultAccount?.params?.identityAddress?.asStringUriOnly() ?? "No account found") \(passwordUpdateAddress)")
|
||||
|
||||
if let account = core.accountList.first { $0.params?.identityAddress?.asStringUriOnly() == passwordUpdateAddress } {
|
||||
let authInfo = account.findAuthInfo()
|
||||
if (authInfo != nil) {
|
||||
Log.info(
|
||||
"[SetNewPassword] Updating password for username \(authInfo!.username) using auth info \(authInfo!)"
|
||||
)
|
||||
authInfo!.password = passwordPopupText
|
||||
core.addAuthInfo(info: authInfo!)
|
||||
core.refreshRegisters()
|
||||
} else {
|
||||
Log.warn(
|
||||
"[SetNewPassword] Failed to find auth info for account \(account.params?.identityAddress?.asStringUriOnly())"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
PopupUpdatePassword(isShowUpdatePasswordPopup: .constant(true), passwordUpdateAddress: .constant("example@sip.linphone.org"))
|
||||
}
|
||||
|
|
@ -1,9 +1,21 @@
|
|||
//
|
||||
// PopupViewWithTextField.swift
|
||||
// Linphone
|
||||
//
|
||||
// Created by Benoît Martins on 12/11/2024.
|
||||
//
|
||||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
|
||||
|
|
|
|||
|
|
@ -192,6 +192,7 @@
|
|||
D7E6D0552AEBFCCE00A57AAF /* ContactsInnerFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E6D0542AEBFCCE00A57AAF /* ContactsInnerFragment.swift */; };
|
||||
D7EAACCF2AD6ED8000AA6A8A /* PermissionsFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7EAACCE2AD6ED8000AA6A8A /* PermissionsFragment.swift */; };
|
||||
D7EFD1E42CD11F70005E67CD /* EphemeralFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7EFD1E32CD11F53005E67CD /* EphemeralFragment.swift */; };
|
||||
D7F01ADE2E1D0DA3006942C0 /* PopupUpdatePassword.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7F01ADD2E1D0D92006942C0 /* PopupUpdatePassword.swift */; };
|
||||
D7F4D9CB2B5FD27200CDCD76 /* CallsListFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7F4D9CA2B5FD27200CDCD76 /* CallsListFragment.swift */; };
|
||||
D7F5F6412C359F3B007FCF2F /* SipAddressesPopup.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7F5F6402C359F3B007FCF2F /* SipAddressesPopup.swift */; };
|
||||
D7FB55112AD447FD00A5AB15 /* RegisterFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FB55102AD447FD00A5AB15 /* RegisterFragment.swift */; };
|
||||
|
|
@ -408,6 +409,7 @@
|
|||
D7E6D0542AEBFCCE00A57AAF /* ContactsInnerFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsInnerFragment.swift; sourceTree = "<group>"; };
|
||||
D7EAACCE2AD6ED8000AA6A8A /* PermissionsFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionsFragment.swift; sourceTree = "<group>"; };
|
||||
D7EFD1E32CD11F53005E67CD /* EphemeralFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EphemeralFragment.swift; sourceTree = "<group>"; };
|
||||
D7F01ADD2E1D0D92006942C0 /* PopupUpdatePassword.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopupUpdatePassword.swift; sourceTree = "<group>"; };
|
||||
D7F4D9CA2B5FD27200CDCD76 /* CallsListFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallsListFragment.swift; sourceTree = "<group>"; };
|
||||
D7F5F6402C359F3B007FCF2F /* SipAddressesPopup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SipAddressesPopup.swift; sourceTree = "<group>"; };
|
||||
D7FB55102AD447FD00A5AB15 /* RegisterFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisterFragment.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -782,6 +784,7 @@
|
|||
D74C9CFD2ACAEC150021626A /* Fragments */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D7F01ADD2E1D0D92006942C0 /* PopupUpdatePassword.swift */,
|
||||
D74C9CFE2ACAEC5E0021626A /* PopupView.swift */,
|
||||
D72343352AD037AF009AA24E /* ToastView.swift */,
|
||||
D750D3382AD3E6EE00EC99C5 /* PopupLoadingView.swift */,
|
||||
|
|
@ -1342,6 +1345,7 @@
|
|||
D7C48DF62AFCDF4700D938CB /* ContactInnerActionsFragment.swift in Sources */,
|
||||
D72343322ACEFF58009AA24E /* QRScannerController.swift in Sources */,
|
||||
662B69D92B25DE18007118BF /* TelecomManager.swift in Sources */,
|
||||
D7F01ADE2E1D0DA3006942C0 /* PopupUpdatePassword.swift in Sources */,
|
||||
D72343342ACEFFC3009AA24E /* QRScanner.swift in Sources */,
|
||||
66246C6A2C622AE900973E97 /* TimeZoneExtension.swift in Sources */,
|
||||
66C491FB2B24D32600CEA16D /* CoreExtension.swift in Sources */,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue