Skip to content
This repository has been archived by the owner on Jan 5, 2024. It is now read-only.

Commit

Permalink
Merge pull request #63 from fadyyecob/feature/decryption-single-property
Browse files Browse the repository at this point in the history
Moved to a single property for decryption
  • Loading branch information
albertodebortoli authored Dec 15, 2021
2 parents ae7b25e + 89aa645 commit a35213f
Show file tree
Hide file tree
Showing 14 changed files with 106 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ extension GeneratedTweakAccessor {
static let displayGreenView = "display_green_view"
static let displayRedView = "display_red_view"
static let displayYellowView = "display_yellow_view"
static let encryptedAnswerToTheUniverse = "encrypted_answer_to_the_universe"
static let greetOnAppDidBecomeActive = "greet_on_app_did_become_active"
static let labelText = "label_text"
static let redViewAlphaComponent = "red_view_alpha_component"
Expand Down
5 changes: 5 additions & 0 deletions Example/JustTweak/Accessors/GeneratedTweakAccessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ class GeneratedTweakAccessor {
set { tweakManager.set(newValue, feature: Features.uiCustomization, variable: Variables.displayYellowView) }
}

var definitiveAnswerEncrypted: String {
get { tweakManager.tweakWith(feature: Features.general, variable: Variables.encryptedAnswerToTheUniverse)?.stringValue ?? "" }
set { tweakManager.set(newValue, feature: Features.general, variable: Variables.encryptedAnswerToTheUniverse) }
}

var isTapGestureToChangeColorEnabled: Bool {
get { tweakManager.tweakWith(feature: Features.general, variable: Variables.tapToChangeColorEnabled)?.boolValue ?? false }
set { tweakManager.set(newValue, feature: Features.general, variable: Variables.tapToChangeColorEnabled) }
Expand Down
5 changes: 5 additions & 0 deletions Example/JustTweak/Code/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

let tweakManager = TweakManager(tweakProviders: tweakProviders)
tweakManager.useCache = true

tweakManager.decryptionClosure = { tweak in
String((tweak.value.stringValue ?? "").reversed())
}

return tweakManager
}
}
14 changes: 14 additions & 0 deletions Example/JustTweak/Code/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ class ViewController: UIViewController {
print("Tweak changed: \(tweak)")
self?.updateView()
}
addEncryptedMeaningOfLifeTapGesture()
}

private func addEncryptedMeaningOfLifeTapGesture() {
let tapGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(showEncryptedMeaningOfLife))
view.addGestureRecognizer(tapGestureRecognizer)
}

internal func updateView() {
Expand Down Expand Up @@ -60,6 +66,14 @@ class ViewController: UIViewController {
present(alertController, animated: true, completion: nil)
}

@objc func showEncryptedMeaningOfLife() {
let alertController = UIAlertController(title: "Encrypted Meaning of Life",
message: String(describing: tweakAccessor.definitiveAnswerEncrypted),
preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
present(alertController, animated: true)
}

@objc internal func changeViewColor() {
func randomColorValue() -> CGFloat {
return CGFloat(arc4random() % 255) / 255.0
Expand Down
8 changes: 8 additions & 0 deletions Example/JustTweak/TweakProviders/LocalTweaks_example.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@
}
},
"general": {
"encrypted_answer_to_the_universe": {
"Title": "Encrypted definitive answer",
"Description": "Encrypted answer to the Ultimate Question of Life, the Universe, and Everything",
"Group": "General",
"Value": "24 ton yletinifeD",
"GeneratedPropertyName": "definitiveAnswerEncrypted",
"Encrypted": true
},
"answer_to_the_universe": {
"Title": "Definitive answer",
"Description": "Answer to the Ultimate Question of Life, the Universe, and Everything",
Expand Down
20 changes: 7 additions & 13 deletions Example/Tests/Core/TweakManagerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,25 +90,19 @@ class TweakManagerTests: XCTestCase {
}

func testTweakManagerDecryption() throws {
var mutableTweakProvider = try XCTUnwrap(tweakManager.mutableTweakProvider)
let feature = "password"
let variable = "variable"
let url = try XCTUnwrap(Bundle.main.url(forResource: "LocalTweaks_example", withExtension: "json"))

let encodedString = try XCTUnwrap("my secret password".data(using: .utf8)?.base64EncodedString())
tweakManager.tweakProviders.append(LocalTweakProvider(jsonURL: url))

mutableTweakProvider.set(encodedString, feature: feature, variable: variable)
mutableTweakProvider.decryptionClosure = { tweak in
let data = Data(base64Encoded: tweak.stringValue ?? "").map {
String(data: $0, encoding: .utf8)
} ?? ""

return data ?? ""
tweakManager.decryptionClosure = { tweak in
String((tweak.value.stringValue ?? "").reversed())
}

let feature = "general"
let variable = "encrypted_answer_to_the_universe"
let tweak = tweakManager.tweakWith(feature: feature, variable: variable)

XCTAssertEqual("bXkgc2VjcmV0IHBhc3N3b3Jk", tweak?.stringValue)
XCTAssertEqual("my secret password", tweak?.decryptedValue?.stringValue)
XCTAssertEqual("Definitely not 42", tweak?.stringValue)
}

func testSetTweakManagerDecryptionClosureThenDecryptionClosureIsSetForProviders() throws {
Expand Down
11 changes: 3 additions & 8 deletions JustTweak/Classes/DTOs/Tweak.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ public struct Tweak {
public let variable: String

public let value: TweakValue
public let decryptedValue: TweakValue?

public let title: String?
public let desc: String?
Expand Down Expand Up @@ -41,16 +40,14 @@ public struct Tweak {
title: String? = nil,
description: String? = nil,
group: String? = nil,
source: String? = nil,
decryptedValue: TweakValue? = nil) {
source: String? = nil) {
self.feature = feature
self.variable = variable
self.value = value
self.title = title
self.desc = description
self.group = group
self.source = source
self.decryptedValue = decryptedValue
}

func mutatedCopy(feature: String? = nil,
Expand All @@ -59,16 +56,14 @@ public struct Tweak {
title: String? = nil,
description: String? = nil,
group: String? = nil,
source: String? = nil,
decryptedValue: TweakValue? = nil) -> Self {
source: String? = nil) -> Self {
Self(feature: feature ?? self.feature,
variable: variable ?? self.variable,
value: value ?? self.value,
title: title ?? self.title,
description: description ?? self.desc,
group: group ?? self.group,
source: source ?? self.source,
decryptedValue: decryptedValue ?? self.decryptedValue)
source: source ?? self.source)
}
}

Expand Down
18 changes: 8 additions & 10 deletions JustTweak/Classes/TweakManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,17 @@ extension TweakManager: MutableTweakProvider {
if let tweak = tweakProvider.tweakWith(feature: feature, variable: variable) {
logClosure?("Tweak '\(tweak)' found in configuration \(tweakProvider))", .verbose)

let tweakWithoutDecryptedValue = Tweak(feature: feature,
variable: variable,
value: tweak.value,
title: tweak.title,
group: tweak.group,
source: "\(type(of: tweakProvider))")

let decryptedValue = tweakProvider.decryptionClosure?(tweakWithoutDecryptedValue)
result = tweakWithoutDecryptedValue.mutatedCopy(decryptedValue: decryptedValue)
result = Tweak(feature: feature,
variable: variable,
value: tweak.value,
title: tweak.title,
group: tweak.group,
source: "\(type(of: tweakProvider))")
break
}
else {
logClosure?("Tweak with identifier '\(variable)' NOT found in configuration \(tweakProvider))", .verbose)
let logMessage = "Tweak with identifier '\(variable)' in configuration \(tweakProvider)) could NOT be found or has an invalid configuration"
logClosure?(logMessage, .verbose)
}
}
if let result = result {
Expand Down
15 changes: 13 additions & 2 deletions JustTweak/Classes/TweakProviders/LocalTweakProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Foundation
final public class LocalTweakProvider {

private enum EncodingKeys : String {
case Title, Description, Group, Value
case Title, Description, Group, Value, Encrypted
}

private let configurationFile: [String : [String : [String : AnyObject]]]
Expand Down Expand Up @@ -66,6 +66,7 @@ extension LocalTweakProvider: TweakProvider {
let description = entry[EncodingKeys.Description.rawValue] as? String
let group = entry[EncodingKeys.Group.rawValue] as? String
let value = tweakValueFromJSONObject(entry[EncodingKeys.Value.rawValue])
let isEncrypted = (entry[EncodingKeys.Encrypted.rawValue] as? Bool) ?? false

let tweak = Tweak(feature: feature,
variable: variable,
Expand All @@ -74,6 +75,16 @@ extension LocalTweakProvider: TweakProvider {
description: description,
group: group)

return tweak.mutatedCopy(decryptedValue: decryptionClosure?(tweak))
if isEncrypted {
guard let decryptionClosure = decryptionClosure else {
// The configuration is not correct, it's encrypted, but there's no way to decrypt
// So return nil to indicate an error. Should be changed to a throwing function in the future
return nil
}

return tweak.mutatedCopy(value: decryptionClosure(tweak))
} else {
return tweak
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,13 @@ extension UserDefaultsTweakProvider: TweakProvider {
let userDefaultsValue = userDefaults.object(forKey: userDefaultsKey) as AnyObject?
guard let value = updateUserDefaults(userDefaultsValue) else { return nil }

let tweak = Tweak(
return Tweak(
feature: feature,
variable: variable,
value: value,
title: nil,
group: nil
)

return tweak.mutatedCopy(decryptedValue: decryptionClosure?(tweak))
}
}

Expand Down
10 changes: 1 addition & 9 deletions JustTweak/Classes/UI/TweakManager+Presentation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,8 @@ extension TweakManager {
description: jsonTweak.desc,
group: jsonTweak.group)

let decryptedTweakValue = decryptionClosure?(aggregatedTweak)

let key = "\(feature)-\(variable)"
tweaks[key] = Tweak(feature: feature,
variable: variable,
value: tweak.value,
title: jsonTweak.title,
description: jsonTweak.desc,
group: jsonTweak.group,
decryptedValue: decryptedTweakValue)
tweaks[key] = aggregatedTweak
}
}
}
Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,31 @@ JustTweak comes with three tweak providers out-of-the-box:
In addition, JustTweak defines `TweakProvider` and `MutableTweakProvider` protocols you can implement to create your own tweak provider to fit your needs. In the example project you can find some examples which you can use as a starting point.


### Encryption or pre-processing (Advanced)

JustTweak offers the ability to add a `decryptionClosure` to a `TweakProvider`. This closure takes the `Tweak` as input and returns a `TweakValue` as output. The closure allows you to do some preprocessing on your tweak which can e.g. be used to decrypt values. This can be used if you have an encrypted value in your tweaks JSON file as can be seen below:

```json
"encrypted_answer_to_the_universe": {
"Title": "Encrypted definitive answer",
"Description": "Encrypted answer to the Ultimate Question of Life, the Universe, and Everything",
"Group": "General",
"Value": "24 ton yletinifeD",
"GeneratedPropertyName": "definitiveAnswerEncrypted",
"Encrypted": true
}
```

Note that you have to specify if the value is encrypted in your JSON file (with the `Encrypted` property) for the decryption closure to process the value. The decryption closure for the JSON above can be specified as follows:

```swift
tweakProvider.decryptionClosure = { tweak in
// decrypt `tweak.value` with your cypher of choice and return the decrypted value
}
```

In this way, the tweak fetched from the tweak provider will have the decrypted value.

## License

JustTweak is available under the Apache 2.0 license. See the LICENSE file for more info.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@
}
},
"general": {
"encrypted_answer_to_the_universe": {
"Title": "Encrypted definitive answer",
"Description": "Encrypted answer to the Ultimate Question of Life, the Universe, and Everything",
"Group": "General",
"Value": "24 ton yletinifeD",
"GeneratedPropertyName": "definitiveAnswerEncrypted",
"Encrypted": true
},
"answer_to_the_universe": {
"Title": "Definitive answer",
"Description": "Answer to the Ultimate Question of Life, the Universe, and Everything",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ class TweakLoaderTests: XCTestCase {
group: "General",
valueType: "Int",
propertyName: "definitiveAnswer"),
Tweak(feature: "general",
variable: "encrypted_answer_to_the_universe",
title: "Encrypted definitive answer",
description: "Encrypted answer to the Ultimate Question of Life, the Universe, and Everything",
group: "General",
valueType: "String",
propertyName: "definitiveAnswerEncrypted"),
Tweak(feature: "general",
variable: "greet_on_app_did_become_active",
title: "Greet on app launch",
Expand Down

0 comments on commit a35213f

Please sign in to comment.