Skip to content

Commit

Permalink
Merge pull request #6 from LubomirYordanov/master
Browse files Browse the repository at this point in the history
Include new async / await language feature to make parallel executions possible
  • Loading branch information
KoCMoHaBTa authored Oct 2, 2022
2 parents d5d6c44 + 7b55d05 commit b00e7ea
Show file tree
Hide file tree
Showing 14 changed files with 2,021 additions and 3 deletions.
52 changes: 51 additions & 1 deletion MHIdentityKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@
objects = {

/* Begin PBXBuildFile section */
1EEF02EB289969B40087B863 /* OAuth2IdentityManagerAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02EA289969B40087B863 /* OAuth2IdentityManagerAsyncTests.swift */; };
1EEF02EC289969B40087B863 /* OAuth2IdentityManagerAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02EA289969B40087B863 /* OAuth2IdentityManagerAsyncTests.swift */; };
1EEF02ED289969B40087B863 /* OAuth2IdentityManagerAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02EA289969B40087B863 /* OAuth2IdentityManagerAsyncTests.swift */; };
1EEF02EF289A5D0E0087B863 /* ResourceOwnerPasswordCredentialsGrantFlowAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02EE289A5D0D0087B863 /* ResourceOwnerPasswordCredentialsGrantFlowAsyncTests.swift */; };
1EEF02F0289A5D0E0087B863 /* ResourceOwnerPasswordCredentialsGrantFlowAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02EE289A5D0D0087B863 /* ResourceOwnerPasswordCredentialsGrantFlowAsyncTests.swift */; };
1EEF02F1289A5D0E0087B863 /* ResourceOwnerPasswordCredentialsGrantFlowAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02EE289A5D0D0087B863 /* ResourceOwnerPasswordCredentialsGrantFlowAsyncTests.swift */; };
1EEF02F3289D12CC0087B863 /* ClientCredentialsGrantFlowAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02F2289D12CC0087B863 /* ClientCredentialsGrantFlowAsyncTests.swift */; };
1EEF02F4289D12CC0087B863 /* ClientCredentialsGrantFlowAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02F2289D12CC0087B863 /* ClientCredentialsGrantFlowAsyncTests.swift */; };
1EEF02F5289D12CC0087B863 /* ClientCredentialsGrantFlowAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02F2289D12CC0087B863 /* ClientCredentialsGrantFlowAsyncTests.swift */; };
1EEF02F7289D167C0087B863 /* AuthorizationCodeGrantFlowAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02F6289D167C0087B863 /* AuthorizationCodeGrantFlowAsyncTests.swift */; };
1EEF02F8289D167C0087B863 /* AuthorizationCodeGrantFlowAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02F6289D167C0087B863 /* AuthorizationCodeGrantFlowAsyncTests.swift */; };
1EEF02F9289D167C0087B863 /* AuthorizationCodeGrantFlowAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02F6289D167C0087B863 /* AuthorizationCodeGrantFlowAsyncTests.swift */; };
1EEF02FB289D33CE0087B863 /* ImplicitGrantFlowAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02FA289D33CE0087B863 /* ImplicitGrantFlowAsyncTests.swift */; };
1EEF02FC289D33CE0087B863 /* ImplicitGrantFlowAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02FA289D33CE0087B863 /* ImplicitGrantFlowAsyncTests.swift */; };
1EEF02FD289D33CE0087B863 /* ImplicitGrantFlowAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02FA289D33CE0087B863 /* ImplicitGrantFlowAsyncTests.swift */; };
1EEF02FF289D3DD00087B863 /* RequestAuthorizerAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02FE289D3DD00087B863 /* RequestAuthorizerAsyncTests.swift */; };
1EEF0300289D3DD00087B863 /* RequestAuthorizerAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02FE289D3DD00087B863 /* RequestAuthorizerAsyncTests.swift */; };
1EEF0301289D3DD00087B863 /* RequestAuthorizerAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EEF02FE289D3DD00087B863 /* RequestAuthorizerAsyncTests.swift */; };
9954AE4F1E9D169700F2A73D /* MHIdentityKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9954AE451E9D169700F2A73D /* MHIdentityKit.framework */; };
9954AE541E9D169700F2A73D /* MHIdentityKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9954AE531E9D169700F2A73D /* MHIdentityKitTests.swift */; };
9954AE561E9D169700F2A73D /* MHIdentityKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 9954AE481E9D169700F2A73D /* MHIdentityKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -292,6 +310,12 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
1EEF02EA289969B40087B863 /* OAuth2IdentityManagerAsyncTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuth2IdentityManagerAsyncTests.swift; sourceTree = "<group>"; };
1EEF02EE289A5D0D0087B863 /* ResourceOwnerPasswordCredentialsGrantFlowAsyncTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceOwnerPasswordCredentialsGrantFlowAsyncTests.swift; sourceTree = "<group>"; };
1EEF02F2289D12CC0087B863 /* ClientCredentialsGrantFlowAsyncTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientCredentialsGrantFlowAsyncTests.swift; sourceTree = "<group>"; };
1EEF02F6289D167C0087B863 /* AuthorizationCodeGrantFlowAsyncTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorizationCodeGrantFlowAsyncTests.swift; sourceTree = "<group>"; };
1EEF02FA289D33CE0087B863 /* ImplicitGrantFlowAsyncTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImplicitGrantFlowAsyncTests.swift; sourceTree = "<group>"; };
1EEF02FE289D3DD00087B863 /* RequestAuthorizerAsyncTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestAuthorizerAsyncTests.swift; sourceTree = "<group>"; };
434E10062685CF1C00257D8A /* MHIdentityKit-iOSTestsHost.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "MHIdentityKit-iOSTestsHost.entitlements"; sourceTree = "<group>"; };
434E10082685FD5F00257D8A /* MHIdentityKit-tvOSTestsHost.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "MHIdentityKit-tvOSTestsHost.entitlements"; sourceTree = "<group>"; };
9954AE451E9D169700F2A73D /* MHIdentityKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MHIdentityKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -713,6 +737,10 @@
E6B1956D22CA068C00954DED /* ImplicitGrantFlowTests.swift */,
E6B39C2B206BB24300CB1435 /* ResourceOwnerPasswordCredentialsGrantFlowTests.swift */,
E6B39C27206BB23700CB1435 /* ClientCredentialsGrantFlowTests.swift */,
1EEF02EE289A5D0D0087B863 /* ResourceOwnerPasswordCredentialsGrantFlowAsyncTests.swift */,
1EEF02F2289D12CC0087B863 /* ClientCredentialsGrantFlowAsyncTests.swift */,
1EEF02F6289D167C0087B863 /* AuthorizationCodeGrantFlowAsyncTests.swift */,
1EEF02FA289D33CE0087B863 /* ImplicitGrantFlowAsyncTests.swift */,
);
path = Flows;
sourceTree = "<group>";
Expand All @@ -725,6 +753,8 @@
E619748F1EE15F9C00DAFC15 /* IdentityStorageTests.swift */,
E61974911EE160F000DAFC15 /* RequestAuthorizerTests.swift */,
E61974B11EE5688800DAFC15 /* OAuth2IdentityManagerTests.swift */,
1EEF02EA289969B40087B863 /* OAuth2IdentityManagerAsyncTests.swift */,
1EEF02FE289D3DD00087B863 /* RequestAuthorizerAsyncTests.swift */,
);
path = Infrastructure;
sourceTree = "<group>";
Expand Down Expand Up @@ -771,9 +801,9 @@
isa = PBXNativeTarget;
buildConfigurationList = 9954AE591E9D169700F2A73D /* Build configuration list for PBXNativeTarget "MHIdentityKit-iOS" */;
buildPhases = (
9954AE421E9D169700F2A73D /* Headers */,
9954AE401E9D169700F2A73D /* Sources */,
9954AE411E9D169700F2A73D /* Frameworks */,
9954AE421E9D169700F2A73D /* Headers */,
9954AE431E9D169700F2A73D /* Resources */,
);
buildRules = (
Expand Down Expand Up @@ -1182,12 +1212,18 @@
E683DCA81ED426BE0075B03B /* XCTestExtensions.swift in Sources */,
E6B1956E22CA068C00954DED /* ImplicitGrantFlowTests.swift in Sources */,
E619748E1EE15EAD00DAFC15 /* CredentialsProviderTests.swift in Sources */,
1EEF02FF289D3DD00087B863 /* RequestAuthorizerAsyncTests.swift in Sources */,
E61974901EE15F9C00DAFC15 /* IdentityStorageTests.swift in Sources */,
1EEF02FB289D33CE0087B863 /* ImplicitGrantFlowAsyncTests.swift in Sources */,
E6B39C2C206BB24300CB1435 /* ResourceOwnerPasswordCredentialsGrantFlowTests.swift in Sources */,
1EEF02F3289D12CC0087B863 /* ClientCredentialsGrantFlowAsyncTests.swift in Sources */,
1EEF02F7289D167C0087B863 /* AuthorizationCodeGrantFlowAsyncTests.swift in Sources */,
1EEF02EF289A5D0E0087B863 /* ResourceOwnerPasswordCredentialsGrantFlowAsyncTests.swift in Sources */,
E619748A1EE0B50000DAFC15 /* AccessTokenResponseHandlerTests.swift in Sources */,
E6B39C24206BB22500CB1435 /* AuthorizationCodeGrantFlowTests.swift in Sources */,
E61974B21EE5688800DAFC15 /* OAuth2IdentityManagerTests.swift in Sources */,
E6B39C28206BB23700CB1435 /* ClientCredentialsGrantFlowTests.swift in Sources */,
1EEF02EB289969B40087B863 /* OAuth2IdentityManagerAsyncTests.swift in Sources */,
E61974921EE160F000DAFC15 /* RequestAuthorizerTests.swift in Sources */,
9954AE541E9D169700F2A73D /* MHIdentityKitTests.swift in Sources */,
);
Expand Down Expand Up @@ -1306,12 +1342,18 @@
E6985E1220690C6800BE5F6A /* XCTestExtensions.swift in Sources */,
E6B1956F22CA068C00954DED /* ImplicitGrantFlowTests.swift in Sources */,
E6985E1520690C6800BE5F6A /* CredentialsProviderTests.swift in Sources */,
1EEF0300289D3DD00087B863 /* RequestAuthorizerAsyncTests.swift in Sources */,
E6985E1620690C6800BE5F6A /* IdentityStorageTests.swift in Sources */,
1EEF02FC289D33CE0087B863 /* ImplicitGrantFlowAsyncTests.swift in Sources */,
E6B39C2D206BB24300CB1435 /* ResourceOwnerPasswordCredentialsGrantFlowTests.swift in Sources */,
1EEF02F4289D12CC0087B863 /* ClientCredentialsGrantFlowAsyncTests.swift in Sources */,
1EEF02F8289D167C0087B863 /* AuthorizationCodeGrantFlowAsyncTests.swift in Sources */,
1EEF02F0289A5D0E0087B863 /* ResourceOwnerPasswordCredentialsGrantFlowAsyncTests.swift in Sources */,
E6985E1420690C6800BE5F6A /* AccessTokenResponseHandlerTests.swift in Sources */,
E6B39C25206BB22500CB1435 /* AuthorizationCodeGrantFlowTests.swift in Sources */,
E6985E1920690C6800BE5F6A /* OAuth2IdentityManagerTests.swift in Sources */,
E6B39C29206BB23700CB1435 /* ClientCredentialsGrantFlowTests.swift in Sources */,
1EEF02EC289969B40087B863 /* OAuth2IdentityManagerAsyncTests.swift in Sources */,
E6985E1720690C6800BE5F6A /* RequestAuthorizerTests.swift in Sources */,
E6985E1320690C6800BE5F6A /* MHIdentityKitTests.swift in Sources */,
);
Expand Down Expand Up @@ -1372,12 +1414,18 @@
E6985E1A20690C6900BE5F6A /* XCTestExtensions.swift in Sources */,
E6B1957022CA068C00954DED /* ImplicitGrantFlowTests.swift in Sources */,
E6985E1D20690C6900BE5F6A /* CredentialsProviderTests.swift in Sources */,
1EEF0301289D3DD00087B863 /* RequestAuthorizerAsyncTests.swift in Sources */,
E6985E1E20690C6900BE5F6A /* IdentityStorageTests.swift in Sources */,
1EEF02FD289D33CE0087B863 /* ImplicitGrantFlowAsyncTests.swift in Sources */,
E6B39C2E206BB24300CB1435 /* ResourceOwnerPasswordCredentialsGrantFlowTests.swift in Sources */,
1EEF02F5289D12CC0087B863 /* ClientCredentialsGrantFlowAsyncTests.swift in Sources */,
1EEF02F9289D167C0087B863 /* AuthorizationCodeGrantFlowAsyncTests.swift in Sources */,
1EEF02F1289A5D0E0087B863 /* ResourceOwnerPasswordCredentialsGrantFlowAsyncTests.swift in Sources */,
E6985E1C20690C6900BE5F6A /* AccessTokenResponseHandlerTests.swift in Sources */,
E6B39C26206BB22500CB1435 /* AuthorizationCodeGrantFlowTests.swift in Sources */,
E6985E2120690C6900BE5F6A /* OAuth2IdentityManagerTests.swift in Sources */,
E6B39C2A206BB23700CB1435 /* ClientCredentialsGrantFlowTests.swift in Sources */,
1EEF02ED289969B40087B863 /* OAuth2IdentityManagerAsyncTests.swift in Sources */,
E6985E1F20690C6900BE5F6A /* RequestAuthorizerTests.swift in Sources */,
E6985E1B20690C6900BE5F6A /* MHIdentityKitTests.swift in Sources */,
);
Expand Down Expand Up @@ -1489,6 +1537,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
APPLICATION_EXTENSION_API_ONLY = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
Expand Down Expand Up @@ -1559,6 +1608,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
APPLICATION_EXTENSION_API_ONLY = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,22 @@ public protocol CredentialsProvider {
func didFailAuthenticating(with error: Error)
}

extension CredentialsProvider {

///Provides credentials asynchronously. Can be implemented in a way to show a login screen.
@available(iOS 13, tvOS 13.0.0, macOS 10.15, *)
public func credentials() async -> (Username, Password) {

return await withCheckedContinuation { continuation in

self.credentials { (username, password) in

continuation.resume(returning: (username, password))
}
}
}
}

extension CredentialsProvider {

public func didFinishAuthenticating() {
Expand Down
90 changes: 90 additions & 0 deletions MHIdentityKit/Infrastructure/IdentityManager/IdentityManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,37 @@ public protocol IdentityManager {
var responseValidator: NetworkResponseValidator { get }
}

extension IdentityManager {

/**
Asynchronously authorizes an instance of URLRequest.
- parameter request: The request to authorize.
- parameter forceAuthenticate: If true, an authentication is always performed, otherwise authentication is done only if internal state requires it, like the access token has expired
- throws: if authorization fails.
- returns: The authorized request
*/

@available(iOS 13, tvOS 13.0.0, macOS 10.15, *)
public func authorize(request: URLRequest, forceAuthenticate: Bool) async throws -> URLRequest {

return try await withCheckedThrowingContinuation { continuation in

self.authorize(request: request, forceAuthenticate: forceAuthenticate) { urlRequest, error in

if let error = error {
continuation.resume(throwing: error)
}
else {
continuation.resume(returning: urlRequest)
}
}
}
}
}

extension IdentityManager {

/**
Expand All @@ -50,6 +81,22 @@ extension IdentityManager {
self.authorize(request: request, forceAuthenticate: false, handler: handler)
}

/**
Asynchronously authorizes an instance of URLRequest.
- parameter request: The request to authorize.
- throws: if authorization fails
- returns: The authorized request
*/

@available(iOS 13, tvOS 13.0.0, macOS 10.15, *)
public func authorize(request: URLRequest) async throws -> URLRequest {

return try await self.authorize(request: request, forceAuthenticate: false)
}

///Performs forced authentication on a placeholder request. Can be used when you want to authenticate in advance, without authorizing a particular request
public func forceAuthenticate(handler: ((Error?) -> Void)? = nil) {

Expand All @@ -61,6 +108,24 @@ extension IdentityManager {
handler?(error)
}
}

///Performs forced authentication on a placeholder request. Can be used when you want to authenticate in advance, without authorizing a particular request
@available(iOS 13, tvOS 13.0.0, macOS 10.15, *)
public func forceAuthenticate() async throws {

return try await withCheckedThrowingContinuation { continuation in

self.forceAuthenticate { error in

if let error = error {
continuation.resume(throwing: error)
}
else {
continuation.resume(returning: ())
}
}
}
}
}

extension URLRequest {
Expand Down Expand Up @@ -181,5 +246,30 @@ extension IdentityManager {
}
}
}

/**
Performs an asynchronous request and validates if the response requires authentication.
- parameter request: The request to be performed
- parameter networkClient: The client that should perform the request. Default to internal system client.
- parameter retryAttempts: The number of times to retry the request if the validation fails.
- parameter validator: The validator, used to determine if a request must be reauthorized with forced authentication and retried, based on the network response. Default to `responseValidator` if nil is passed.
- parameter forceAuthenticate: Whenver to force authentication during authorization. Default to false.
- returns: The response when the requests has finished
- note: The implementation of this menthod, simple checks if the HTTP response status code is 401 Unauthorized and if so - authorizes the request again by forcing the authentication. Then the request is retried.
*/

@available(iOS 13, tvOS 13.0.0, macOS 10.15, *)
public func perform(_ request: URLRequest, using networkClient: NetworkClient = _defaultNetworkClient, retryAttempts: Int = 1, validator: NetworkResponseValidator? = nil, forceAuthenticate: Bool = false) async -> NetworkResponse {

return await withCheckedContinuation { continuation in

self.perform(request, using: networkClient, retryAttempts: retryAttempts, validator: validator, forceAuthenticate: forceAuthenticate) { response in
continuation.resume(returning: response)
}
}
}
}

Loading

0 comments on commit b00e7ea

Please sign in to comment.