Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a5bb815
WIP
mpivchev Nov 13, 2024
25bcaba
WIP
mpivchev Nov 14, 2024
e6015cf
WIP
mpivchev Nov 15, 2024
9aef669
Finish
mpivchev Nov 15, 2024
37a108a
Merge branch 'develop' of https://github.com/nextcloud/ios into enfor…
mpivchev Nov 15, 2024
3020b69
WIP
mpivchev Nov 13, 2024
eec0518
WIP
mpivchev Nov 14, 2024
ca2731a
WIP
mpivchev Nov 15, 2024
b7be621
Finish
mpivchev Nov 15, 2024
fdeff27
Merge branch 'enfore_lock' of https://github.com/nextcloud/ios into e…
marinofaggiana Nov 18, 2024
075e2c7
WIP
mpivchev Nov 19, 2024
d229d9f
Merge branch 'enfore_lock' of https://github.com/nextcloud/ios into e…
mpivchev Nov 19, 2024
baf787c
WIP
mpivchev Nov 19, 2024
84252b9
WIP
mpivchev Nov 26, 2024
475f7fa
Merge branch 'develop' of https://github.com/nextcloud/ios into enfor…
mpivchev Nov 26, 2024
280eb62
WIP
mpivchev Nov 26, 2024
983f08c
Merge branch 'develop' of https://github.com/nextcloud/ios into enfor…
mpivchev Nov 27, 2024
90ed82d
WIP
mpivchev Nov 27, 2024
52e98fa
WIP
mpivchev Nov 27, 2024
dcff66b
WIP
mpivchev Nov 27, 2024
e8ab444
WIP
mpivchev Nov 28, 2024
190869c
WIP
mpivchev Nov 28, 2024
3017823
WIP
mpivchev Nov 28, 2024
f3bb4e5
added didAttemptCurrentPasscode
marinofaggiana Nov 28, 2024
d74a381
Refactor
mpivchev Nov 28, 2024
96400ff
Merge branch 'develop' of https://github.com/nextcloud/ios into enfor…
mpivchev Nov 28, 2024
47fc019
Merge branch 'enfore_lock' of https://github.com/nextcloud/ios into e…
marinofaggiana Nov 29, 2024
32973f5
Fix build
mpivchev Nov 29, 2024
6742283
Add attempt check
mpivchev Nov 29, 2024
02b40e1
Fix
mpivchev Nov 29, 2024
592ae6a
WIP
mpivchev Nov 29, 2024
c22be9e
Refactor
mpivchev Nov 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Brand/NCBrand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ let userAgent: String = {
var disable_show_more_nextcloud_apps_in_settings: Bool = false
var doNotAskPasscodeAtStartup: Bool = false
var disable_source_code_in_settings: Bool = false
var enforce_protection = true

This comment was marked as resolved.


// (name: "Name 1", url: "https://cloud.nextcloud.com"),(name: "Name 2", url: "https://cloud.nextcloud.com")
var enforce_servers: [(name: String, url: String)] = []
Expand Down Expand Up @@ -117,6 +118,9 @@ let userAgent: String = {
if let str = configurationManaged[NCGlobal.shared.configuration_disable_openin_file] as? String {
disable_openin_file = (str as NSString).boolValue
}
if let str = configurationManaged[NCGlobal.shared.configuration_enforce_protection] as? String {
enforce_protection = (str as NSString).boolValue
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions iOSClient/Main/NCMainTabBarController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
//

import UIKit
import SwiftUI

struct NavigationCollectionViewCommon {
var serverUrl: String
Expand Down Expand Up @@ -55,6 +56,13 @@ class NCMainTabBarController: UITabBarController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
previousIndex = selectedIndex

if NCBrandOptions.shared.enforce_protection && NCKeychain().passcode.isEmptyOrNil {
let vc = UIHostingController(rootView: SetupPasscodeView(isLockActive: .constant(false)))
vc.isModalInPresentation = true

present(vc, animated: true)
}
}

@objc func changeTheming(_ notification: NSNotification) {
Expand Down
1 change: 1 addition & 0 deletions iOSClient/NCGlobal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ class NCGlobal: NSObject {
let configuration_disable_log = "disable_log"
let configuration_disable_more_external_site = "disable_more_external_site"
let configuration_disable_openin_file = "disable_openin_file"
let configuration_enforce_protection = "enforce_protection"

// MORE NEXTCLOUD APPS
//
Expand Down
1 change: 1 addition & 0 deletions iOSClient/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import UIKit
import NextcloudKit
import WidgetKit
import SwiftEntryKit
import SwiftUI

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
Expand Down
18 changes: 14 additions & 4 deletions iOSClient/Settings/Settings/NCSettingsModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class NCSettingsModel: ObservableObject, ViewOnAppearHandling {
NCSession.shared.getSession(controller: controller)
}

var changePasscode = false

/// Initializes the view model with default values.
init(controller: NCMainTabBarController?) {
self.controller = controller
Expand Down Expand Up @@ -112,13 +114,14 @@ class NCSettingsModel: ObservableObject, ViewOnAppearHandling {
}
}

struct PasscodeView: UIViewControllerRepresentable {
struct SetupPasscodeView: UIViewControllerRepresentable {
@Binding var isLockActive: Bool
var changePasscode = false

func makeUIViewController(context: Context) -> UIViewController {
let laContext = LAContext()
var error: NSError?
if NCKeychain().passcode != nil {
if NCKeychain().passcode != nil, !changePasscode {
let passcodeViewController = TOPasscodeViewController(passcodeType: .sixDigits, allowCancel: true)
passcodeViewController.keypadButtonShowLettering = false
if NCKeychain().touchFaceID && laContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
Expand All @@ -138,6 +141,13 @@ struct PasscodeView: UIViewControllerRepresentable {
}
passcodeViewController.delegate = context.coordinator
return passcodeViewController
} else if changePasscode {
let passcodeSettingsViewController = TOPasscodeSettingsViewController()
passcodeSettingsViewController.hideOptionsButton = true
// passcodeSettingsViewController.requireCurrentPasscode = true
passcodeSettingsViewController.passcodeType = .sixDigits
passcodeSettingsViewController.delegate = context.coordinator
return passcodeSettingsViewController
} else {
let passcodeSettingsViewController = TOPasscodeSettingsViewController()
passcodeSettingsViewController.hideOptionsButton = true
Expand All @@ -157,8 +167,8 @@ struct PasscodeView: UIViewControllerRepresentable {
}

class Coordinator: NSObject, TOPasscodeSettingsViewControllerDelegate, TOPasscodeViewControllerDelegate {
var parent: PasscodeView
init(_ parent: PasscodeView) {
var parent: SetupPasscodeView
init(_ parent: SetupPasscodeView) {
self.parent = parent
}

Expand Down
91 changes: 59 additions & 32 deletions iOSClient/Settings/Settings/NCSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ struct NCSettingsView: View {
@State private var showAcknowledgements = false
/// State to control the visibility of the passcode view
@State private var showPasscode = false
/// State to contorl the visibility of the change passcode view
@State private var showChangePasscode = false
/// State to control the visibility of the Policy view
@State private var showBrowser = false
/// State to control the visibility of the Source Code view
Expand All @@ -57,7 +59,6 @@ struct NCSettingsView: View {
}
.font(.system(size: 16))
}
}, header: {
}, footer: {
Text(NSLocalizedString("_autoupload_description_", comment: ""))
})
Expand All @@ -73,49 +74,69 @@ struct NCSettingsView: View {
.font(Font.system(.body).weight(.light))
.foregroundColor(Color(NCBrandColor.shared.iconImageColor))
.frame(width: 20, height: 20)
.opacity(NCBrandOptions.shared.enforce_protection ? 0.5 : 1)
Text(model.isLockActive ? NSLocalizedString("_lock_active_", comment: "") : NSLocalizedString("_lock_not_active_", comment: ""))
}
.font(.system(size: 16))
})
.tint(Color(NCBrandColor.shared.textColor))
.sheet(isPresented: $showPasscode) {
PasscodeView(isLockActive: $model.isLockActive)
.disabled(NCBrandOptions.shared.enforce_protection)
}, header: {
Text(NSLocalizedString("_privacy_", comment: ""))
}, footer: {
if NCBrandOptions.shared.enforce_protection {
Text(NSLocalizedString("_lock_cannot_disable_mdm_", comment: ""))
}
/// Enable Touch ID
Toggle(NSLocalizedString("_enable_touch_face_id_", comment: ""), isOn: $model.enableTouchID)
.tint(Color(NCBrandColor.shared.getElement(account: model.session.account)))
.font(.system(size: 16))
.onChange(of: model.enableTouchID) { _ in
model.updateTouchIDSetting()
}
/// Lock no screen
Toggle(NSLocalizedString("_lock_protection_no_screen_", comment: ""), isOn: $model.lockScreen)
.tint(Color(NCBrandColor.shared.getElement(account: model.session.account)))
.font(.system(size: 16))
.onChange(of: model.lockScreen) { _ in
model.updateLockScreenSetting()
})

if model.isLockActive {
Section(content: {
Group {
// Change passcode
Button(action: {
showChangePasscode.toggle()
}, label: {
VStack {
Text(NSLocalizedString("_change_lock_passcode_", comment: ""))
.tint(Color(NCBrandColor.shared.textColor))
}
.font(.system(size: 16))
})
/// Enable Touch ID
Toggle(NSLocalizedString("_enable_touch_face_id_", comment: ""), isOn: $model.enableTouchID)
.onChange(of: model.enableTouchID) { _ in
model.updateTouchIDSetting()
}
/// Lock no screen
Toggle(NSLocalizedString("_lock_protection_no_screen_", comment: ""), isOn: $model.lockScreen)
.onChange(of: model.lockScreen) { _ in
model.updateLockScreenSetting()
}

/// Reset app wrong attempts
Toggle(NSLocalizedString("_reset_wrong_passcode_", comment: ""), isOn: $model.resetWrongAttempts)
.onChange(of: model.resetWrongAttempts) { _ in
model.updateResetWrongAttemptsSetting()
}
.font(.system(size: 16))

This comment was marked as resolved.

}
}, footer: {
Text(NSLocalizedString("_lock_protection_no_screen_footer_", comment: "") + "\n" + String(format: NSLocalizedString("_reset_wrong_passcode_desc_", comment: ""), NCBrandOptions.shared.resetAppPasscodeAttempts))
.font(.system(size: 12))
.lineSpacing(1)
})
.tint(Color(NCBrandColor.shared.getElement(account: model.session.account)))
}

Section {
/// Privacy screen
Toggle(NSLocalizedString("_privacy_screen_", comment: ""), isOn: $model.privacyScreen)
.tint(Color(NCBrandColor.shared.getElement(account: model.session.account)))
.font(.system(size: 16))
.onChange(of: model.privacyScreen) { _ in
model.updatePrivacyScreenSetting()
}
/// Reset app wrong attempts
Toggle(NSLocalizedString("_reset_wrong_passcode_", comment: ""), isOn: $model.resetWrongAttempts)
.tint(Color(NCBrandColor.shared.getElement(account: model.session.account)))
.font(.system(size: 16))
.onChange(of: model.resetWrongAttempts) { _ in
model.updateResetWrongAttemptsSetting()
}
}, header: {
Text(NSLocalizedString("_privacy_", comment: ""))
}, footer: {
Text(NSLocalizedString("_lock_protection_no_screen_footer_", comment: "") + "\n" + String(format: NSLocalizedString("_reset_wrong_passcode_desc_", comment: ""), NCBrandOptions.shared.resetAppPasscodeAttempts))
.font(.system(size: 12))
.lineSpacing(1)
})
}
.tint(Color(NCBrandColor.shared.getElement(account: model.session.account)))

/// Display
Section(header: Text(NSLocalizedString("_display_", comment: "")), content: {
NavigationLink(destination: LazyView {
Expand Down Expand Up @@ -266,6 +287,12 @@ struct NCSettingsView: View {
Text(model.footerApp + model.footerServer + model.footerSlogan)
})
}
.sheet(isPresented: $showPasscode) {
SetupPasscodeView(isLockActive: $model.isLockActive)
}
.sheet(isPresented: $showChangePasscode) {
SetupPasscodeView(isLockActive: $model.isLockActive, changePasscode: true)
}
.navigationBarTitle(NSLocalizedString("_settings_", comment: ""))
.defaultViewModifier(model)
}
Expand Down
Loading