Skip to content

Commit

Permalink
Added Additional OAuth and Certificate Infos (#325)
Browse files Browse the repository at this point in the history
* #267 - added a info view as tableview header for showing additional informations for OAuth 2 login
- added additional informations for certificate validation as label and text

* better value handling

* changed function name to better reflect, what it does

* now using theme colors

* fixed typo

* Fix for http connections and OAuth authentication
- new sdk is used, which supports warnings for https connections
- for http connections, continue only, if OAuthInfoHeader was shown to the user, before OAuth authentication is performed

* fixed ui test for OAuth http test, added additional Continue step

* - correct handling of OAuth Header in edit mode
- remove certificate description, if certificate was removed from bookmark
- added new helper methods for updating header / footer title in TableView Section without loosing text field focus

* - fixed wrong table header view height, if it was not set
- fixed additional continue step in edit mode for http token based connections

* fixed ui test, because password field is not visible on iPhone 8 (used test device)
  • Loading branch information
hosy authored Mar 26, 2019
1 parent 7876c51 commit db0990f
Show file tree
Hide file tree
Showing 16 changed files with 469 additions and 6 deletions.
16 changes: 16 additions & 0 deletions ownCloud.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
39607CBC2225D480007B386D /* UITableViewController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39607CBB2225D480007B386D /* UITableViewController+Extension.swift */; };
3971B48F221B23FE006FB441 /* ThemeableColoredView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3971B48E221B23FE006FB441 /* ThemeableColoredView.swift */; };
39878B7421FB1DE800DBF693 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39878B7321FB1DE800DBF693 /* UINavigationController+Extension.swift */; };
3998F5CC2240CD8300B66713 /* RoundedInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3998F5CB2240CD8300B66713 /* RoundedInfoView.swift */; };
3998F5D3224102FE00B66713 /* UITableView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3998F5D2224102FE00B66713 /* UITableView+Extension.swift */; };
3998F5D522411EDF00B66713 /* BorderedLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3998F5D422411EDF00B66713 /* BorderedLabel.swift */; };
3998F5D72241486F00B66713 /* OCCertificate+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3998F5D62241486F00B66713 /* OCCertificate+Extension.swift */; };
39E2FDED21FDEC7500F0117F /* ServerListTableHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39E2FDEC21FDEC7500F0117F /* ServerListTableHeaderView.swift */; };
39E2FE0021FF814A00F0117F /* ThemeRoundedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39E2FDFF21FF814A00F0117F /* ThemeRoundedButton.swift */; };
4C1561E8222321E0009C4EF3 /* PhotoSelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1561E7222321E0009C4EF3 /* PhotoSelectionViewController.swift */; };
Expand Down Expand Up @@ -472,6 +476,10 @@
39607CBB2225D480007B386D /* UITableViewController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableViewController+Extension.swift"; sourceTree = "<group>"; };
3971B48E221B23FE006FB441 /* ThemeableColoredView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeableColoredView.swift; sourceTree = "<group>"; };
39878B7321FB1DE800DBF693 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = "<group>"; };
3998F5CB2240CD8300B66713 /* RoundedInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedInfoView.swift; sourceTree = "<group>"; };
3998F5D2224102FE00B66713 /* UITableView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableView+Extension.swift"; sourceTree = "<group>"; };
3998F5D422411EDF00B66713 /* BorderedLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BorderedLabel.swift; sourceTree = "<group>"; };
3998F5D62241486F00B66713 /* OCCertificate+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OCCertificate+Extension.swift"; sourceTree = "<group>"; };
39E2FDEC21FDEC7500F0117F /* ServerListTableHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerListTableHeaderView.swift; sourceTree = "<group>"; };
39E2FDFF21FF814A00F0117F /* ThemeRoundedButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeRoundedButton.swift; sourceTree = "<group>"; };
4C1561E7222321E0009C4EF3 /* PhotoSelectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoSelectionViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -865,6 +873,7 @@
4C235CED21F88C0300A989A8 /* UIViewController+Extension.swift */,
4CF8CAB021F9B70500B8CA67 /* UIBarButtonItem+Extension.swift */,
39607CBB2225D480007B386D /* UITableViewController+Extension.swift */,
3998F5D2224102FE00B66713 /* UITableView+Extension.swift */,
);
path = "UIKit Extensions";
sourceTree = "<group>";
Expand Down Expand Up @@ -1255,6 +1264,7 @@
DCE5E8B72080D8D9005F60CE /* OCItem+Extension.swift */,
DC136581208223F000FC0F60 /* OCBookmark+Extension.swift */,
DC4FEAE6209E3A7700D4476B /* OCIssue+Extension.swift */,
3998F5D62241486F00B66713 /* OCCertificate+Extension.swift */,
);
path = "SDK Extensions";
sourceTree = "<group>";
Expand Down Expand Up @@ -1290,6 +1300,8 @@
6E0A569D218702400056B7B4 /* DownloadFileProgressHUDViewController.swift */,
DC63208621FCEE5D007EC0A8 /* ProgressView.swift */,
3971B48E221B23FE006FB441 /* ThemeableColoredView.swift */,
3998F5CB2240CD8300B66713 /* RoundedInfoView.swift */,
3998F5D422411EDF00B66713 /* BorderedLabel.swift */,
);
path = "UI Elements";
sourceTree = "<group>";
Expand Down Expand Up @@ -1807,9 +1819,11 @@
DC680576212DF548006C3B1F /* CertificateManagementViewController.swift in Sources */,
DC7DBA25207F684700E7337D /* ThemeResource.swift in Sources */,
DC01CDCC212EDDF600FC8E38 /* TextViewController.swift in Sources */,
3998F5D72241486F00B66713 /* OCCertificate+Extension.swift in Sources */,
6E4F1734217749910049A71B /* ImageDisplayViewController.swift in Sources */,
DC6CF7FB219446050013B9F9 /* LogSettingsViewController.swift in Sources */,
39878B7421FB1DE800DBF693 /* UINavigationController+Extension.swift in Sources */,
3998F5CC2240CD8300B66713 /* RoundedInfoView.swift in Sources */,
23EC775D2137FB6B0032D4E6 /* WebViewDisplayViewController.swift in Sources */,
DC018F8C20A1060A00135198 /* ProgressHUDViewController.swift in Sources */,
DC7DBA29207F71D600E7337D /* VectorImage.swift in Sources */,
Expand Down Expand Up @@ -1839,6 +1853,7 @@
23FA23E620BFD3D8009A6D73 /* SortBar.swift in Sources */,
3971B48F221B23FE006FB441 /* ThemeableColoredView.swift in Sources */,
4C1561E8222321E0009C4EF3 /* PhotoSelectionViewController.swift in Sources */,
3998F5D3224102FE00B66713 /* UITableView+Extension.swift in Sources */,
6E83C78420A33C180066EC23 /* LAContext+Extension.swift in Sources */,
593BAB46209AE1BC00023634 /* PasscodeViewController.swift in Sources */,
DC6428D02081406800493A01 /* CollapsibleProgressBar.swift in Sources */,
Expand Down Expand Up @@ -1869,6 +1884,7 @@
6E5FC172221590B000F60846 /* GalleryHostViewController.swift in Sources */,
DC85493421831B0B00782BA8 /* Tools.swift in Sources */,
DCFED972208095E200A2D984 /* ClientItemCell.swift in Sources */,
3998F5D522411EDF00B66713 /* BorderedLabel.swift in Sources */,
23E22BB720C6A5C40024D11E /* UIDevice+UIUserInterfaceIdiom.swift in Sources */,
4C235CEE21F88C0300A989A8 /* UIViewController+Extension.swift in Sources */,
23F6238120B587EF004FDE8B /* SortMethod.swift in Sources */,
Expand Down
62 changes: 59 additions & 3 deletions ownCloud/Bookmarks/BookmarkViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class BookmarkViewController: StaticTableViewController {
var passwordRow : StaticTableViewRow?
var tokenInfoRow : StaticTableViewRow?
var deleteAuthDataButtonRow : StaticTableViewRow?
var oAuthInfoView : RoundedInfoView?
var showOAuthInfoHeader = false
var showedOAuthInfoHeader : Bool = false
var activeTextField: UITextField?

lazy var continueBarButtonItem: UIBarButtonItem = UIBarButtonItem(title: "Continue".localized, style: .done, target: self, action: #selector(handleContinue))
Expand Down Expand Up @@ -133,6 +136,7 @@ class BookmarkViewController: StaticTableViewController {
}

if changedBookmark {
self?.showOAuthInfoHeader = false
self?.composeSectionsAndRows(animated: true)
}

Expand All @@ -148,7 +152,7 @@ class BookmarkViewController: StaticTableViewController {
self?.present(navigationController, animated: true, completion: nil)
}
}
}, title: "Certificate Details".localized, accessoryType: .disclosureIndicator, identifier: "row-url-certificate")
}, title: "Certificate Details".localized, accessoryType: .disclosureIndicator, accessoryView: BorderedLabel(), identifier: "row-url-certificate")

urlSection = StaticTableViewSection(headerTitle: "Server URL".localized, footerTitle: nil, identifier: "section-url", rows: [ urlRow! ])

Expand All @@ -173,6 +177,14 @@ class BookmarkViewController: StaticTableViewController {

deleteAuthDataButtonRow = StaticTableViewRow(buttonWithAction: { [weak self] (_, _) in
if self?.bookmark?.authenticationData != nil {

if let authMethodIdentifier = self?.bookmark?.authenticationMethodIdentifier {
if self?.isAuthenticationMethodTokenBased(authMethodIdentifier as OCAuthenticationMethodIdentifier) ?? false {
self?.showOAuthInfoHeader = true
self?.showedOAuthInfoHeader = true
}
}

self?.bookmark?.authenticationMethodIdentifier = nil
self?.bookmark?.authenticationData = nil
self?.updateUI(from: (self?.bookmark)!, fieldSelector: { (row) -> Bool in
Expand All @@ -185,6 +197,10 @@ class BookmarkViewController: StaticTableViewController {

credentialsSection = StaticTableViewSection(headerTitle: "Credentials".localized, footerTitle: nil, identifier: "section-credentials", rows: [ usernameRow!, passwordRow! ])

var oAuthInfoText = "If you 'Continue', you will be prompted to allow the '%@' App to open OAuth2 login where you can enter your credentials.".localized
oAuthInfoText = oAuthInfoText.replacingOccurrences(of: "%@", with: OCAppIdentity.shared.appName ?? "ownCloud")
oAuthInfoView = RoundedInfoView(text: oAuthInfoText)

// Input focus tracking
urlRow?.textField?.delegate = self
passwordRow?.textField?.delegate = self
Expand Down Expand Up @@ -249,6 +265,15 @@ class BookmarkViewController: StaticTableViewController {
self.updateInputFocus()
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
if size.width != self.view.frame.size.width {
DispatchQueue.main.async {
self.tableView.layoutTableHeaderView()
}
}
}

// MARK: - Continue
@objc func handleContinue() {
let hud : ProgressHUDViewController? = ProgressHUDViewController(on: nil)
Expand All @@ -269,7 +294,21 @@ class BookmarkViewController: StaticTableViewController {
}

if bookmark?.authenticationData == nil {
handleContinueAuthentication(hud: hud, hudCompletion: hudCompletion)
var proceed = true
if let authMethodIdentifier = bookmark?.authenticationMethodIdentifier {
if isAuthenticationMethodTokenBased(authMethodIdentifier as OCAuthenticationMethodIdentifier) {
// Only proceed, if OAuth Info Header was shown to the user, before continue was pressed
// Statement here is only important for http connections and token based auth
if showedOAuthInfoHeader == false {
proceed = false
showedOAuthInfoHeader = true
}
}
}
if proceed == true {
handleContinueAuthentication(hud: hud, hudCompletion: hudCompletion)
}

return
}
}
Expand Down Expand Up @@ -506,9 +545,18 @@ class BookmarkViewController: StaticTableViewController {
if bookmark?.certificate != nil {
if certificateRow != nil, certificateRow?.attached == false {
urlSection?.add(row: certificateRow!, animated: animated)
showedOAuthInfoHeader = true
bookmark?.certificate?.validationResult(completionHandler: { (_, shortDescription, longDescription, color, _) in
OnMainThread {
guard let accessoryView = self.certificateRow?.additionalAccessoryView as? BorderedLabel else { return }
accessoryView.update(text: shortDescription, color: color)
}
self.urlSection?.footerTitle = longDescription
})
}
} else {
if certificateRow != nil, certificateRow?.attached == true {
urlSection?.updateFooter(title: nil)
urlSection?.remove(rows: [certificateRow!], animated: animated)
}
}
Expand All @@ -520,7 +568,6 @@ class BookmarkViewController: StaticTableViewController {

// Credentials section: show depending on authentication method and data
var showCredentialsSection = false

if let authenticationMethodIdentifier = bookmark?.authenticationMethodIdentifier {
// Username & Password: show if passphrase-based authentication method is used
if let authenticationMethodClass = OCAuthenticationMethod.registeredAuthenticationMethod(forIdentifier: authenticationMethodIdentifier) {
Expand Down Expand Up @@ -588,6 +635,8 @@ class BookmarkViewController: StaticTableViewController {
}

showCredentialsSection = true
} else {
showOAuthInfoHeader = true
}
}

Expand All @@ -611,6 +660,13 @@ class BookmarkViewController: StaticTableViewController {
}
}

if showOAuthInfoHeader {
self.tableView.tableHeaderView = oAuthInfoView
self.tableView.layoutTableHeaderView()
} else {
self.tableView.tableHeaderView?.removeFromSuperview()
}

// Continue button: show always
if isBookmarkComplete(bookmark: self.bookmark) {
if self.mode == .create {
Expand Down
9 changes: 9 additions & 0 deletions ownCloud/Resources/de-DE.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@
"Authenticated as %@ via %@" = "Authentifiziert als 1%@ über 1%@";
"Edit" = "Bearbeiten";
"Credentials" = "Zugangsdaten";
"Rejected" = "Abgelehnt";
"Passed" = "Bestanden";
"Accepted" = "Akzeptiert";
"Validation Error" = "Validierungsfehler";
"Certificate was rejected by user." = "Zertifikat wurde vom Benutzer abgelehnt.";
"Certificate has issues.\nOpen 'Certificate Details' for more informations." = "Zertifikat hat Probleme.\nÖffnen Sie 'Zertifikat-Details' für weitere Informationen.";
"No issues found. Certificate passed validation." = "Keine Probleme gefunden. Zertifikat hat die Validierung bestanden.";
"Certificate may have issues, but was accepted by user.\nOpen 'Certificate Details' for more informations." = "Das Zertifikat hat möglicherweise Probleme, wurde aber vom Benutzer akzeptiert.\nÖffnen Sie 'Zertifikat-Details' für weitere Informationen.";
"If you 'Continue', you will be prompted to allow the '%@' App to open OAuth2 login where you can enter your credentials." = "Wenn Sie auf 'Fortsetzen' klicken, werden Sie aufgefordert, der App '%@' zu erlauben, die Anmeldung bei OAuth2 zu öffnen, wo Sie Ihre Zugangsdaten eingeben können.";

"Contacting server…" = "Verbinde zu Server ...";
"Authenticating…" = "Anmeldung läuft";
Expand Down
9 changes: 9 additions & 0 deletions ownCloud/Resources/de.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@
"Authenticated as %@ via %@" = "Als %@ mit %@ angemeldet";
"Edit" = "Bearbeiten";
"Credentials" = "Zugangsdaten";
"Rejected" = "Abgelehnt";
"Passed" = "Bestanden";
"Accepted" = "Akzeptiert";
"Validation Error" = "Validierungsfehler";
"Certificate was rejected by user." = "Zertifikat wurde vom Benutzer abgelehnt.";
"Certificate has issues.\nOpen 'Certificate Details' for more informations." = "Zertifikat hat Probleme.\nÖffnen Sie 'Zertifikat-Details' für weitere Informationen.";
"No issues found. Certificate passed validation." = "Keine Probleme gefunden. Zertifikat hat die Validierung bestanden.";
"Certificate may have issues, but was accepted by user.\nOpen 'Certificate Details' for more informations." = "Das Zertifikat hat möglicherweise Probleme, wurde aber vom Benutzer akzeptiert.\nÖffnen Sie 'Zertifikat-Details' für weitere Informationen.";
"If you 'Continue', you will be prompted to allow the '%@' App to open OAuth2 login where you can enter your credentials." = "Wenn Sie auf 'Fortsetzen' klicken, werden Sie aufgefordert, der App '%@' zu erlauben, die Anmeldung bei OAuth2 zu öffnen, wo Sie Ihre Zugangsdaten eingeben können.";

"Contacting server…" = "Kontaktiere Server...";
"Authenticating…" = "Authentifiziere";
Expand Down
9 changes: 9 additions & 0 deletions ownCloud/Resources/en-GB.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@
"Review Connection" = "Review Connection";
"Authenticated via" = "Authenticated via";
"Authenticated as %@ via %@" = "Authenticated as %@ via %@";
"Rejected" = "Rejected";
"Passed" = "Passed";
"Accepted" = "Accepted";
"Validation Error" = "Validation Error";
"Certificate was rejected by user." = "Certificate was rejected by user.";
"Certificate has issues.\nOpen 'Certificate Details' for more informations." = "Certificate has issues.\nOpen 'Certificate Details' for more informations.";
"No issues found. Certificate passed validation." = "No issues found. Certificate passed validation.";
"Certificate may have issues, but was accepted by user.\nOpen 'Certificate Details' for more informations." = "Certificate may have issues, but was accepted by user.\nOpen 'Certificate Details' for more informations.";
"If you 'Continue', you will be prompted to allow the '%@' App to open OAuth2 login where you can enter your credentials." = "If you 'Continue', you will be prompted to allow the '%@' App to open OAuth2 login where you can enter your credentials.";

"Contacting server…" = "Contacting server…";
"Authenticating…" = "Authenticating…";
Expand Down
9 changes: 9 additions & 0 deletions ownCloud/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@
"Authenticated as %@ via %@" = "Authenticated as %@ via %@";
"Edit" = "Edit";
"Credentials" = "Credentials";
"Rejected" = "Rejected";
"Passed" = "Passed";
"Accepted" = "Accepted";
"Validation Error" = "Validation Error";
"Certificate was rejected by user." = "Certificate was rejected by user.";
"Certificate has issues.\nOpen 'Certificate Details' for more informations." = "Certificate has issues.\nOpen 'Certificate Details' for more informations.";
"No issues found. Certificate passed validation." = "No issues found. Certificate passed validation.";
"Certificate may have issues, but was accepted by user.\nOpen 'Certificate Details' for more informations." = "Certificate may have issues, but was accepted by user.\nOpen 'Certificate Details' for more informations.";
"If you 'Continue', you will be prompted to allow the '%@' App to open OAuth2 login where you can enter your credentials." = "If you 'Continue', you will be prompted to allow the '%@' App to open OAuth2 login where you can enter your credentials.";

"Contacting server…" = "Contacting server…";
"Authenticating…" = "Authenticating…";
Expand Down
59 changes: 59 additions & 0 deletions ownCloud/SDK Extensions/OCCertificate+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// OCCertificate+Extension.swift
// ownCloud
//
// Created by Matthias Hühne on 19.03.19.
// Copyright © 2019 ownCloud GmbH. All rights reserved.
//

/*
* Copyright (C) 2019, ownCloud GmbH.
*
* This code is covered by the GNU Public License Version 3.
*
* For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/
* You should have received a copy of this license along with this program. If not, see <http://www.gnu.org/licenses/gpl-3.0.en.html>.
*
*/

import UIKit
import ownCloudSDK

extension OCCertificate {

func validationResult(completionHandler: @escaping (_ status: OCCertificateValidationResult, _ shortDescription : String, _ longDescription : String, _ color : UIColor, _ error : Error) -> Void) {

self.evaluate(completionHandler: { (_, status, error) in
var color = UIColor.red
var shortDescription = ""
var longDescription = ""

switch status {

case .none:
break
case .error:
color = Theme.shared.activeCollection.errorColor
shortDescription = "Error".localized
longDescription = "\("Validation Error".localized) \(error.localizedDescription)"
case .reject:
color = Theme.shared.activeCollection.errorColor
shortDescription = "Rejected".localized
longDescription = "Certificate was rejected by user.".localized
case .promptUser:
color = Theme.shared.activeCollection.warningColor
shortDescription = "Warning".localized
longDescription = "Certificate has issues.\nOpen 'Certificate Details' for more informations.".localized
case .passed:
color = Theme.shared.activeCollection.successColor
shortDescription = "Passed".localized
longDescription = "No issues found. Certificate passed validation.".localized
case .userAccepted:
color = Theme.shared.activeCollection.warningColor
shortDescription = "Accepted".localized
longDescription = "Certificate may have issues, but was accepted by user.\nOpen 'Certificate Details' for more informations.".localized
}
completionHandler(status, shortDescription, longDescription, color, error)
})
}
}
2 changes: 1 addition & 1 deletion ownCloud/SDK Extensions/OCIssue+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ extension OCIssue {
}
}

case .urlRedirection, .certificate, .error, .multipleChoice:
case .urlRedirection, .certificate, .error, .generic, .multipleChoice:
displayIssues = [self]
}

Expand Down
Loading

0 comments on commit db0990f

Please sign in to comment.