Skip to content

Commit

Permalink
Elevate warnings and add lint rules, other cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Greg Stromire committed Apr 20, 2018
1 parent 2dc6509 commit b636c45
Show file tree
Hide file tree
Showing 13 changed files with 217 additions and 64 deletions.
26 changes: 24 additions & 2 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,52 @@ disabled_rules: # rule identifiers to exclude from running
- large_tuple
- line_length
- function_parameter_count
- nesting

identifier_name:
excluded:
- j # JSON identifier
- ak # Access Key
- dk # Data Key
- ef # Encrypted Field
- id # ID

opt_in_rules: # some rules are only opt-in
- force_unwrapping
- array_init
- attributes
- closure_end_indentation
- closure_spacing
- contains_over_first_not_nil
- control_statement
- empty_count
- empty_string
- explicit_init
- fatal_error_message
- file_header
- file_length
- first_where
- force_unwrapping
- implicit_return
- implicitly_unwrapped_optional
- joined_default_parameter
- literal_expression_end_indentation
- multiline_arguments
- multiline_parameters
- no_extension_access_modifier
- number_separator
- object_literal
- overridden_super_call
- override_in_extension
- pattern_matching_keywords
- prefixed_toplevel_constant
- private_action
- prohibited_super_call
- redundant_nil_coalescing
- required_enum_case
- sorted_first_last
- sorted_imports
- switch_case_on_newline
- trailing_closure
- unneeded_parentheses_in_closure_argument
- untyped_error_in_catch
- vertical_parameter_alignment_on_call
- yoda_condition
6 changes: 3 additions & 3 deletions E3db/Classes/AccessKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
//

import Foundation
import Swish
import Heimdallr
import Result
import Sodium
import Heimdallr
import Swish

// MARK: Access Key Management

Expand Down Expand Up @@ -164,7 +164,7 @@ extension Client {

// update server
self.putAccessKey(eak: eak, writerId: writerId, userId: userId, readerId: readerId, recordType: recordType) { result in
let response = EAKInfo(eak: eak, authorizerId: self.config.clientId, authorizerPublicKey: client.publicKey, signerId: self.config.clientId, signerSigningKey:client.signingKey)
let response = EAKInfo(eak: eak, authorizerId: self.config.clientId, authorizerPublicKey: client.publicKey, signerId: self.config.clientId, signerSigningKey: client.signingKey)
let accessKey = AccessKey(rawAk: ak, eakInfo: response)

// update local cache
Expand Down
8 changes: 4 additions & 4 deletions E3db/Classes/Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
//

import Foundation
import Swish
import Heimdallr
import Result
import Sodium
import Heimdallr
import Swish

#if E3DB_LOGGING && DEBUG
#if E3DB_LOGGING && DEBUG && canImport(ResponseDetective)
import ResponseDetective
#endif

Expand All @@ -28,7 +28,7 @@ public final class Client {
internal let akCache = NSCache<AkCacheKey, AccessKey>()

internal static let session: URLSession = {
#if E3DB_LOGGING && DEBUG
#if E3DB_LOGGING && DEBUG && canImport(ResponseDetective)
let configuration = URLSessionConfiguration.default
ResponseDetective.enable(inConfiguration: configuration)
return URLSession(configuration: configuration)
Expand Down
14 changes: 7 additions & 7 deletions E3db/Classes/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ public struct Config: Codable {

// MARK: Storage in Keychain / Secure Enclave

private let defaultProfileName = "com.tozny.e3db.defaultProfile"
private let defaultUserPrompt = "Unlock to load profile"
private let kDefaultProfileName = "com.tozny.e3db.defaultProfile"
private let kDefaultUserPrompt = "Unlock to load profile"

/// Access Protections for storing the Config in the device Keychain
public enum ConfigAccessControl {
Expand Down Expand Up @@ -198,8 +198,8 @@ extension Config {
/// - enclaveAccess: The Secure Enclave access control level used to protect the configuration when saved. Uses `.biometricAny` if unspecified.
/// - Returns: A fully initialized `Config` object if successful, `nil` otherwise.
public init?(loadProfile: String? = nil, userPrompt: String? = nil, enclaveAccess: ConfigAccessControl.SecureEnclave = .biometricAny) {
let profile = loadProfile ?? defaultProfileName
let prompt = userPrompt ?? defaultUserPrompt
let profile = loadProfile ?? kDefaultProfileName
let prompt = userPrompt ?? kDefaultUserPrompt
guard let identifier = Identifier(nonEmpty: profile) else { return nil }

let valet = SecureEnclaveValet.valet(with: identifier, accessControl: enclaveAccess.valetAccess)
Expand All @@ -220,7 +220,7 @@ extension Config {
/// - keychainAccess: The Keychain access control level used to protect the configuration when saved.
/// - Returns: A fully initialized `Config` object if successful, `nil` otherwise.
public init?(loadProfile: String? = nil, keychainAccess: ConfigAccessControl.Keychain) {
let profile = loadProfile ?? defaultProfileName
let profile = loadProfile ?? kDefaultProfileName
guard let identifier = Identifier(nonEmpty: profile) else { return nil }

let valet = Valet.valet(with: identifier, accessibility: keychainAccess.valetAccess)
Expand All @@ -245,7 +245,7 @@ extension Config {
/// - enclaveAccess: The Secure Enclave access control level used to protect the configuration. Uses `.biometricAny` if unspecified.
/// - Returns: A boolean value indicating whether the config object was successfully saved.
public func save(profile: String? = nil, enclaveAccess: ConfigAccessControl.SecureEnclave = .biometricAny) -> Bool {
let userProfile = profile ?? defaultProfileName
let userProfile = profile ?? kDefaultProfileName
guard let identifier = Identifier(nonEmpty: userProfile) else { return false }

let valet = SecureEnclaveValet.valet(with: identifier, accessControl: enclaveAccess.valetAccess)
Expand All @@ -265,7 +265,7 @@ extension Config {
/// - keychainAccess: The Keychain access control level to protect the configuration.
/// - Returns: A boolean value indicating whether the config object was successfully saved.
public func save(profile: String? = nil, keychainAccess: ConfigAccessControl.Keychain) -> Bool {
let userProfile = profile ?? defaultProfileName
let userProfile = profile ?? kDefaultProfileName
guard let identifier = Identifier(nonEmpty: userProfile) else { return false }

let valet = Valet.valet(with: identifier, accessibility: keychainAccess.valetAccess)
Expand Down
9 changes: 4 additions & 5 deletions E3db/Classes/Document.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
//

import Foundation
import Swish
import Result
import Sodium
import Swish

// MARK: Offline Crypto Operations

Expand Down Expand Up @@ -34,7 +33,7 @@ public struct EncryptedDocument: Encodable {
/// The ciphertext after it has been encrypted,
/// the keys remain unencrypted
public let encryptedData: CipherData

/// A cryptographic signature of the `clientMeta`
/// and the cleartext data before it was encrypted
public let recordSignature: String
Expand All @@ -51,7 +50,7 @@ extension EncryptedDocument: Signable {
return [
CodingKeys.clientMeta.rawValue: AnySignable(clientMeta),
CodingKeys.encryptedData.rawValue: AnySignable(encryptedData),
CodingKeys.recordSignature.rawValue: AnySignable(recordSignature)
CodingKeys.recordSignature.rawValue: AnySignable(recordSignature)
].serialized()
}
}
Expand Down Expand Up @@ -196,7 +195,7 @@ extension Client {
}
let meta = encryptedDoc.clientMeta
let localAk = try getLocalAk(clientId: eakInfo.authorizerId, recordType: meta.type, eakInfo: eakInfo)
let decrypted = try Crypto.decrypt(cipherData: encryptedDoc.encryptedData, ak: localAk)
let decrypted = try Crypto.decrypt(cipherData: encryptedDoc.encryptedData, ak: localAk)
let docInfo = DocInfo(meta: meta, data: decrypted)
let signed = SignedDocument(document: docInfo, signature: encryptedDoc.recordSignature)
guard try verify(signed: signed, pubSigKey: sigKey) else {
Expand Down
12 changes: 10 additions & 2 deletions E3db/Classes/Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
//

import Foundation
import Swish
import Result
import Swish

extension Formatter {
static let iso8601: DateFormatter = {
Expand Down Expand Up @@ -33,13 +33,21 @@ extension String {
extension URLRequest {
mutating func asJsonRequest<T: Encodable>(_ method: RequestMethod, payload: T) -> URLRequest {
self.httpMethod = method.rawValue
self.httpBody = try? staticJsonEncoder.encode(payload)
self.httpBody = try? kStaticJsonEncoder.encode(payload)
self.setValue("application/json", forHTTPHeaderField: "Accept")
self.setValue("application/json", forHTTPHeaderField: "Content-Type")
return self
}
}

// Extends Swish.Request to override their `parse`
// method to replace with custom json decoder
extension E3dbRequest where ResponseObject: Decodable {
func parse(_ data: Data) throws -> ResponseObject {
return try kStaticJsonDecoder.decode(ResponseObject.self, from: data)
}
}

extension URL {
static func / (lhs: URL, rhs: String) -> URL {
return lhs.appendingPathComponent(rhs)
Expand Down
3 changes: 1 addition & 2 deletions E3db/Classes/Query.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import Foundation
import Swish
import Result

/// Data type to specify filters for querying records
public struct QueryParams: Encodable {
Expand Down Expand Up @@ -165,7 +164,7 @@ extension Client {
private func decryptSearchRecord(_ searchRecord: SearchRecord) -> E3dbResult<Record> {
guard let cipherData = searchRecord.data,
let eakInfo = searchRecord.eakInfo else {
return Result(value: Record(meta: searchRecord.meta, data: Cleartext()))
return .success(Record(meta: searchRecord.meta, data: Cleartext()))
}

return decryptEak(eakInfo: eakInfo, clientPrivateKey: self.config.privateKey)
Expand Down
14 changes: 7 additions & 7 deletions E3db/Classes/Record.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
//

import Foundation
import Swish
import Result
import Swish

/// A type that holds arbitrary metadata for a record in cleartext
public typealias PlainMeta = [String: String]
Expand Down Expand Up @@ -187,8 +187,8 @@ extension Client {

let cipher: CipherData
switch encrypt(data, ak: ak) {
case .success(let c):
cipher = c
case .success(let thisCipher):
cipher = thisCipher
case .failure(let err):
return completion(Result(error: err))
}
Expand Down Expand Up @@ -282,8 +282,8 @@ extension Client {
public func read(recordId: UUID, fields: [String]? = nil, completion: @escaping E3dbCompletion<Record>) {
readRaw(recordId: recordId, fields: fields) { result in
switch result {
case .success(let r):
self.decryptRecord(record: r, completion: completion)
case .success(let record):
self.decryptRecord(record: record, completion: completion)
case .failure(let err):
completion(Result(error: err))
}
Expand Down Expand Up @@ -311,8 +311,8 @@ extension Client {
private func update(_ recordId: UUID, version: String, metaReq: ClientMeta, data: RecordData, ak: RawAccessKey, completion: @escaping E3dbCompletion<Record>) {
let cipher: CipherData
switch self.encrypt(data, ak: ak) {
case .success(let c):
cipher = c
case .success(let thisCipher):
cipher = thisCipher
case .failure(let err):
return completion(Result(error: err))
}
Expand Down
13 changes: 6 additions & 7 deletions E3db/Classes/Register.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
//

import Foundation
import Swish
import Result
import Sodium
import Swish

struct ClientRequest: Encodable {
let name: String
Expand Down Expand Up @@ -120,17 +119,17 @@ extension Client {
static func register(token: String, clientName: String, apiUrl: String? = nil, scheduler: @escaping Scheduler, completion: @escaping E3dbCompletion<Config>) {
// ensure api url is valid
guard let url = URL(string: apiUrl ?? Api.defaultUrl) else {
return completion(Result(error: .configError("Invalid apiUrl: \(apiUrl ?? "")")))
return completion(.failure(.configError("Invalid apiUrl: \(apiUrl ?? "")")))
}

// create encryption key pair
guard let keyPair = Client.generateKeyPair() else {
return completion(Result(error: .cryptoError("Failed to create encryption key pair")))
return completion(.failure(.cryptoError("Failed to create encryption key pair")))
}

// create signing key pair
guard let signingKeyPair = Client.generateSigningKeyPair() else {
return completion(Result(error: .cryptoError("Failed to create signing key pair")))
return completion(.failure(.cryptoError("Failed to create signing key pair")))
}

let api = Api(baseUrl: url)
Expand All @@ -155,7 +154,7 @@ extension Client {
publicSigKey: signingKeyPair.publicKey,
privateSigKey: signingKeyPair.secretKey
)
}
}
completion(resp)
}
}
Expand Down Expand Up @@ -198,7 +197,7 @@ extension Client {
public static func register(token: String, clientName: String, publicKey: String, signingKey: String, apiUrl: String? = nil, completion: @escaping E3dbCompletion<ClientCredentials>) {
// ensure api url is valid
guard let url = URL(string: apiUrl ?? Api.defaultUrl) else {
return completion(Result(error: .configError("Invalid apiUrl: \(apiUrl ?? "")")))
return completion(.failure(.configError("Invalid apiUrl: \(apiUrl ?? "")")))
}

let api = Api(baseUrl: url)
Expand Down
7 changes: 3 additions & 4 deletions E3db/Classes/Share.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import Foundation
import Swish
import Result

// MARK: Sharing

Expand Down Expand Up @@ -94,7 +93,7 @@ extension Client {
let req = ShareRequest(api: self.api, policy: .allow, clientId: clientId, readerId: readerId, contentType: type)
self.authedClient.performDefault(req, completion: completion)
case .failure(let err):
completion(Result(error: err))
completion(.failure(err))
}
}
}
Expand All @@ -112,7 +111,7 @@ extension Client {
case .success(let ak):
self.addSharePolicy(ak: ak.rawAk, type: type, clientId: clientId, readerId: readerId, completion: completion)
case .failure:
completion(Result(error: .apiError(code: 404, message: "No applicable records exist to share")))
completion(.failure(.apiError(code: 404, message: "No applicable records exist to share")))
}
}
}
Expand All @@ -131,7 +130,7 @@ extension Client {
let req = ShareRequest(api: self.api, policy: .deny, clientId: clientId, readerId: readerId, contentType: type)
self.authedClient.performDefault(req, completion: completion)
case .failure(let err):
completion(Result(error: err))
completion(.failure(err))
}
}
}
Expand Down
Loading

0 comments on commit b636c45

Please sign in to comment.