Skip to content

Commit

Permalink
issue #714 sort recipient keys depending on expire date
Browse files Browse the repository at this point in the history
  • Loading branch information
sosnovsky committed Oct 26, 2021
1 parent 8776b63 commit 74a0cf6
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,21 @@ struct RecipientWithSortedPubKeys {
let name: String?
/// last time an email was sent to this contact, update when email is sent
let lastUsed: Date?
/// public keys
var pubKeys: [PubKey]
/// sorted public keys
var pubKeys: [PubKey] {
get { sortedPubKeys }
set { _pubKeys = newValue }
}
/// non-sorted public keys
private var _pubKeys: [PubKey]
}

extension RecipientWithSortedPubKeys {
init(_ recipientObject: RecipientObject, keyDetails: [KeyDetails] = []) {
self.email = recipientObject.email
self.name = recipientObject.name.nilIfEmpty
self.lastUsed = recipientObject.lastUsed
self.pubKeys = keyDetails.map(PubKey.init)
self._pubKeys = keyDetails.map(PubKey.init)
}
}

Expand All @@ -32,7 +37,7 @@ extension RecipientWithSortedPubKeys {
self.email = email
self.name = keyDetails.first?.users.first ?? email
self.lastUsed = nil
self.pubKeys = keyDetails.map(PubKey.init)
self._pubKeys = keyDetails.map(PubKey.init)
}
}

Expand All @@ -42,6 +47,20 @@ extension RecipientWithSortedPubKeys {
}

var keyState: PubKeyState { pubKeys.first?.keyState ?? .empty }

private var sortedPubKeys: [PubKey] {
_pubKeys
.sorted(by: {
guard !$0.isRevoked else { return false }

guard let expire1 = $0.expiresOn,
let expire2 = $1.expiresOn,
!$1.isRevoked
else { return true }

return expire1 > expire2
})
}
}

extension RecipientWithSortedPubKeys: Equatable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class RecipientTests: XCTestCase {

func testRecipientWithRevokedKey() {
let keyDetails = generateKey(expiration: nil, revoked: true)
let recipient = RecipientWithPubKeys(email: "[email protected]", keyDetails: [keyDetails])
let recipient = RecipientWithSortedPubKeys(email: "[email protected]", keyDetails: [keyDetails])

XCTAssertEqual(recipient.keyState, .revoked)
}
Expand All @@ -23,37 +23,60 @@ class RecipientTests: XCTestCase {
let expiration = Date().timeIntervalSince1970 - 60 * 60
let keyDetails = generateKey(expiration: Int(expiration), revoked: false)

let recipient = RecipientWithPubKeys(email: "[email protected]", keyDetails: [keyDetails])
let recipient = RecipientWithSortedPubKeys(email: "[email protected]", keyDetails: [keyDetails])
XCTAssertEqual(recipient.keyState, .expired)
}

func testRecipientWithValidKey() {
let expiration = Date().timeIntervalSince1970 + 60 * 60
let keyDetails = generateKey(expiration: Int(expiration), revoked: false)
let recipient = RecipientWithPubKeys(email: "[email protected]", keyDetails: [keyDetails])
let recipient = RecipientWithSortedPubKeys(email: "[email protected]", keyDetails: [keyDetails])
XCTAssertEqual(recipient.keyState, .active)

let keyDetails2 = generateKey(expiration: nil, revoked: false)
let recipient2 = RecipientWithPubKeys(email: "[email protected]", keyDetails: [keyDetails2])
let recipient2 = RecipientWithSortedPubKeys(email: "[email protected]", keyDetails: [keyDetails2])
XCTAssertEqual(recipient2.keyState, .active)
}

func testRecipientWithoutPubKey() {
let recipient = RecipientWithPubKeys(email: "[email protected]", keyDetails: [])
let recipient = RecipientWithSortedPubKeys(email: "[email protected]", keyDetails: [])
XCTAssertEqual(recipient.keyState, .empty)
}

func testRecipientKeysOrder() {
let revokedKey = generateKey(expiration: Int(Date().timeIntervalSince1970 + 60 * 60), revoked: true)

let activeKey1 = generateKey(expiration: Int(Date().timeIntervalSince1970 + 60 * 60))
let activeKey2 = generateKey(expiration: Int(Date().timeIntervalSince1970 + 48 * 60 * 60))
let activeKey3 = generateKey(expiration: Int(Date().timeIntervalSince1970 + 24 * 60 * 60))

let nonExpiringKey = generateKey(expiration: nil)
let expiredKey = generateKey(expiration: Int(Date().timeIntervalSince1970 - 60 * 60))
let oldExpiredKey = generateKey(expiration: Int(Date().timeIntervalSince1970 - 24 * 60 * 60))

let keyDetails = [revokedKey, oldExpiredKey, activeKey1, expiredKey, activeKey2, nonExpiringKey, activeKey3]
let recipient = RecipientWithSortedPubKeys(email: "[email protected]",
keyDetails: keyDetails)

XCTAssertEqual(recipient.pubKeys[0].fingerprint, nonExpiringKey.primaryFingerprint)
XCTAssertEqual(recipient.pubKeys[1].fingerprint, activeKey2.primaryFingerprint)
XCTAssertEqual(recipient.pubKeys[2].fingerprint, activeKey3.primaryFingerprint)
XCTAssertEqual(recipient.pubKeys[3].fingerprint, activeKey1.primaryFingerprint)
XCTAssertEqual(recipient.pubKeys[4].fingerprint, expiredKey.primaryFingerprint)
XCTAssertEqual(recipient.pubKeys[5].fingerprint, oldExpiredKey.primaryFingerprint)
XCTAssertEqual(recipient.pubKeys[6].fingerprint, revokedKey.primaryFingerprint)
}
}

extension RecipientTests {
private func generateKey(expiration: Int?, revoked: Bool) -> KeyDetails {
private func generateKey(expiration: Int?, revoked: Bool = false) -> KeyDetails {
KeyDetails(
public: "Public part",
private: nil,
isFullyDecrypted: false,
isFullyEncrypted: false,
ids: [
KeyId(longid: "longid", fingerprint: "fingerprint")
],
ids: [KeyId(longid: randomString(length: 16),
fingerprint: randomString(length: 16))],
created: 1,
lastModified: nil,
expiration: expiration,
Expand All @@ -62,4 +85,9 @@ extension RecipientTests {
revoked: revoked
)
}

private func randomString(length: Int) -> String {
let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
return String((0..<length).map { _ in letters.randomElement()! })
}
}
4 changes: 2 additions & 2 deletions FlowCryptAppTests/Mocks/ContactsServiceMock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ final class ContactsServiceMock: ContactsServiceType {
retrievePubKeysResult(email)
}

var searchContactResult: Result<RecipientWithPubKeys, Error>!
func searchContact(with email: String) async throws -> RecipientWithPubKeys {
var searchContactResult: Result<RecipientWithSortedPubKeys, Error>!
func searchContact(with email: String) async throws -> RecipientWithSortedPubKeys {
switch searchContactResult {
case .success(let result):
return result
Expand Down

0 comments on commit 74a0cf6

Please sign in to comment.