From 1443651ce9e6c6dfc0e18c5f506aede7509121ad Mon Sep 17 00:00:00 2001 From: Egzon Arifi Date: Sat, 9 Nov 2024 09:25:43 +0100 Subject: [PATCH 1/5] Introduce PersonNameComponents for Google, Facebook, LinkedIn sign in --- Sources/Apple/AppleAuthenticator+Models.swift | 8 +--- .../Core/PersonNameComponents+Extension.swift | 41 +++++++++++++++++++ .../FacebookAuthenticator+Models.swift | 15 +++---- Sources/Facebook/FacebookAuthenticator.swift | 2 +- .../Google/GoogleAuthenticator+Models.swift | 8 +++- Sources/Google/GoogleAuthenticator.swift | 5 ++- .../LinkedInAuthenticator+Models.swift | 7 +++- Sources/LinkedIn/LinkedInAuthenticator.swift | 3 +- 8 files changed, 67 insertions(+), 22 deletions(-) create mode 100644 Sources/Core/PersonNameComponents+Extension.swift diff --git a/Sources/Apple/AppleAuthenticator+Models.swift b/Sources/Apple/AppleAuthenticator+Models.swift index 935eb49..d09335d 100644 --- a/Sources/Apple/AppleAuthenticator+Models.swift +++ b/Sources/Apple/AppleAuthenticator+Models.swift @@ -25,13 +25,7 @@ public extension AppleAuthenticator { /// User full name represented by `givenName` and `familyName` public var name: String? { - guard let givenName = nameComponents?.givenName else { - return nameComponents?.familyName - } - guard let familyName = nameComponents?.familyName else { - return givenName - } - return "\(givenName) \(familyName)" + nameComponents?.name } } diff --git a/Sources/Core/PersonNameComponents+Extension.swift b/Sources/Core/PersonNameComponents+Extension.swift new file mode 100644 index 0000000..c07e459 --- /dev/null +++ b/Sources/Core/PersonNameComponents+Extension.swift @@ -0,0 +1,41 @@ +// +// PersonNameComponents+Extension.swift +// PovioKitAuth +// +// Created by Egzon Arifi on 09/11/2024. +// + +import AuthenticationServices +import Foundation + +public extension PersonNameComponents { + var name: String? { + guard let givenName = givenName else { + return familyName + } + guard let familyName = familyName else { + return givenName + } + return "\(givenName) \(familyName)" + } +} + +public extension PersonNameComponents { + static func create(namePrefix: String? = .none, + middleName: String? = .none, + givenName: String? = .none, + familyName: String? = .none, + nameSuffix: String? = .none, + nickname: String? = .none, + phoneticRepresentation: PersonNameComponents? = .none) -> PersonNameComponents { + var components = PersonNameComponents() + components.namePrefix = namePrefix + components.familyName = familyName + components.middleName = middleName + components.givenName = givenName + components.nameSuffix = nameSuffix + components.nickname = nickname + components.phoneticRepresentation = phoneticRepresentation + return components + } +} diff --git a/Sources/Facebook/FacebookAuthenticator+Models.swift b/Sources/Facebook/FacebookAuthenticator+Models.swift index ca060d2..9996584 100644 --- a/Sources/Facebook/FacebookAuthenticator+Models.swift +++ b/Sources/Facebook/FacebookAuthenticator+Models.swift @@ -12,9 +12,14 @@ public extension FacebookAuthenticator { struct Response { public let userId: String public let token: String - public let name: String? + public let nameComponents: PersonNameComponents? public let email: String? public let expiresAt: Date + + /// User full name represented by `givenName` and `familyName` + public var name: String? { + nameComponents?.name + } } struct GraphResponse: Decodable { @@ -36,11 +41,3 @@ public extension FacebookAuthenticator { } } } - -public extension FacebookAuthenticator.GraphResponse { - var displayName: String { - [firstName, lastName] - .compactMap { $0 } - .joined(separator: " ") - } -} diff --git a/Sources/Facebook/FacebookAuthenticator.swift b/Sources/Facebook/FacebookAuthenticator.swift index 90bd25a..de4c1b2 100644 --- a/Sources/Facebook/FacebookAuthenticator.swift +++ b/Sources/Facebook/FacebookAuthenticator.swift @@ -110,7 +110,7 @@ private extension FacebookAuthenticator { let authResponse = Response( userId: object.id, token: token.tokenString, - name: object.displayName, + nameComponents: .create(givenName: object.firstName, familyName: object.lastName), email: object.email, expiresAt: token.expirationDate ) diff --git a/Sources/Google/GoogleAuthenticator+Models.swift b/Sources/Google/GoogleAuthenticator+Models.swift index a0906f6..7f08a41 100644 --- a/Sources/Google/GoogleAuthenticator+Models.swift +++ b/Sources/Google/GoogleAuthenticator+Models.swift @@ -7,6 +7,7 @@ // import Foundation +import PovioKitAuthCore public extension GoogleAuthenticator { struct Response { @@ -14,8 +15,13 @@ public extension GoogleAuthenticator { public let idToken: String? public let accessToken: String public let refreshToken: String - public let name: String? + public let nameComponents: PersonNameComponents? public let email: String? public let expiresAt: Date? + + /// User full name represented by `givenName` and `familyName` + public var name: String? { + nameComponents?.name + } } } diff --git a/Sources/Google/GoogleAuthenticator.swift b/Sources/Google/GoogleAuthenticator.swift index 6e7f88d..25db965 100644 --- a/Sources/Google/GoogleAuthenticator.swift +++ b/Sources/Google/GoogleAuthenticator.swift @@ -107,7 +107,10 @@ private extension GIDGoogleUser { idToken: idToken?.tokenString, accessToken: accessToken.tokenString, refreshToken: refreshToken.tokenString, - name: profile?.name, + nameComponents: PersonNameComponents.create( + givenName: profile?.givenName, + familyName: profile?.familyName + ), email: profile?.email, expiresAt: accessToken.expirationDate ) diff --git a/Sources/LinkedIn/LinkedInAuthenticator+Models.swift b/Sources/LinkedIn/LinkedInAuthenticator+Models.swift index 73441cf..e835783 100644 --- a/Sources/LinkedIn/LinkedInAuthenticator+Models.swift +++ b/Sources/LinkedIn/LinkedInAuthenticator+Models.swift @@ -86,8 +86,13 @@ public extension LinkedInAuthenticator { struct Response { public let userId: String public let token: String - public let name: String + public let nameComponents: PersonNameComponents public let email: String public let expiresAt: Date + + /// User full name represented by `givenName` and `familyName` + public var name: String? { + nameComponents.name + } } } diff --git a/Sources/LinkedIn/LinkedInAuthenticator.swift b/Sources/LinkedIn/LinkedInAuthenticator.swift index bc91c4d..70afef5 100644 --- a/Sources/LinkedIn/LinkedInAuthenticator.swift +++ b/Sources/LinkedIn/LinkedInAuthenticator.swift @@ -39,11 +39,10 @@ extension LinkedInAuthenticator: Authenticator { storage.set(true, forKey: storageIsAuthenticatedKey) - let name = "\(profileResponse.localizedFirstName) \(profileResponse.localizedLastName)" return Response( userId: profileResponse.id, token: authResponse.accessToken, - name: name, + nameComponents: .create(givenName: profileResponse.localizedFirstName, familyName: profileResponse.localizedLastName), email: emailResponse.emailAddress, expiresAt: authResponse.expiresIn ) From 4cf6b2fd929957236a5d67a5d105f4467029b6a4 Mon Sep 17 00:00:00 2001 From: Egzon Arifi Date: Wed, 13 Nov 2024 12:20:36 +0100 Subject: [PATCH 2/5] indentation --- .../Core/PersonNameComponents+Extension.swift | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Sources/Core/PersonNameComponents+Extension.swift b/Sources/Core/PersonNameComponents+Extension.swift index c07e459..b0a0787 100644 --- a/Sources/Core/PersonNameComponents+Extension.swift +++ b/Sources/Core/PersonNameComponents+Extension.swift @@ -21,13 +21,15 @@ public extension PersonNameComponents { } public extension PersonNameComponents { - static func create(namePrefix: String? = .none, - middleName: String? = .none, - givenName: String? = .none, - familyName: String? = .none, - nameSuffix: String? = .none, - nickname: String? = .none, - phoneticRepresentation: PersonNameComponents? = .none) -> PersonNameComponents { + static func create( + namePrefix: String? = .none, + middleName: String? = .none, + givenName: String? = .none, + familyName: String? = .none, + nameSuffix: String? = .none, + nickname: String? = .none, + phoneticRepresentation: PersonNameComponents? = .none + ) -> PersonNameComponents { var components = PersonNameComponents() components.namePrefix = namePrefix components.familyName = familyName From 987e535269cfa3bcecc3e32cc1fbf92db9e3213b Mon Sep 17 00:00:00 2001 From: Yll Fejziu Date: Fri, 15 Nov 2024 13:13:28 +0100 Subject: [PATCH 3/5] Minor refactor --- .../Core/PersonNameComponents+Extension.swift | 37 +++++++++---------- Sources/Facebook/FacebookAuthenticator.swift | 5 ++- Sources/Google/GoogleAuthenticator.swift | 2 +- Sources/LinkedIn/LinkedInAuthenticator.swift | 5 ++- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/Sources/Core/PersonNameComponents+Extension.swift b/Sources/Core/PersonNameComponents+Extension.swift index b0a0787..ec508e5 100644 --- a/Sources/Core/PersonNameComponents+Extension.swift +++ b/Sources/Core/PersonNameComponents+Extension.swift @@ -10,10 +10,10 @@ import Foundation public extension PersonNameComponents { var name: String? { - guard let givenName = givenName else { + guard let givenName else { return familyName } - guard let familyName = familyName else { + guard let familyName else { return givenName } return "\(givenName) \(familyName)" @@ -21,23 +21,20 @@ public extension PersonNameComponents { } public extension PersonNameComponents { - static func create( - namePrefix: String? = .none, - middleName: String? = .none, - givenName: String? = .none, - familyName: String? = .none, - nameSuffix: String? = .none, - nickname: String? = .none, - phoneticRepresentation: PersonNameComponents? = .none - ) -> PersonNameComponents { - var components = PersonNameComponents() - components.namePrefix = namePrefix - components.familyName = familyName - components.middleName = middleName - components.givenName = givenName - components.nameSuffix = nameSuffix - components.nickname = nickname - components.phoneticRepresentation = phoneticRepresentation - return components + init(namePrefix: String? = .none, + middleName: String? = .none, + givenName: String? = .none, + familyName: String? = .none, + nameSuffix: String? = .none, + nickname: String? = .none, + phoneticRepresentation: PersonNameComponents? = .none) { + self.init() + self.namePrefix = namePrefix + self.familyName = familyName + self.middleName = middleName + self.givenName = givenName + self.nameSuffix = nameSuffix + self.nickname = nickname + self.phoneticRepresentation = phoneticRepresentation } } diff --git a/Sources/Facebook/FacebookAuthenticator.swift b/Sources/Facebook/FacebookAuthenticator.swift index de4c1b2..f133815 100644 --- a/Sources/Facebook/FacebookAuthenticator.swift +++ b/Sources/Facebook/FacebookAuthenticator.swift @@ -110,7 +110,10 @@ private extension FacebookAuthenticator { let authResponse = Response( userId: object.id, token: token.tokenString, - nameComponents: .create(givenName: object.firstName, familyName: object.lastName), + nameComponents: PersonNameComponents( + givenName: object.firstName, + familyName: object.lastName + ), email: object.email, expiresAt: token.expirationDate ) diff --git a/Sources/Google/GoogleAuthenticator.swift b/Sources/Google/GoogleAuthenticator.swift index 25db965..367eb46 100644 --- a/Sources/Google/GoogleAuthenticator.swift +++ b/Sources/Google/GoogleAuthenticator.swift @@ -107,7 +107,7 @@ private extension GIDGoogleUser { idToken: idToken?.tokenString, accessToken: accessToken.tokenString, refreshToken: refreshToken.tokenString, - nameComponents: PersonNameComponents.create( + nameComponents: PersonNameComponents( givenName: profile?.givenName, familyName: profile?.familyName ), diff --git a/Sources/LinkedIn/LinkedInAuthenticator.swift b/Sources/LinkedIn/LinkedInAuthenticator.swift index 70afef5..e2a8aa1 100644 --- a/Sources/LinkedIn/LinkedInAuthenticator.swift +++ b/Sources/LinkedIn/LinkedInAuthenticator.swift @@ -42,7 +42,10 @@ extension LinkedInAuthenticator: Authenticator { return Response( userId: profileResponse.id, token: authResponse.accessToken, - nameComponents: .create(givenName: profileResponse.localizedFirstName, familyName: profileResponse.localizedLastName), + nameComponents: PersonNameComponents( + givenName: profileResponse.localizedFirstName, + familyName: profileResponse.localizedLastName + ), email: emailResponse.emailAddress, expiresAt: authResponse.expiresIn ) From c7b9d9e814cc93c6643c4e9c1808e6329dcda906 Mon Sep 17 00:00:00 2001 From: Yll Fejziu Date: Fri, 15 Nov 2024 13:46:07 +0100 Subject: [PATCH 4/5] Update CI --- .github/workflows/Tests.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/Tests.yml b/.github/workflows/Tests.yml index 9627414..326c034 100644 --- a/.github/workflows/Tests.yml +++ b/.github/workflows/Tests.yml @@ -7,7 +7,7 @@ on: jobs: Tests: - runs-on: macos-14-xlarge + runs-on: macos-15-xlarge steps: - name: Cancel previous jobs uses: styfle/cancel-workflow-action@0.11.0 @@ -21,8 +21,8 @@ jobs: xcode-version: latest-stable - name: Build project - run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild build-for-testing -destination 'name=iPhone 14 Pro' -scheme 'PovioKitAuth-Package' | xcpretty + run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild build-for-testing -destination 'name=iPhone 16 Pro,OS=18.0' -scheme 'PovioKitAuth-Package' | xcpretty - name: Run tests - run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild test-without-building -destination 'name=iPhone 14 Pro' -scheme 'PovioKitAuth-Package' | xcpretty - + run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild test-without-building -destination 'name=iPhone 16 Pro,OS=18.0' -scheme 'PovioKitAuth-Package' | xcpretty + From 1c8d0315a6258697db66e6ed2f2e588ea8391d0c Mon Sep 17 00:00:00 2001 From: Yll Fejziu Date: Fri, 15 Nov 2024 13:49:30 +0100 Subject: [PATCH 5/5] Indentation --- .../Core/PersonNameComponents+Extension.swift | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Sources/Core/PersonNameComponents+Extension.swift b/Sources/Core/PersonNameComponents+Extension.swift index ec508e5..46c70b7 100644 --- a/Sources/Core/PersonNameComponents+Extension.swift +++ b/Sources/Core/PersonNameComponents+Extension.swift @@ -21,13 +21,15 @@ public extension PersonNameComponents { } public extension PersonNameComponents { - init(namePrefix: String? = .none, - middleName: String? = .none, - givenName: String? = .none, - familyName: String? = .none, - nameSuffix: String? = .none, - nickname: String? = .none, - phoneticRepresentation: PersonNameComponents? = .none) { + init( + namePrefix: String? = .none, + middleName: String? = .none, + givenName: String? = .none, + familyName: String? = .none, + nameSuffix: String? = .none, + nickname: String? = .none, + phoneticRepresentation: PersonNameComponents? = .none + ) { self.init() self.namePrefix = namePrefix self.familyName = familyName