From 1bac025291311c6f5557da456f0a07de7af4cd05 Mon Sep 17 00:00:00 2001 From: TSI-amrutwaghmare <96108296+TSI-amrutwaghmare@users.noreply.github.com> Date: Tue, 17 Oct 2023 17:16:37 +0530 Subject: [PATCH 1/3] NMC 1615 - Login screen status bar color update and title removed --- iOSClient/Login/NCLoginProvider.swift | 87 +++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 12 deletions(-) diff --git a/iOSClient/Login/NCLoginProvider.swift b/iOSClient/Login/NCLoginProvider.swift index 840fbbc535..859c37cb9a 100644 --- a/iOSClient/Login/NCLoginProvider.swift +++ b/iOSClient/Login/NCLoginProvider.swift @@ -3,12 +3,13 @@ // SPDX-License-Identifier: GPL-3.0-or-later import UIKit -@preconcurrency import WebKit +import WebKit import NextcloudKit import FloatingPanel class NCLoginProvider: UIViewController { var webView: WKWebView? + let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! let utility = NCUtility() var titleView: String = "" var urlBase = "" @@ -54,22 +55,34 @@ class NCLoginProvider: UIViewController { NCContentPresenter().showError(error: error, priority: .max) } - if let host = URL(string: urlBase)?.host { - titleView = host - if let activeTableAccount = NCManageDatabase.shared.getActiveTableAccount(), NCKeychain().getPassword(account: activeTableAccount.account).isEmpty { - titleView = NSLocalizedString("_user_", comment: "") + " " + activeTableAccount.userId + " " + NSLocalizedString("_in_", comment: "") + " " + host + if #available(iOS 13, *) { + let keyWindow = UIApplication.shared.connectedScenes + .filter({$0.activationState == .foregroundActive}) + .map({$0 as? UIWindowScene}) + .compactMap({$0}) + .first?.windows + .filter({$0.isKeyWindow}).first + let statusBar = UIView(frame: (keyWindow?.windowScene?.statusBarManager?.statusBarFrame)!) + statusBar.backgroundColor = NCBrandColor.shared.customer + keyWindow?.addSubview(statusBar) + } else { + if let statusBar = UIApplication.shared.value(forKey: "statusBar") as? UIView { + statusBar.backgroundColor = NCBrandColor.shared.customer } } + self.navigationController?.navigationBar.backgroundColor = NCBrandColor.shared.customer + } - self.title = titleView + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + // Stop timer error network + appDelegate.timerErrorNetworkingDisabled = true } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) NCActivityIndicator.shared.stop() - - pollTimer?.cancel() - pollTimer = nil + appDelegate.timerErrorNetworkingDisabled = false } func loadWebPage(webView: WKWebView, url: URL) { @@ -255,8 +268,58 @@ extension NCLoginProvider: WKNavigationDelegate { func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { NCActivityIndicator.shared.stop() } -} -protocol NCLoginProviderDelegate: AnyObject { - func onBack() + // MARK: - + + func createAccount(server: String, username: String, password: String) { + var urlBase = server + if urlBase.last == "/" { urlBase = String(urlBase.dropLast()) } + let account: String = "\(username) \(urlBase)" + let user = username + + NextcloudKit.shared.setup(account: account, user: user, userId: user, password: password, urlBase: urlBase) + NextcloudKit.shared.getUserProfile(account: account) { _, userProfile, _, error in + if error == .success, let userProfile { + NextcloudKit.shared.appendSession(account: account, + urlBase: urlBase, + user: user, + userId: user, + password: password, + userAgent: userAgent, + nextcloudVersion: NCCapabilities.shared.getCapabilities(account: account).capabilityServerVersionMajor, + httpMaximumConnectionsPerHost: NCBrandOptions.shared.httpMaximumConnectionsPerHost, + httpMaximumConnectionsPerHostInDownload: NCBrandOptions.shared.httpMaximumConnectionsPerHostInDownload, + httpMaximumConnectionsPerHostInUpload: NCBrandOptions.shared.httpMaximumConnectionsPerHostInUpload, + groupIdentifier: NCBrandOptions.shared.capabilitiesGroup) + NCSession.shared.appendSession(account: account, urlBase: urlBase, user: user, userId: userProfile.userId) + NCManageDatabase.shared.deleteAccount(account) + NCManageDatabase.shared.addAccount(account, urlBase: urlBase, user: user, userId: userProfile.userId, password: password) + self.appDelegate.changeAccount(account, userProfile: userProfile) { } + let window = UIApplication.shared.firstWindow + if window?.rootViewController is NCMainTabBarController { + self.dismiss(animated: true) + } else { + if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? NCMainTabBarController { + controller.modalPresentationStyle = .fullScreen + controller.view.alpha = 0 + + window?.rootViewController = controller + window?.makeKeyAndVisible() + + if let scene = window?.windowScene { + SceneManager.shared.register(scene: scene, withRootViewController: controller) + } + + UIView.animate(withDuration: 0.5) { + controller.view.alpha = 1 + } + } + } + } else { + let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: error.errorDescription, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in })) + self.present(alertController, animated: true) + } + } + } } From 6620deb0f5f348b9614c9bbb4665678b38d04985 Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Wed, 9 Apr 2025 11:54:02 +0530 Subject: [PATCH 2/3] NMC 1615 - Login screens customisation changes --- Nextcloud.xcodeproj/project.pbxproj | 8 + iOSClient/Login/NCLogin.storyboard | 15 + iOSClient/Login/NCLogin.swift | 27 +- iOSClient/Login/NCLoginProvider.swift | 17 +- iOSClient/Login/NCLoginWeb.swift | 370 ++++++++++++++++++ .../Login/NCViewCertificateDetails.swift | 4 +- 6 files changed, 427 insertions(+), 14 deletions(-) create mode 100644 iOSClient/Login/NCLoginWeb.swift diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index 05654d1b07..568b1d69f6 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -92,6 +92,9 @@ AFCE353527E4ED5900FEA6C2 /* DateFormatter+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353427E4ED5900FEA6C2 /* DateFormatter+Extension.swift */; }; AFCE353727E4ED7B00FEA6C2 /* NCShareCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */; }; AFCE353927E5DE0500FEA6C2 /* Shareable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* Shareable.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B54315302DA647A400981E7E /* NCLoginWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = B543152F2DA647A400981E7E /* NCLoginWeb.swift */; }; + C04E2F232A17BB4D001BAD85 /* FilesIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04E2F222A17BB4D001BAD85 /* FilesIntegrationTests.swift */; }; D575039F27146F93008DC9DC /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extension.swift */; }; D5B6AA7827200C7200D49C24 /* NCActivityTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */; }; F310B1EF2BA862F1001C42F5 /* NCViewerMedia+VisionKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = F310B1EE2BA862F1001C42F5 /* NCViewerMedia+VisionKit.swift */; }; @@ -1330,6 +1333,8 @@ AFCE353427E4ED5900FEA6C2 /* DateFormatter+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateFormatter+Extension.swift"; sourceTree = ""; }; AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCells.swift; sourceTree = ""; }; AFCE353827E5DE0400FEA6C2 /* Shareable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shareable.swift; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B543152F2DA647A400981E7E /* NCLoginWeb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCLoginWeb.swift; sourceTree = ""; }; C0046CDA2A17B98400D87C9D /* NextcloudUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NextcloudUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; C04E2F202A17BB4D001BAD85 /* NextcloudIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NextcloudIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCActivityTableViewCell.swift; sourceTree = ""; }; @@ -2969,6 +2974,8 @@ F7BFFA621A24D7300044ED85 /* Login */ = { isa = PBXGroup; children = ( + B543152F2DA647A400981E7E /* NCLoginWeb.swift */, + F3CA33802D106FF900672333 /* Poll */, F702F2F025EE5CDA008F8E80 /* NCLogin.storyboard */, F702F2F625EE5CEC008F8E80 /* NCLogin.swift */, F738D48F2756740100CD1D38 /* NCLoginNavigationController.swift */, @@ -4850,6 +4857,7 @@ F77BB748289985270090FC19 /* UITabBarController+Extension.swift in Sources */, F763D29D2A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */, F76882252C0DD1E7001CF441 /* NCSettingsAdvancedModel.swift in Sources */, + B54315302DA647A400981E7E /* NCLoginWeb.swift in Sources */, F7C7B489245EBA4100D93E60 /* NCViewerQuickLook.swift in Sources */, F758B45E212C569D00515F55 /* NCScanCell.swift in Sources */, F78B87E72B62527100C65ADC /* NCMediaDataSource.swift in Sources */, diff --git a/iOSClient/Login/NCLogin.storyboard b/iOSClient/Login/NCLogin.storyboard index 05bf9df04d..b6c2b6319d 100644 --- a/iOSClient/Login/NCLogin.storyboard +++ b/iOSClient/Login/NCLogin.storyboard @@ -162,6 +162,21 @@ + + + + + + + + + + + + + + + diff --git a/iOSClient/Login/NCLogin.swift b/iOSClient/Login/NCLogin.swift index 946e8c6300..2231f907d8 100644 --- a/iOSClient/Login/NCLogin.swift +++ b/iOSClient/Login/NCLogin.swift @@ -86,6 +86,9 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { baseUrlTextField.isUserInteractionEnabled = false baseUrlTextField.alpha = 0.5 } + + // qrcode + qrCode.setImage(UIImage(named: "qrcode")?.image(color: textColor, size: 100), for: .normal) // certificate certificate.setImage(UIImage(named: "certificate")?.image(color: textColor, size: 100), for: .normal) @@ -318,13 +321,23 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { let loginOptions = NKRequestOptions(customUserAgent: userAgent) NextcloudKit.shared.getLoginFlowV2(serverUrl: url, options: loginOptions) { [self] token, endpoint, login, _, error in // Login Flow V2 - if error == .success, let token, let endpoint, let login { - let safariVC = NCLoginProvider() - safariVC.urlBase = login - safariVC.uiColor = textColor - safariVC.delegate = self - safariVC.poll(loginFlowV2Token: token, loginFlowV2Endpoint: endpoint, loginFlowV2Login: login) - navigationController?.pushViewController(safariVC, animated: true) + if error == .success && NCBrandOptions.shared.use_loginflowv2 && token != nil && endpoint != nil && login != nil { + + if let loginWeb = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLoginWeb") as? NCLoginWeb { + + loginWeb.urlBase = url + loginWeb.user = user + loginWeb.loginFlowV2Available = true + loginWeb.loginFlowV2Token = token! + loginWeb.loginFlowV2Endpoint = endpoint! + loginWeb.loginFlowV2Login = login! + + self.navigationController?.pushViewController(loginWeb, animated: true) + } + } else if serverInfo.versionMajor < NCGlobal.shared.nextcloudVersion12 { // No login flow available + let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: NSLocalizedString("_webflow_not_available_", comment: ""), preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in })) + present(alertController, animated: true, completion: { }) } } case .failure(let error): diff --git a/iOSClient/Login/NCLoginProvider.swift b/iOSClient/Login/NCLoginProvider.swift index 859c37cb9a..06d8367f07 100644 --- a/iOSClient/Login/NCLoginProvider.swift +++ b/iOSClient/Login/NCLoginProvider.swift @@ -76,13 +76,20 @@ class NCLoginProvider: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // Stop timer error network - appDelegate.timerErrorNetworkingDisabled = true +// appDelegate.timerErrorNetworkingDisabled = true + if let account = NCManageDatabase.shared.getActiveTableAccount(), NCKeychain().getPassword(account: account.account).isEmpty { + + let message = "\n" + NSLocalizedString("_password_not_present_", comment: "") + let alertController = UIAlertController(title: titleView, message: message, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in })) + present(alertController, animated: true) + } } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) NCActivityIndicator.shared.stop() - appDelegate.timerErrorNetworkingDisabled = false +// appDelegate.timerErrorNetworkingDisabled = false } func loadWebPage(webView: WKWebView, url: URL) { @@ -277,7 +284,7 @@ extension NCLoginProvider: WKNavigationDelegate { let account: String = "\(username) \(urlBase)" let user = username - NextcloudKit.shared.setup(account: account, user: user, userId: user, password: password, urlBase: urlBase) +// NextcloudKit.shared.setup(account: account, user: user, userId: user, password: password, urlBase: urlBase) NextcloudKit.shared.getUserProfile(account: account) { _, userProfile, _, error in if error == .success, let userProfile { NextcloudKit.shared.appendSession(account: account, @@ -292,9 +299,9 @@ extension NCLoginProvider: WKNavigationDelegate { httpMaximumConnectionsPerHostInUpload: NCBrandOptions.shared.httpMaximumConnectionsPerHostInUpload, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup) NCSession.shared.appendSession(account: account, urlBase: urlBase, user: user, userId: userProfile.userId) - NCManageDatabase.shared.deleteAccount(account) + NCAccount().deleteAccount(account) NCManageDatabase.shared.addAccount(account, urlBase: urlBase, user: user, userId: userProfile.userId, password: password) - self.appDelegate.changeAccount(account, userProfile: userProfile) { } + NCAccount().changeAccount(account, userProfile: userProfile, controller: nil) { } let window = UIApplication.shared.firstWindow if window?.rootViewController is NCMainTabBarController { self.dismiss(animated: true) diff --git a/iOSClient/Login/NCLoginWeb.swift b/iOSClient/Login/NCLoginWeb.swift new file mode 100644 index 0000000000..daa39f5e6c --- /dev/null +++ b/iOSClient/Login/NCLoginWeb.swift @@ -0,0 +1,370 @@ +// +// NCLoginWeb.swift +// Nextcloud +// +// Created by Marino Faggiana on 21/08/2019. +// Copyright © 2019 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// 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 . +// + +import UIKit +import WebKit +import NextcloudKit +import FloatingPanel + +class NCLoginWeb: UIViewController { + + var webView: WKWebView? + var newWebView: WKWebView? + + let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! + let utility = NCUtility() + + var titleView: String = "" + + var urlBase = "" + var user: String? + + var configServerUrl: String? + var configUsername: String? + var configPassword: String? + var configAppPassword: String? + + var loginFlowV2Available = false + var loginFlowV2Token = "" + var loginFlowV2Endpoint = "" + var loginFlowV2Login = "" + + // MARK: - View Life Cycle + + override func viewDidLoad() { + super.viewDidLoad() + + let accountCount = NCManageDatabase.shared.getAccounts()?.count ?? 0 + + // load AppConfig + if (NCBrandOptions.shared.disable_multiaccount == false) || (NCBrandOptions.shared.disable_multiaccount == true && accountCount == 0) { + if let configurationManaged = UserDefaults.standard.dictionary(forKey: "com.apple.configuration.managed"), NCBrandOptions.shared.use_AppConfig { + + if let serverUrl = configurationManaged[NCGlobal.shared.configuration_serverUrl] as? String { + self.configServerUrl = serverUrl + } + if let username = configurationManaged[NCGlobal.shared.configuration_username] as? String, !username.isEmpty, username.lowercased() != "username" { + self.configUsername = username + } + if let password = configurationManaged[NCGlobal.shared.configuration_password] as? String, !password.isEmpty, password.lowercased() != "password" { + self.configPassword = password + } + if let apppassword = configurationManaged[NCGlobal.shared.configuration_apppassword] as? String, !apppassword.isEmpty, apppassword.lowercased() != "apppassword" { + self.configAppPassword = apppassword + } + } + } + + if (NCBrandOptions.shared.use_login_web_personalized || NCBrandOptions.shared.use_AppConfig) && accountCount > 0 { + navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .stop, target: self, action: #selector(self.closeView(sender:))) + } + + if accountCount > 0 { + navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "users")!.image(color: .label, size: 35), style: .plain, target: self, action: #selector(self.changeUser(sender:))) + } + + let config = WKWebViewConfiguration() + config.websiteDataStore = WKWebsiteDataStore.nonPersistent() + + webView = WKWebView(frame: CGRect.zero, configuration: config) + webView!.navigationDelegate = self +// webView!.uiDelegate = self + view.addSubview(webView!) + + webView!.translatesAutoresizingMaskIntoConstraints = false + webView!.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true + webView!.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true + webView!.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true + webView!.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true + + // AppConfig + if let serverUrl = configServerUrl { + if let username = self.configUsername, let password = configAppPassword { + self.createAccount(urlBase: serverUrl, user: username, password: password) + return + } else if let username = self.configUsername, let password = configPassword { + getAppPassword(urlBase: serverUrl, user: username, password: password) + return + } else { + urlBase = serverUrl + } + } + + // ADD end point for Web Flow + if urlBase != NCBrandOptions.shared.linkloginPreferredProviders { + if loginFlowV2Available { + urlBase = loginFlowV2Login + } else { + urlBase += "/index.php/login/flow" + if let user = self.user { + urlBase += "?user=\(user)" + } + } + } + + if let url = URL(string: urlBase) { + loadWebPage(webView: webView!, url: url) + } else { + let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_login_url_error_") + NCContentPresenter().showError(error: error, priority: .max) + } + + if #available(iOS 13, *) { + let keyWindow = UIApplication.shared.connectedScenes + .filter({$0.activationState == .foregroundActive}) + .map({$0 as? UIWindowScene}) + .compactMap({$0}) + .first?.windows + .filter({$0.isKeyWindow}).first + let statusBar = UIView(frame: (keyWindow?.windowScene?.statusBarManager?.statusBarFrame)!) + statusBar.backgroundColor = NCBrandColor.shared.customer + keyWindow?.addSubview(statusBar) + } else { + if let statusBar = UIApplication.shared.value(forKey: "statusBar") as? UIView { + statusBar.backgroundColor = NCBrandColor.shared.customer + } + } + self.navigationController?.navigationBar.backgroundColor = NCBrandColor.shared.customer + self.edgesForExtendedLayout = [] // iphone 16, white gap between navigaiton and status bar. + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + // Stop timer error network + appDelegate.timerErrorNetworking?.invalidate() + + if let account = NCManageDatabase.shared.getActiveTableAccount(), NCKeychain().getPassword(account: account.account).isEmpty { + + let message = "\n" + NSLocalizedString("_password_not_present_", comment: "") + let alertController = UIAlertController(title: titleView, message: message, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in })) + present(alertController, animated: true) + } + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + NCActivityIndicator.shared.stop() + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + + // Start timer error network + appDelegate.startTimerErrorNetworking() + } + + func loadWebPage(webView: WKWebView, url: URL) { + + let language = NSLocale.preferredLanguages[0] as String + var request = URLRequest(url: url) + + if let deviceName = "\(UIDevice.current.name) (\(NCBrandOptions.shared.brand) iOS)".cString(using: .utf8), + let deviceUserAgent = String(cString: deviceName, encoding: .ascii) { + webView.customUserAgent = deviceUserAgent + } else { + webView.customUserAgent = userAgent + } + + request.addValue("true", forHTTPHeaderField: "OCS-APIRequest") + request.addValue(language, forHTTPHeaderField: "Accept-Language") + + webView.load(request) + } + + func getAppPassword(urlBase: String, user: String, password: String) { + + NextcloudKit.shared.getAppPassword(url: urlBase, user: user, password: password) { token, _, error in + if error == .success, let password = token { + self.createAccount(urlBase: urlBase, user: user, password: password) + } else { + NCContentPresenter().showError(error: error) + self.dismiss(animated: true, completion: nil) + } + } + } + + @objc func closeView(sender: UIBarButtonItem) { + self.dismiss(animated: true, completion: nil) + } + + @objc func changeUser(sender: UIBarButtonItem) { +// toggleMenu() + } +} + +extension NCLoginWeb: WKNavigationDelegate { + + func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) { + + guard let url = webView.url else { return } + + let urlString: String = url.absoluteString.lowercased() + + // prevent http redirection + if urlBase.lowercased().hasPrefix("https://") && urlString.lowercased().hasPrefix("http://") { + let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: NSLocalizedString("_prevent_http_redirection_", comment: ""), preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in + _ = self.navigationController?.popViewController(animated: true) + })) + self.present(alertController, animated: true) + return + } + + if urlString.hasPrefix(NCBrandOptions.shared.webLoginAutenticationProtocol) == true && urlString.contains("login") == true { + + var server: String = "" + var user: String = "" + var password: String = "" + + let keyValue = url.path.components(separatedBy: "&") + for value in keyValue { + if value.contains("server:") { server = value } + if value.contains("user:") { user = value } + if value.contains("password:") { password = value } + } + + if !server.isEmpty, !user.isEmpty, !password.isEmpty { + + let server: String = server.replacingOccurrences(of: "/server:", with: "") + let username: String = user.replacingOccurrences(of: "user:", with: "").replacingOccurrences(of: "+", with: " ") + let password: String = password.replacingOccurrences(of: "password:", with: "") + + self.createAccount(urlBase: server, user: username, password: password) + + } + } + } + + func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { + DispatchQueue.global().async { + if let serverTrust = challenge.protectionSpace.serverTrust { + completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: serverTrust)) + } else { + completionHandler(URLSession.AuthChallengeDisposition.useCredential, nil) + } + } + } + + func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { + decisionHandler(.allow) + } + + func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) { + if let httpResponse = navigationResponse.response as? HTTPURLResponse { + print("Response status code: \(httpResponse.statusCode)") + + if httpResponse.statusCode == 403 { +// showAccessDeniedAlert() + closeApp() + decisionHandler(.cancel) // Stop loading the page + } else { + decisionHandler(.allow) + } + } else { + decisionHandler(.allow) + } + } + + + // Show an alert instead of closing the app + private func showAccessDeniedAlert() { + DispatchQueue.main.async { + let alert = UIAlertController(title: "Access Denied", message: "You are not authorized to view this page.", preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in + // Optionally, redirect user + self.webView?.load(URLRequest(url: URL(string: "https://www.google.com")!)) + })) + self.present(alert, animated: true, completion: nil) + } + } + + func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { + NCActivityIndicator.shared.startActivity(style: .medium, blurEffect: false) + } + + func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { + + NCActivityIndicator.shared.stop() + + if loginFlowV2Available { + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + NextcloudKit.shared.getLoginFlowV2Poll(token: self.loginFlowV2Token, endpoint: self.loginFlowV2Endpoint) { server, loginName, appPassword, _, error in + if error == .success && server != nil && loginName != nil && appPassword != nil { + self.createAccount(urlBase: server!, user: loginName!, password: appPassword!) + } + } + } + } + } + + + private func closeApp() { + // Exit the app immediately + exit(0) + } + + + // MARK: - + + func createAccount(urlBase: String, user: String, password: String) { + let controller = UIApplication.shared.firstWindow?.rootViewController as? NCMainTabBarController + if let host = URL(string: urlBase)?.host { + NCNetworking.shared.writeCertificate(host: host) + } + NCAccount().createAccount(urlBase: urlBase, user: user, password: password, controller: controller) { account, error in + if error == .success { + let window = UIApplication.shared.firstWindow + if let controller = window?.rootViewController as? NCMainTabBarController { + controller.account = account + self.dismiss(animated: true) + } else { + if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? NCMainTabBarController { + AnalyticsHelper.shared.trackUserData() + controller.account = account + controller.modalPresentationStyle = .fullScreen + controller.view.alpha = 0 + + window?.rootViewController = controller + window?.makeKeyAndVisible() + + if let scene = window?.windowScene { + SceneManager.shared.register(scene: scene, withRootViewController: controller) + } + + UIView.animate(withDuration: 0.5) { + controller.view.alpha = 1 + } + } + } + } else { + let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: error.errorDescription, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in })) + self.present(alertController, animated: true) + } + } + } + +} diff --git a/iOSClient/Login/NCViewCertificateDetails.swift b/iOSClient/Login/NCViewCertificateDetails.swift index 04be62adc6..d70e4369cb 100644 --- a/iOSClient/Login/NCViewCertificateDetails.swift +++ b/iOSClient/Login/NCViewCertificateDetails.swift @@ -42,9 +42,9 @@ class NCViewCertificateDetails: UIViewController { var delegate: NCViewCertificateDetailsDelegate? let utilityFileSystem = NCUtilityFileSystem() - public var host: String = "" + @objc public var host: String = "" public var fileNamePath: String = "" - public var certificateTitle = NSLocalizedString("_certificate_view_", comment: "") + @objc public var certificateTitle = NSLocalizedString("_certificate_view_", comment: "") // MARK: - View Life Cycle From 7e8ebb27f457c309a106cf133130c5d2c76ff472 Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Wed, 9 Apr 2025 11:55:14 +0530 Subject: [PATCH 3/3] NMC 2615 - Login screens customisation changes --- iOSClient/Login/NCLogin.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/iOSClient/Login/NCLogin.swift b/iOSClient/Login/NCLogin.swift index 2231f907d8..6b9e16813f 100644 --- a/iOSClient/Login/NCLogin.swift +++ b/iOSClient/Login/NCLogin.swift @@ -318,8 +318,7 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate { if let host = URL(string: url)?.host { NCNetworking.shared.writeCertificate(host: host) } - let loginOptions = NKRequestOptions(customUserAgent: userAgent) - NextcloudKit.shared.getLoginFlowV2(serverUrl: url, options: loginOptions) { [self] token, endpoint, login, _, error in + NextcloudKit.shared.getLoginFlowV2(serverUrl: url) { [self] token, endpoint, login, _, error in // Login Flow V2 if error == .success && NCBrandOptions.shared.use_loginflowv2 && token != nil && endpoint != nil && login != nil {