From d2db636d6fdbded6b128590e80343ba4ceb3b1d8 Mon Sep 17 00:00:00 2001 From: dianakarh <86302636+dianakarh@users.noreply.github.com> Date: Thu, 20 Oct 2022 14:31:13 +0300 Subject: [PATCH] Mob 4371 post release 1 7 0 [MASTER] (#169) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) * Bump nokogiri from 1.11.2 to 1.11.5 (#98) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.2 to 1.11.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.2...v1.11.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use date data type for dateBooked (#99) * Bump version number to 1.5.0 (#100) * [MOB-3438] login with credentials (#104) * Make first small changes to auth service. * Create auth credentials swift files and update authservice * Init auth credentials interactor * Credentials finally works as public * Almost finished * Swap credentials with authToken * Finish interactor + rename token interactor * Remove requestsender * Test pass * Release 1.5.1 (#106) * versiob bump to 1_5_1-rc1 * updated version to 1_5_1 * changed readme (#108) * MOB-3445 change AuthToken init access level from internal to public (#109) * MOB-3488 Release 1.5.2 (develop) (#110) * Release 1.5.2 * Update marketting project version * MOB-3405 fix coding key for fleet capabilties (#112) Co-authored-by: Anca Feurdean * fix refresh token call headers (#114) * MOB-3528: Release 1.5.3 (develop) (#115) * Release 1.5.3 * test circleci * undo circleci test * Add new error codes (#117) * Add loyalty nonce to booking api (#118) * Modify LoyaltyProgramme to be an Object vs an Array (#120) * Mob xxxx circleci fix (#124) * Update config.yml * Update config.yml * Revert * Avoid deleting the SSH private key * use separate commends * use xlarge resource * use cache for bundle * update xcode version to 12.2.0 * a bit cleanup * revert back to working version * update bundler version * use large resource * use xlarge resource * update xcode version, decrease resource_class to medium to fit our price plan * revert Xcode to 12.0, revert resource_class to xlarge, and change bundler version to 2.2.7 - working UISDK config * try solution proposed by Mikolaj * going back to xcode 12.2 and large resource_class * using medium resource_class * update fastlane * update fastlane take 2 * circleci sanity check * test removing ssh key * reverting last commit * adjust bundler version * test circleci * update to xcode 13 * update fastlane * remove fastline update, run bundle install before installing specific gem * Use xcode 12.5.1 * Minor change Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Diana Petrea * [MOB-3633] Add Loyalty API (#119) * Add endpoints * LoyaltyStatus API Added * Add LoyaltyPoints model * Fix up the API endpoints * LoyaltyStatus Interactor * Edit APIEndpoint again * Update LoyaltyService * LoyaltyBurn interactor * Loyaltyearn Interactor * Update LoyaltyService * PreAuth interactor * Update service * Add mocks * Preauth mock * Add tests * Add remaining tests * Update PreAuth interactor * Remove Integration Tests (Not ready) * Fix loyaltyservice for preauth * Fix tests * Make requested changes to LoyaltyPreAuth * points to burnPoints * Guard currency * Fix broken test * Add new status test to make sure request is setup correctly * Fix loyaltyStatus? * cicleci test commit * test circleci commit * Add errors * Mob 3656 (#123) * get and persist loyalty status after payment provider response * minor change * add get current status method to loyalty service * refresh current loyalty status * add unit tests * Fix for paymemt provider model * resolve PR comments Co-authored-by: Mostafa Hadian Co-authored-by: Diana Petrea Co-authored-by: Mostafa Hadian Co-authored-by: dianakarh <86302636+dianakarh@users.noreply.github.com> * Mob 3650 (#125) * update loyalty nonce model * fix unit test * fix loyalty preauth interactor * redo execute implementation in loyalty preauth interactor * Mob 3785 (#126) * add slug to KarhooError * use slug, add new error type * add new errot type * bump version (#127) * MOB-3819 add shopper locale to adyen payment request (#129) * add shopper locale to adyen payment request * add minor tweak * Feature/MOB-3883 add basic analytics events to track the conversion steps (#130) * New event names added according to requirements in https://karhoo.atlassian.net/browse/MOB-3868 * cleanup * cleanup * Renaming * bump version (#131) * change vehicle class to vehicle type in quote categories (#134) * change vehicle class to vehicle type in quote categories * fix tests * Feature/4021 add client key endpoint (#137) * add Adyen client key call * Mob 4024 post release 1.6 [DEVELOP] (#141) * [MOB-3216] Update master (#97) * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: Mostafa Hadian Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> * MOB-3387 Final release 1.5.0 (#102) * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) * Bump nokogiri from 1.11.2 to 1.11.5 (#98) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.2 to 1.11.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.2...v1.11.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use date data type for dateBooked (#99) * Bump version number to 1.5.0 Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> * Post release 1 5 1 (#107) * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) * Bump nokogiri from 1.11.2 to 1.11.5 (#98) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.2 to 1.11.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.2...v1.11.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use date data type for dateBooked (#99) * Bump version number to 1.5.0 (#100) * [MOB-3438] login with credentials (#104) * Make first small changes to auth service. * Create auth credentials swift files and update authservice * Init auth credentials interactor * Credentials finally works as public * Almost finished * Swap credentials with authToken * Finish interactor + rename token interactor * Remove requestsender * Test pass * versiob bump to 1_5_1-rc1 * updated version to 1_5_1 Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: Mostafa Hadian Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> * MOB-3488 Post release 1.5.2 (master) (#111) * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) * Bump nokogiri from 1.11.2 to 1.11.5 (#98) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.2 to 1.11.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.2...v1.11.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use date data type for dateBooked (#99) * Bump version number to 1.5.0 (#100) * [MOB-3438] login with credentials (#104) * Make first small changes to auth service. * Create auth credentials swift files and update authservice * Init auth credentials interactor * Credentials finally works as public * Almost finished * Swap credentials with authToken * Finish interactor + rename token interactor * Remove requestsender * Test pass * Release 1.5.1 (#106) * versiob bump to 1_5_1-rc1 * updated version to 1_5_1 * changed readme (#108) * MOB-3445 change AuthToken init access level from internal to public (#109) * Release 1.5.2 * Update marketting project version Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> Co-authored-by: cosminBadulescu Co-authored-by: dianakarh <86302636+dianakarh@users.noreply.github.com> * MOB-3528: Post Release 1.5.3 (master) (#116) * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) * Bump nokogiri from 1.11.2 to 1.11.5 (#98) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.2 to 1.11.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.2...v1.11.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use date data type for dateBooked (#99) * Bump version number to 1.5.0 (#100) * [MOB-3438] login with credentials (#104) * Make first small changes to auth service. * Create auth credentials swift files and update authservice * Init auth credentials interactor * Credentials finally works as public * Almost finished * Swap credentials with authToken * Finish interactor + rename token interactor * Remove requestsender * Test pass * Release 1.5.1 (#106) * versiob bump to 1_5_1-rc1 * updated version to 1_5_1 * changed readme (#108) * MOB-3445 change AuthToken init access level from internal to public (#109) * MOB-3488 Release 1.5.2 (develop) (#110) * Release 1.5.2 * Update marketting project version * MOB-3405 fix coding key for fleet capabilties (#112) Co-authored-by: Anca Feurdean * fix refresh token call headers (#114) * Release 1.5.3 * test circleci fix * undo circleci test Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: Mostafa Hadian Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> Co-authored-by: cosminBadulescu Co-authored-by: ancafeurdean09 <30659315+ancafeurdean09@users.noreply.github.com> * Mob-3749_post_release_1_5_4 (#128) * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) * Bump nokogiri from 1.11.2 to 1.11.5 (#98) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.2 to 1.11.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.2...v1.11.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use date data type for dateBooked (#99) * Bump version number to 1.5.0 (#100) * [MOB-3438] login with credentials (#104) * Make first small changes to auth service. * Create auth credentials swift files and update authservice * Init auth credentials interactor * Credentials finally works as public * Almost finished * Swap credentials with authToken * Finish interactor + rename token interactor * Remove requestsender * Test pass * Release 1.5.1 (#106) * versiob bump to 1_5_1-rc1 * updated version to 1_5_1 * changed readme (#108) * MOB-3445 change AuthToken init access level from internal to public (#109) * MOB-3488 Release 1.5.2 (develop) (#110) * Release 1.5.2 * Update marketting project version * MOB-3405 fix coding key for fleet capabilties (#112) Co-authored-by: Anca Feurdean * fix refresh token call headers (#114) * MOB-3528: Release 1.5.3 (develop) (#115) * Release 1.5.3 * test circleci * undo circleci test * Add new error codes (#117) * Add loyalty nonce to booking api (#118) * Modify LoyaltyProgramme to be an Object vs an Array (#120) * Mob xxxx circleci fix (#124) * Update config.yml * Update config.yml * Revert * Avoid deleting the SSH private key * use separate commends * use xlarge resource * use cache for bundle * update xcode version to 12.2.0 * a bit cleanup * revert back to working version * update bundler version * use large resource * use xlarge resource * update xcode version, decrease resource_class to medium to fit our price plan * revert Xcode to 12.0, revert resource_class to xlarge, and change bundler version to 2.2.7 - working UISDK config * try solution proposed by Mikolaj * going back to xcode 12.2 and large resource_class * using medium resource_class * update fastlane * update fastlane take 2 * circleci sanity check * test removing ssh key * reverting last commit * adjust bundler version * test circleci * update to xcode 13 * update fastlane * remove fastline update, run bundle install before installing specific gem * Use xcode 12.5.1 * Minor change Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Diana Petrea * [MOB-3633] Add Loyalty API (#119) * Add endpoints * LoyaltyStatus API Added * Add LoyaltyPoints model * Fix up the API endpoints * LoyaltyStatus Interactor * Edit APIEndpoint again * Update LoyaltyService * LoyaltyBurn interactor * Loyaltyearn Interactor * Update LoyaltyService * PreAuth interactor * Update service * Add mocks * Preauth mock * Add tests * Add remaining tests * Update PreAuth interactor * Remove Integration Tests (Not ready) * Fix loyaltyservice for preauth * Fix tests * Make requested changes to LoyaltyPreAuth * points to burnPoints * Guard currency * Fix broken test * Add new status test to make sure request is setup correctly * Fix loyaltyStatus? * cicleci test commit * test circleci commit * Add errors * Mob 3656 (#123) * get and persist loyalty status after payment provider response * minor change * add get current status method to loyalty service * refresh current loyalty status * add unit tests * Fix for paymemt provider model * resolve PR comments Co-authored-by: Mostafa Hadian Co-authored-by: Diana Petrea Co-authored-by: Mostafa Hadian Co-authored-by: dianakarh <86302636+dianakarh@users.noreply.github.com> * Mob 3650 (#125) * update loyalty nonce model * fix unit test * fix loyalty preauth interactor * redo execute implementation in loyalty preauth interactor * Mob 3785 (#126) * add slug to KarhooError * use slug, add new error type * add new errot type * bump version Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: Mostafa Hadian Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> Co-authored-by: cosminBadulescu Co-authored-by: ancafeurdean09 <30659315+ancafeurdean09@users.noreply.github.com> Co-authored-by: Anca Feurdean * Mob 3893 post release 1 5 5 [MASTER] (#132) * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) * Bump nokogiri from 1.11.2 to 1.11.5 (#98) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.2 to 1.11.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.2...v1.11.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use date data type for dateBooked (#99) * Bump version number to 1.5.0 (#100) * [MOB-3438] login with credentials (#104) * Make first small changes to auth service. * Create auth credentials swift files and update authservice * Init auth credentials interactor * Credentials finally works as public * Almost finished * Swap credentials with authToken * Finish interactor + rename token interactor * Remove requestsender * Test pass * Release 1.5.1 (#106) * versiob bump to 1_5_1-rc1 * updated version to 1_5_1 * changed readme (#108) * MOB-3445 change AuthToken init access level from internal to public (#109) * MOB-3488 Release 1.5.2 (develop) (#110) * Release 1.5.2 * Update marketting project version * MOB-3405 fix coding key for fleet capabilties (#112) Co-authored-by: Anca Feurdean * fix refresh token call headers (#114) * MOB-3528: Release 1.5.3 (develop) (#115) * Release 1.5.3 * test circleci * undo circleci test * Add new error codes (#117) * Add loyalty nonce to booking api (#118) * Modify LoyaltyProgramme to be an Object vs an Array (#120) * Mob xxxx circleci fix (#124) * Update config.yml * Update config.yml * Revert * Avoid deleting the SSH private key * use separate commends * use xlarge resource * use cache for bundle * update xcode version to 12.2.0 * a bit cleanup * revert back to working version * update bundler version * use large resource * use xlarge resource * update xcode version, decrease resource_class to medium to fit our price plan * revert Xcode to 12.0, revert resource_class to xlarge, and change bundler version to 2.2.7 - working UISDK config * try solution proposed by Mikolaj * going back to xcode 12.2 and large resource_class * using medium resource_class * update fastlane * update fastlane take 2 * circleci sanity check * test removing ssh key * reverting last commit * adjust bundler version * test circleci * update to xcode 13 * update fastlane * remove fastline update, run bundle install before installing specific gem * Use xcode 12.5.1 * Minor change Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Diana Petrea * [MOB-3633] Add Loyalty API (#119) * Add endpoints * LoyaltyStatus API Added * Add LoyaltyPoints model * Fix up the API endpoints * LoyaltyStatus Interactor * Edit APIEndpoint again * Update LoyaltyService * LoyaltyBurn interactor * Loyaltyearn Interactor * Update LoyaltyService * PreAuth interactor * Update service * Add mocks * Preauth mock * Add tests * Add remaining tests * Update PreAuth interactor * Remove Integration Tests (Not ready) * Fix loyaltyservice for preauth * Fix tests * Make requested changes to LoyaltyPreAuth * points to burnPoints * Guard currency * Fix broken test * Add new status test to make sure request is setup correctly * Fix loyaltyStatus? * cicleci test commit * test circleci commit * Add errors * Mob 3656 (#123) * get and persist loyalty status after payment provider response * minor change * add get current status method to loyalty service * refresh current loyalty status * add unit tests * Fix for paymemt provider model * resolve PR comments Co-authored-by: Mostafa Hadian Co-authored-by: Diana Petrea Co-authored-by: Mostafa Hadian Co-authored-by: dianakarh <86302636+dianakarh@users.noreply.github.com> * Mob 3650 (#125) * update loyalty nonce model * fix unit test * fix loyalty preauth interactor * redo execute implementation in loyalty preauth interactor * Mob 3785 (#126) * add slug to KarhooError * use slug, add new error type * add new errot type * bump version (#127) * MOB-3819 add shopper locale to adyen payment request (#129) * add shopper locale to adyen payment request * add minor tweak * Feature/MOB-3883 add basic analytics events to track the conversion steps (#130) * New event names added according to requirements in https://karhoo.atlassian.net/browse/MOB-3868 * cleanup * cleanup * Renaming * bump version Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: Mostafa Hadian Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> Co-authored-by: cosminBadulescu Co-authored-by: ancafeurdean09 <30659315+ancafeurdean09@users.noreply.github.com> Co-authored-by: Anca Feurdean Co-authored-by: Aleksander Wędrychowski <97090287+AleksanderWedrychowskiKarhoo@users.noreply.github.com> * Feature/MOB-4020 update network sdk to support versioning of payment related calls (#136) * Add `version` parameter to PaymentProvider model * Payment API Version added to payments interactors and endpints * force v68 api version for debug * Payment version added to path if differs from v51 * version path component fix * version string calculation improved * Test v68 version * update tests * version bump 1.5.5 => 1.5.6 * Change version number * MOB-4021 cherry pick * version bump 1.6.0 * version bump in Podspec Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: Mostafa Hadian Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> Co-authored-by: cosminBadulescu Co-authored-by: dianakarh <86302636+dianakarh@users.noreply.github.com> Co-authored-by: ancafeurdean09 <30659315+ancafeurdean09@users.noreply.github.com> Co-authored-by: Anca Feurdean Co-authored-by: Aleksander Wędrychowski <97090287+AleksanderWedrychowskiKarhoo@users.noreply.github.com> Co-authored-by: Aleksander Wędrychowski * MOB-4020 post release 1.6.1 [develop] (#144) * [MOB-3216] Update master (#97) * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: Mostafa Hadian Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> * MOB-3387 Final release 1.5.0 (#102) * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) * Bump nokogiri from 1.11.2 to 1.11.5 (#98) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.2 to 1.11.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.2...v1.11.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use date data type for dateBooked (#99) * Bump version number to 1.5.0 Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> * Post release 1 5 1 (#107) * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) * Bump nokogiri from 1.11.2 to 1.11.5 (#98) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.2 to 1.11.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.2...v1.11.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use date data type for dateBooked (#99) * Bump version number to 1.5.0 (#100) * [MOB-3438] login with credentials (#104) * Make first small changes to auth service. * Create auth credentials swift files and update authservice * Init auth credentials interactor * Credentials finally works as public * Almost finished * Swap credentials with authToken * Finish interactor + rename token interactor * Remove requestsender * Test pass * versiob bump to 1_5_1-rc1 * updated version to 1_5_1 Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: Mostafa Hadian Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> * MOB-3488 Post release 1.5.2 (master) (#111) * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) * Bump nokogiri from 1.11.2 to 1.11.5 (#98) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.2 to 1.11.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.2...v1.11.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use date data type for dateBooked (#99) * Bump version number to 1.5.0 (#100) * [MOB-3438] login with credentials (#104) * Make first small changes to auth service. * Create auth credentials swift files and update authservice * Init auth credentials interactor * Credentials finally works as public * Almost finished * Swap credentials with authToken * Finish interactor + rename token interactor * Remove requestsender * Test pass * Release 1.5.1 (#106) * versiob bump to 1_5_1-rc1 * updated version to 1_5_1 * changed readme (#108) * MOB-3445 change AuthToken init access level from internal to public (#109) * Release 1.5.2 * Update marketting project version Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> Co-authored-by: cosminBadulescu Co-authored-by: dianakarh <86302636+dianakarh@users.noreply.github.com> * MOB-3528: Post Release 1.5.3 (master) (#116) * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) * Bump nokogiri from 1.11.2 to 1.11.5 (#98) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.2 to 1.11.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.2...v1.11.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use date data type for dateBooked (#99) * Bump version number to 1.5.0 (#100) * [MOB-3438] login with credentials (#104) * Make first small changes to auth service. * Create auth credentials swift files and update authservice * Init auth credentials interactor * Credentials finally works as public * Almost finished * Swap credentials with authToken * Finish interactor + rename token interactor * Remove requestsender * Test pass * Release 1.5.1 (#106) * versiob bump to 1_5_1-rc1 * updated version to 1_5_1 * changed readme (#108) * MOB-3445 change AuthToken init access level from internal to public (#109) * MOB-3488 Release 1.5.2 (develop) (#110) * Release 1.5.2 * Update marketting project version * MOB-3405 fix coding key for fleet capabilties (#112) Co-authored-by: Anca Feurdean * fix refresh token call headers (#114) * Release 1.5.3 * test circleci fix * undo circleci test Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: Mostafa Hadian Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> Co-authored-by: cosminBadulescu Co-authored-by: ancafeurdean09 <30659315+ancafeurdean09@users.noreply.github.com> * Mob-3749_post_release_1_5_4 (#128) * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) * Bump nokogiri from 1.11.2 to 1.11.5 (#98) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.2 to 1.11.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.2...v1.11.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use date data type for dateBooked (#99) * Bump version number to 1.5.0 (#100) * [MOB-3438] login with credentials (#104) * Make first small changes to auth service. * Create auth credentials swift files and update authservice * Init auth credentials interactor * Credentials finally works as public * Almost finished * Swap credentials with authToken * Finish interactor + rename token interactor * Remove requestsender * Test pass * Release 1.5.1 (#106) * versiob bump to 1_5_1-rc1 * updated version to 1_5_1 * changed readme (#108) * MOB-3445 change AuthToken init access level from internal to public (#109) * MOB-3488 Release 1.5.2 (develop) (#110) * Release 1.5.2 * Update marketting project version * MOB-3405 fix coding key for fleet capabilties (#112) Co-authored-by: Anca Feurdean * fix refresh token call headers (#114) * MOB-3528: Release 1.5.3 (develop) (#115) * Release 1.5.3 * test circleci * undo circleci test * Add new error codes (#117) * Add loyalty nonce to booking api (#118) * Modify LoyaltyProgramme to be an Object vs an Array (#120) * Mob xxxx circleci fix (#124) * Update config.yml * Update config.yml * Revert * Avoid deleting the SSH private key * use separate commends * use xlarge resource * use cache for bundle * update xcode version to 12.2.0 * a bit cleanup * revert back to working version * update bundler version * use large resource * use xlarge resource * update xcode version, decrease resource_class to medium to fit our price plan * revert Xcode to 12.0, revert resource_class to xlarge, and change bundler version to 2.2.7 - working UISDK config * try solution proposed by Mikolaj * going back to xcode 12.2 and large resource_class * using medium resource_class * update fastlane * update fastlane take 2 * circleci sanity check * test removing ssh key * reverting last commit * adjust bundler version * test circleci * update to xcode 13 * update fastlane * remove fastline update, run bundle install before installing specific gem * Use xcode 12.5.1 * Minor change Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Diana Petrea * [MOB-3633] Add Loyalty API (#119) * Add endpoints * LoyaltyStatus API Added * Add LoyaltyPoints model * Fix up the API endpoints * LoyaltyStatus Interactor * Edit APIEndpoint again * Update LoyaltyService * LoyaltyBurn interactor * Loyaltyearn Interactor * Update LoyaltyService * PreAuth interactor * Update service * Add mocks * Preauth mock * Add tests * Add remaining tests * Update PreAuth interactor * Remove Integration Tests (Not ready) * Fix loyaltyservice for preauth * Fix tests * Make requested changes to LoyaltyPreAuth * points to burnPoints * Guard currency * Fix broken test * Add new status test to make sure request is setup correctly * Fix loyaltyStatus? * cicleci test commit * test circleci commit * Add errors * Mob 3656 (#123) * get and persist loyalty status after payment provider response * minor change * add get current status method to loyalty service * refresh current loyalty status * add unit tests * Fix for paymemt provider model * resolve PR comments Co-authored-by: Mostafa Hadian Co-authored-by: Diana Petrea Co-authored-by: Mostafa Hadian Co-authored-by: dianakarh <86302636+dianakarh@users.noreply.github.com> * Mob 3650 (#125) * update loyalty nonce model * fix unit test * fix loyalty preauth interactor * redo execute implementation in loyalty preauth interactor * Mob 3785 (#126) * add slug to KarhooError * use slug, add new error type * add new errot type * bump version Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: Mostafa Hadian Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> Co-authored-by: cosminBadulescu Co-authored-by: ancafeurdean09 <30659315+ancafeurdean09@users.noreply.github.com> Co-authored-by: Anca Feurdean * Mob 3893 post release 1 5 5 [MASTER] (#132) * [MOB-2976] Quote model update for Polling (#80) * Update quote models * Update tests * Update cart file (#81) * Call follow endpoint for guest checkout booking fee retrieval (#83) * [MOB-3176] Cancellation SLA to booking (#84) * New models * Update tripinfo object * Update JSON * Remove package.resolved file * Update tests * Ignore this (#85) * {MOB-3181] Quotes cancellation SLA (#86) * Update quote model * Update tests * MOB-3144 - Add decimal formatting to CancellationFeePrice (#87) * Add decimal formatting to CancellationFeePrice * Update to use global const * Remove URL suffix (#88) * Add BrowserInfo to Adyen DropIn Payload (#89) * Bump nokogiri from 1.10.7 to 1.11.1 (#76) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.7 to 1.11.1. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.7...v1.11.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MOB-3205 Add SupplyPartnerID to the AdyenPayments request (#90) * Add SupplyPartnerId field to the payments API * Update tests and add supplyPartnerId * Add Fleet model to be used in Quote model (#91) * Make service cancellation type an enum (#92) * Make service cancellation type an enum * Retain other service cancellation type values. * Bump kramdown from 2.3.0 to 2.3.1 (#93) Bumps [kramdown](https://github.com/gettalong/kramdown) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/gettalong/kramdown/releases) - [Changelog](https://github.com/gettalong/kramdown/blob/master/doc/news.page) - [Commits](https://github.com/gettalong/kramdown/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use the Keychain to store user credentials. (#94) * Add fastlane update command (#95) * Add fastlane update command * Add fastlane update as a separate command * Update Gemfile.lock * [MOB-3216] Release 1.4.0 (#96) * Bump version * Update pod spec (Need this to be published) * Bump nokogiri from 1.11.2 to 1.11.5 (#98) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.2 to 1.11.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.2...v1.11.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Use date data type for dateBooked (#99) * Bump version number to 1.5.0 (#100) * [MOB-3438] login with credentials (#104) * Make first small changes to auth service. * Create auth credentials swift files and update authservice * Init auth credentials interactor * Credentials finally works as public * Almost finished * Swap credentials with authToken * Finish interactor + rename token interactor * Remove requestsender * Test pass * Release 1.5.1 (#106) * versiob bump to 1_5_1-rc1 * updated version to 1_5_1 * changed readme (#108) * MOB-3445 change AuthToken init access level from internal to public (#109) * MOB-3488 Release 1.5.2 (develop) (#110) * Release 1.5.2 * Update marketting project version * MOB-3405 fix coding key for fleet capabilties (#112) Co-authored-by: Anca Feurdean * fix refresh token call headers (#114) * MOB-3528: Release 1.5.3 (develop) (#115) * Release 1.5.3 * test circleci * undo circleci test * Add new error codes (#117) * Add loyalty nonce to booking api (#118) * Modify LoyaltyProgramme to be an Object vs an Array (#120) * Mob xxxx circleci fix (#124) * Update config.yml * Update config.yml * Revert * Avoid deleting the SSH private key * use separate commends * use xlarge resource * use cache for bundle * update xcode version to 12.2.0 * a bit cleanup * revert back to working version * update bundler version * use large resource * use xlarge resource * update xcode version, decrease resource_class to medium to fit our price plan * revert Xcode to 12.0, revert resource_class to xlarge, and change bundler version to 2.2.7 - working UISDK config * try solution proposed by Mikolaj * going back to xcode 12.2 and large resource_class * using medium resource_class * update fastlane * update fastlane take 2 * circleci sanity check * test removing ssh key * reverting last commit * adjust bundler version * test circleci * update to xcode 13 * update fastlane * remove fastline update, run bundle install before installing specific gem * Use xcode 12.5.1 * Minor change Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Diana Petrea * [MOB-3633] Add Loyalty API (#119) * Add endpoints * LoyaltyStatus API Added * Add LoyaltyPoints model * Fix up the API endpoints * LoyaltyStatus Interactor * Edit APIEndpoint again * Update LoyaltyService * LoyaltyBurn interactor * Loyaltyearn Interactor * Update LoyaltyService * PreAuth interactor * Update service * Add mocks * Preauth mock * Add tests * Add remaining tests * Update PreAuth interactor * Remove Integration Tests (Not ready) * Fix loyaltyservice for preauth * Fix tests * Make requested changes to LoyaltyPreAuth * points to burnPoints * Guard currency * Fix broken test * Add new status test to make sure request is setup correctly * Fix loyaltyStatus? * cicleci test commit * test circleci commit * Add errors * Mob 3656 (#123) * get and persist loyalty status after payment provider response * minor change * add get current status method to loyalty service * refresh current loyalty status * add unit tests * Fix for paymemt provider model * resolve PR comments Co-authored-by: Mostafa Hadian Co-authored-by: Diana Petrea Co-authored-by: Mostafa Hadian Co-authored-by: dianakarh <86302636+dianakarh@users.noreply.github.com> * Mob 3650 (#125) * update loyalty nonce model * fix unit test * fix loyalty preauth interactor * redo execute implementation in loyalty preauth interactor * Mob 3785 (#126) * add slug to KarhooError * use slug, add new error type * add new errot type * bump version (#127) * MOB-3819 add shopper locale to adyen payment request (#129) * add shopper locale to adyen payment request * add minor tweak * Feature/MOB-3883 add basic analytics events to track the conversion steps (#130) * New event names added according to requirements in https://karhoo.atlassian.net/browse/MOB-3868 * cleanup * cleanup * Renaming * bump version Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: Mostafa Hadian Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> Co-authored-by: cosminBadulescu Co-authored-by: ancafeurdean09 <30659315+ancafeurdean09@users.noreply.github.com> Co-authored-by: Anca Feurdean Co-authored-by: Aleksander Wędrychowski <97090287+AleksanderWedrychowskiKarhoo@users.noreply.github.com> * Feature/MOB-4020 update network sdk to support versioning of payment related calls (#136) * Add `version` parameter to PaymentProvider model * Payment API Version added to payments interactors and endpints * force v68 api version for debug * Payment version added to path if differs from v51 * version path component fix * version string calculation improved * Test v68 version * update tests * version bump 1.5.5 => 1.5.6 * Change version number * MOB-4021 cherry pick * version bump 1.6.0 * version bump in Podspec * Feature/MOB-4020 update network sdk to support versioning of payment … (#139) * Feature/MOB-4020 update network sdk to support versioning of payment related calls (#136) * Add `version` parameter to PaymentProvider model * Payment API Version added to payments interactors and endpints * force v68 api version for debug * Payment version added to path if differs from v51 * version path component fix * version string calculation improved * Test v68 version * update tests * version bump 1.5.5 => 1.5.6 * Change version number * MOB-4021 cherry pick * version bump 1.6.0 * version bump in Podspec Co-authored-by: Aleksander Wędrychowski Co-authored-by: Bartłomiej Sopala * Feature/MOB-4020 update network sdk to support versioning of payment related calls (#142) * Add `version` parameter to PaymentProvider model * Payment API Version added to payments interactors and endpints * force v68 api version for debug * Payment version added to path if differs from v51 * version path component fix * version string calculation improved * Test v68 version * update tests * version bump 1.5.5 => 1.5.6 * Change version number * MOB-4021 cherry pick * SPM updated * fetching payment provider api version fixed * Unit tests update * SPM update reverted due to CI issue * remove `version` parameter form PaymentProvider model * bumb version 1.6.0 => 1.6.1 * REvert SPM changes Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: Mostafa Hadian Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> Co-authored-by: cosminBadulescu Co-authored-by: dianakarh <86302636+dianakarh@users.noreply.github.com> Co-authored-by: ancafeurdean09 <30659315+ancafeurdean09@users.noreply.github.com> Co-authored-by: Anca Feurdean Co-authored-by: Bartłomiej Sopala * Bump nokogiri from 1.11.5 to 1.13.4 (#138) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.5 to 1.13.4. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/v1.13.4/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.5...v1.13.4) --- updated-dependencies: - dependency-name: nokogiri dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump cocoapods-downloader from 1.4.0 to 1.6.3 (#135) Bumps [cocoapods-downloader](https://github.com/CocoaPods/cocoapods-downloader) from 1.4.0 to 1.6.3. - [Release notes](https://github.com/CocoaPods/cocoapods-downloader/releases) - [Changelog](https://github.com/CocoaPods/cocoapods-downloader/blob/master/CHANGELOG.md) - [Commits](https://github.com/CocoaPods/cocoapods-downloader/compare/1.4.0...1.6.3) --- updated-dependencies: - dependency-name: cocoapods-downloader dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Feature/mob 4090 make nsdk psp agnostic (#146) * remove braintree psp condition from authentication call * remove if braitree condition * Unit tests updated Co-authored-by: Aleksander Wędrychowski * revert nokogiri version to 1.11.5 (#148) * bump version to 1.6.2 (#149) * Feature/MOB-4198 quote list use vehicle images from be (#155) * VehicleRules configuration fetching * VehivlesRules model updated * temporary set some methods as public so UISDK can debug * Do not add headers to vehicle rules api call * Debug changes reverted * cleanup * remove assert * - VehicleRules -> VehicleImageRules - revert version bump * Small formatting change * Add `isDefault` property to VehicleImageRule model * RuleType enum introduced to VehicleImageRule model * Vehicle image rule type description change * Feature/mob 4160 extract correlation - APPROACH A (#153) * add analytics constants for payment and loyalty * add correlation id to Result * add correlationId in handler * remove enum tuple warnings * update Keys * add missing loyalty key * pr request changes * revert Package.resolved to previous version * update keys * remove unnecessary notes * update user nonce only for Braintree (#154) * update user nonce only for Braintree * Create Payment provider updater * fix tests * fix formatting * pr review updates * try to reset Packge.resolved to previous version * remove default implementation for payment and nonce provider * change way of initialing self.paymentProviderUpdateHandler * add loyaltyPaymerntRequest to paymentProviderUpdateHandler initislizers * MOB-4219 release 1.6.3 (DEVELOP) (#157) * Release preparations * Set KarhooPaymentProviderUpdateHandler privacy protection to default * Bumb sdk version for podspec and readme * Bump tzinfo from 1.2.9 to 1.2.10 (#156) Bumps [tzinfo](https://github.com/tzinfo/tzinfo) from 1.2.9 to 1.2.10. - [Release notes](https://github.com/tzinfo/tzinfo/releases) - [Changelog](https://github.com/tzinfo/tzinfo/blob/master/CHANGES.md) - [Commits](https://github.com/tzinfo/tzinfo/compare/v1.2.9...v1.2.10) --- updated-dependencies: - dependency-name: tzinfo dependency-type: indirect ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump jmespath from 1.4.0 to 1.6.1 (#151) Bumps [jmespath](https://github.com/trevorrowe/jmespath.rb) from 1.4.0 to 1.6.1. - [Release notes](https://github.com/trevorrowe/jmespath.rb/releases) - [Changelog](https://github.com/jmespath/jmespath.rb/blob/main/CHANGELOG.md) - [Commits](https://github.com/trevorrowe/jmespath.rb/compare/v1.4.0...v1.6.1) --- updated-dependencies: - dependency-name: jmespath dependency-type: indirect ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump git from 1.8.1 to 1.11.0 (#145) Bumps [git](https://github.com/ruby-git/ruby-git) from 1.8.1 to 1.11.0. - [Release notes](https://github.com/ruby-git/ruby-git/releases) - [Changelog](https://github.com/ruby-git/ruby-git/blob/master/CHANGELOG.md) - [Commits](https://github.com/ruby-git/ruby-git/compare/v1.8.1...v1.11.0) --- updated-dependencies: - dependency-name: git dependency-type: indirect ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Feature/MOB-4312 change deployment target os to 13 (#159) * Deployment target set to 13 * Not needed IDE runtime marking removed due to changing deployment target * Updated config.yml * Updated config.yml * Feature/mob 4132 refresh token add a way for dp to provide new token (#161) * Get new token from DP closure added to KarhooSDKConfiguration. Debug setup. * Debug setup removed * Renaming, change new credentials providing method to async callback * tests adjustments * Error completion call added to guard statement * Use new token request flow for empty refreshToken (not nil) * Rename error case * remove unused struct RefreshToken * fix tests * remove Credentials from requestNewAuthenticationCredentials callback * rename variable to more descriptive * Unit test updated * Rremove default implementation for `requestNewAuthenticationCredentials` * Updated config.yml * renaming to requestSDKAuthentication * Updated config.yml * renaming to requireSDKAuthentication * debug refresh expiration - 10 secs * add checking refresh token validity * Adjust Refresh Token interactor, to handle additional border cases * remove debug values * Unit tests adjustments to new refresh token flow (in progress) * Refresh token test update Co-authored-by: Bartlomiej Sopala * Feature/mob 4126 proactively refresh token (#162) * proactive refresh token mechanizm intorduced * refresh timer ready * remove MaxTimeIntervalToRefreshToken consstant and replace it with refreshBuffer (5 mins) * Exteral auth request invalidation timer * typo fix * Updated config.yml * Buffet set depending on auth tocken expirre date * Feature/mob 4135 create login token refresh based on queue (#163) * proactive refresh token mechanizm intorduced * refresh timer ready * remove MaxTimeIntervalToRefreshToken consstant and replace it with refreshBuffer (5 mins) * Exteral auth request invalidation timer * typo fix * Updated config.yml * Buffet set depending on auth tocken expirre date * add token request completions array, so multiple API requests can wait for token refresh to be done. Once the process is completed, all completions are triggered using the same result - success or result. * Unit tests updated test multiple completion handling 2 * change variable to constant * Feature/mob 4126 proactively refresh token (#164) * proactive refresh token mechanizm intorduced * refresh timer ready * remove MaxTimeIntervalToRefreshToken consstant and replace it with refreshBuffer (5 mins) * Exteral auth request invalidation timer * typo fix * Updated config.yml * Buffet set depending on auth tocken expirre date * Change minimal refresh token buffer * Refresh token unit tests update * Additional refresh buffer changes. Remove default 5 mins value * Feature/mob 4126 proactively refresh token (#166) * proactive refresh token mechanizm intorduced * refresh timer ready * remove MaxTimeIntervalToRefreshToken consstant and replace it with refreshBuffer (5 mins) * Exteral auth request invalidation timer * typo fix * Updated config.yml * Buffet set depending on auth tocken expirre date * Change minimal refresh token buffer * Refresh token unit tests update * Additional refresh buffer changes. Remove default 5 mins value * limit external auth call to only one at a time * correct refresh_token expiration calculations * fix some deprecated warnings and formatting Co-authored-by: Diana Petrea Co-authored-by: dianakarh <86302636+dianakarh@users.noreply.github.com> * fix read/store operations in UserDataStore (#167) * bump version * update platform version * cleanup get random credentials method * cleanup default value for the refresh expires in field Signed-off-by: dependabot[bot] Co-authored-by: EdwardW2 <44901854+EdwardW2@users.noreply.github.com> Co-authored-by: Jo Santa Maria <60882714+jsm20@users.noreply.github.com> Co-authored-by: Mostafa Hadian Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cornelkar <61707821+cornelkar@users.noreply.github.com> Co-authored-by: cosminBadulescu Co-authored-by: ancafeurdean09 <30659315+ancafeurdean09@users.noreply.github.com> Co-authored-by: Anca Feurdean Co-authored-by: Aleksander Wędrychowski <97090287+AleksanderWedrychowskiKarhoo@users.noreply.github.com> Co-authored-by: Bartłomiej Sopala <97114085+BartlomiejSopalaKarhoo@users.noreply.github.com> Co-authored-by: Aleksander Wędrychowski Co-authored-by: Bartłomiej Sopala --- .circleci/config.yml | 13 +- Client/AppDelegate.swift | 3 + Client/SceneDelegate.swift | 1 - Gemfile.lock | 6 +- KarhooSDK.podspec | 4 +- KarhooSDK.xcodeproj/project.pbxproj | 59 ++++-- .../xcshareddata/swiftpm/Package.resolved | 32 ++++ .../Api/DataStore/User/Credentials.swift | 39 +++- .../DataStore/User/CredentialsStoreKeys.swift | 1 + .../Api/DataStore/User/UserDataStore.swift | 18 +- KarhooSDK/Api/Response/AuthToken.swift | 17 +- KarhooSDK/Api/Response/RefreshToken.swift | 26 --- .../KarhooSDKConfiguration.swift | 4 +- .../KarhooRefreshTokenInteractor.swift | 173 ++++++++++++++---- .../KarhooTokenRefreshNeedWorker.swift | 111 +++++++++++ .../Interactor/RefreshTokenInteractor.swift | 3 + .../RefreshTokenError.swift | 4 +- .../TokenRefreshingHttpClient.swift | 6 +- .../KarhooAuthLoginWithTokenInteractor.swift | 14 +- .../Mocks/Api/Response/RefreshTokenMock.swift | 44 ----- .../Mocks/Networking/MockSDKConfig.swift | 6 + KarhooSDKTests/Mocks/ObjectTestFactory.swift | 17 +- .../Utils/MockTokenRefreshNeedWorker.swift | 33 ++++ .../Api/DataStore/CredentialsSpec.swift | 29 +-- .../Networking/DefaultAuthTokenSpec.swift | 9 +- .../KarhooRefreshTokenInteractorSpec.swift | 166 +++++++++++------ Package.swift | 2 +- README.md | 4 +- 28 files changed, 601 insertions(+), 243 deletions(-) create mode 100644 KarhooSDK.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved delete mode 100644 KarhooSDK/Api/Response/RefreshToken.swift create mode 100644 KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/Interactor/KarhooTokenRefreshNeedWorker.swift delete mode 100644 KarhooSDKTests/Mocks/Api/Response/RefreshTokenMock.swift create mode 100644 KarhooSDKTests/Mocks/Utils/MockTokenRefreshNeedWorker.swift diff --git a/.circleci/config.yml b/.circleci/config.yml index e38747d5..bd79380d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2.1 jobs: build-and-test: macos: - xcode: 12.5.1 + xcode: 14.0 working_directory: /Users/distiller/project/KarhooSDK.xcodeproj environment: FL_OUTPUT_DIR: output @@ -18,9 +18,7 @@ jobs: - run: name: Set Ruby Version command: | - echo 'chruby ruby-2.7.2' >> ~/.bash_profile - bundle install - gem install bundler:2.2.15 + sudo gem install bundler - restore_cache: name: Restore cache - Load installed gems from cache if possible - keys: @@ -52,7 +50,10 @@ jobs: echo "func environment() -> KarhooEnvironment {" >> Client/Keys.swift echo "return .custom(environment: .init(host: \"$ADYEN_STG_HOST\", authHost: \"$ADYEN_STG_AUTHHOST\", guestHost: \"$ADYEN_STG_GUESTHOST\")) }" >> Client/Keys.swift echo "func authenticationMethod() -> AuthenticationMethod {" >> Client/Keys.swift - echo "return .karhooUser }}" >> Client/Keys.swift + echo "return .karhooUser }" >> Client/Keys.swift + echo "func requireSDKAuthentication(callback: @escaping () -> Void) {" >> Client/Keys.swift + echo "callback() }" >> Client/Keys.swift + echo "}" >> Client/Keys.swift - run: name: fastlane command: | @@ -67,7 +68,7 @@ jobs: adhoc: macos: - xcode: 12.5.1 + xcode: 13.4.1 environment: FL_OUTPUT_DIR: output FASTLANE_LANE: adhoc diff --git a/Client/AppDelegate.swift b/Client/AppDelegate.swift index 1c9945f5..84ec84ed 100644 --- a/Client/AppDelegate.swift +++ b/Client/AppDelegate.swift @@ -26,6 +26,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } struct SDKConfig: KarhooSDKConfiguration { + func requireSDKAuthentication(callback: @escaping () -> Void) { + callback() + } func environment() -> KarhooEnvironment { return .sandbox diff --git a/Client/SceneDelegate.swift b/Client/SceneDelegate.swift index 9d5d611e..c047660e 100644 --- a/Client/SceneDelegate.swift +++ b/Client/SceneDelegate.swift @@ -11,7 +11,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - @available(iOS 13.0, *) func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. diff --git a/Gemfile.lock b/Gemfile.lock index 06ce207b..b5fa1c74 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -175,7 +175,7 @@ GEM fourflusher (2.3.1) fuzzy_match (2.0.4) gh_inspector (1.1.3) - git (1.8.1) + git (1.11.0) rchardet (~> 1.8) google-api-client (0.38.0) addressable (~> 2.5, >= 2.5.1) @@ -226,7 +226,7 @@ GEM httpclient (2.8.3) i18n (1.8.10) concurrent-ruby (~> 1.0) - jmespath (1.4.0) + jmespath (1.6.1) json (2.5.1) jwt (2.2.2) kramdown (2.3.1) @@ -302,7 +302,7 @@ GEM tty-cursor (~> 0.7) typhoeus (1.4.0) ethon (>= 0.9.0) - tzinfo (1.2.9) + tzinfo (1.2.10) thread_safe (~> 0.1) uber (0.1.0) unf (0.1.4) diff --git a/KarhooSDK.podspec b/KarhooSDK.podspec index 13f3482c..9aac8b73 100644 --- a/KarhooSDK.podspec +++ b/KarhooSDK.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "KarhooSDK" - s.version = "1.6.3" + s.version = "1.7.0" s.summary = "Karhoo Network SDK" s.homepage = "https://developer.karhoo.com/docs/build-apps-using-sdks" s.license = 'BSD 2-Clause' @@ -9,7 +9,7 @@ Pod::Spec.new do |s| s.source = { :git => "https://github.com/karhoo/karhoo-ios-sdk.git", :tag => s.version } s.source_files = 'KarhooSDK/**/*.swift' - s.platform = :ios, '10.0' + s.platform = :ios, '13.0' s.requires_arc = true s.swift_version = '5.0' diff --git a/KarhooSDK.xcodeproj/project.pbxproj b/KarhooSDK.xcodeproj/project.pbxproj index c0c204a2..ba9d928a 100644 --- a/KarhooSDK.xcodeproj/project.pbxproj +++ b/KarhooSDK.xcodeproj/project.pbxproj @@ -108,9 +108,7 @@ 09A9B29A2405901B00823FB0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 09A9B2982405901B00823FB0 /* LaunchScreen.storyboard */; }; 09A9B2A42405916400823FB0 /* KarhooSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4387A6411E3BAF6D0024FD55 /* KarhooSDK.framework */; }; 09ACCE50207BBB5E0057B0CC /* QuoteListIdRequestPayload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09ACCE4F207BBB5E0057B0CC /* QuoteListIdRequestPayload.swift */; }; - 09AF9AA920D174150046D725 /* RefreshToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09AF9AA820D174150046D725 /* RefreshToken.swift */; }; 09AF9AAB20D1751D0046D725 /* RefreshTokenRequestPayload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09AF9AAA20D1751D0046D725 /* RefreshTokenRequestPayload.swift */; }; - 09AF9AAD20D17B7D0046D725 /* RefreshTokenMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09AF9AAC20D17B7D0046D725 /* RefreshTokenMock.swift */; }; 09B204B121412C3200063632 /* KarhooSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4387A6411E3BAF6D0024FD55 /* KarhooSDK.framework */; }; 09B204BC2141366C00063632 /* InvalidData.json in Resources */ = {isa = PBXBuildFile; fileRef = 09B204BB2141366C00063632 /* InvalidData.json */; }; 09BDE053212F128800798330 /* MockLocationInfoInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BDE052212F128700798330 /* MockLocationInfoInteractor.swift */; }; @@ -317,6 +315,8 @@ 43F939A41F3C85A300914E18 /* KarhooEnvironmentDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F9399B1F3C85A300914E18 /* KarhooEnvironmentDetails.swift */; }; 43F939A51F3C85A300914E18 /* URLSessionSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F9399C1F3C85A300914E18 /* URLSessionSender.swift */; }; 43F939B61F3CD33200914E18 /* JsonHttpRequestBuilderSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F939B11F3CD33200914E18 /* JsonHttpRequestBuilderSpec.swift */; }; + 5128E02328ED8D9E005224F5 /* KarhooTokenRefreshNeedWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5128E02228ED8D9E005224F5 /* KarhooTokenRefreshNeedWorker.swift */; }; + 5128E02628ED8F06005224F5 /* MockTokenRefreshNeedWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5128E02528ED8F06005224F5 /* MockTokenRefreshNeedWorker.swift */; }; 517C6CCF2886BF3C00EA164C /* VehicleImageRules.swift in Sources */ = {isa = PBXBuildFile; fileRef = 517C6CCE2886BF3C00EA164C /* VehicleImageRules.swift */; }; 517C6CD12886BF7500EA164C /* KarhooVehicleRulesInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 517C6CD02886BF7500EA164C /* KarhooVehicleRulesInteractor.swift */; }; 517C6CD32886BF9100EA164C /* VehicleRulesInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 517C6CD22886BF9100EA164C /* VehicleRulesInteractor.swift */; }; @@ -367,7 +367,6 @@ 5CDD26D624BF502400436F01 /* QuoteRequestPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CDD26D524BF502400436F01 /* QuoteRequestPoint.swift */; }; 5D4800F516E293EA22604A94 /* AdyenClientKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D480980D478A06806E93B05 /* AdyenClientKey.swift */; }; 5D4806EC519AFE12A3209A98 /* KarhooAdyenClientKeyInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D480E1AF062F866A3A657C2 /* KarhooAdyenClientKeyInteractor.swift */; }; - 5D480A8C78D7C81F253BC00C /* Keys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D480EA12F7236874F815CF5 /* Keys.swift */; }; 5D480AB4657DBF0AB356D2C6 /* AdyenClientKeyInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D48053897A118D887CD6495 /* AdyenClientKeyInteractor.swift */; }; 6BB9405227512AB600478ABD /* LoyaltyUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BB9405127512AB600478ABD /* LoyaltyUtils.swift */; }; 6F11A47D25713BC2003CFE15 /* NetPrice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F11A47C25713BC2003CFE15 /* NetPrice.swift */; }; @@ -554,6 +553,13 @@ remoteGlobalIDString = 4387A6401E3BAF6D0024FD55; remoteInfo = KarhooSDK; }; + 5124B86528D351F600031CF5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4387A6381E3BAF6D0024FD55 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 09A9B28A2405901900823FB0; + remoteInfo = Client; + }; 5CDD26D124BE560C00436F01 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4387A6381E3BAF6D0024FD55 /* Project object */; @@ -667,9 +673,7 @@ 09A9B2992405901B00823FB0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 09A9B29B2405901B00823FB0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 09ACCE4F207BBB5E0057B0CC /* QuoteListIdRequestPayload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuoteListIdRequestPayload.swift; sourceTree = ""; }; - 09AF9AA820D174150046D725 /* RefreshToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshToken.swift; sourceTree = ""; }; 09AF9AAA20D1751D0046D725 /* RefreshTokenRequestPayload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshTokenRequestPayload.swift; sourceTree = ""; }; - 09AF9AAC20D17B7D0046D725 /* RefreshTokenMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshTokenMock.swift; sourceTree = ""; }; 09B204AC21412C3100063632 /* KarhooSDKIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KarhooSDKIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 09B204B021412C3200063632 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 09B204BB2141366C00063632 /* InvalidData.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = InvalidData.json; sourceTree = ""; }; @@ -883,6 +887,8 @@ 43F9399C1F3C85A300914E18 /* URLSessionSender.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLSessionSender.swift; sourceTree = ""; }; 43F939B01F3CD33200914E18 /* JsonHttpClientSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JsonHttpClientSpec.swift; sourceTree = ""; }; 43F939B11F3CD33200914E18 /* JsonHttpRequestBuilderSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JsonHttpRequestBuilderSpec.swift; sourceTree = ""; }; + 5128E02228ED8D9E005224F5 /* KarhooTokenRefreshNeedWorker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KarhooTokenRefreshNeedWorker.swift; sourceTree = ""; }; + 5128E02528ED8F06005224F5 /* MockTokenRefreshNeedWorker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockTokenRefreshNeedWorker.swift; sourceTree = ""; }; 517C6CCE2886BF3C00EA164C /* VehicleImageRules.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleImageRules.swift; sourceTree = ""; }; 517C6CD02886BF7500EA164C /* KarhooVehicleRulesInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KarhooVehicleRulesInteractor.swift; sourceTree = ""; }; 517C6CD22886BF9100EA164C /* VehicleRulesInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleRulesInteractor.swift; sourceTree = ""; }; @@ -928,7 +934,6 @@ 5D48053897A118D887CD6495 /* AdyenClientKeyInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdyenClientKeyInteractor.swift; sourceTree = ""; }; 5D480980D478A06806E93B05 /* AdyenClientKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdyenClientKey.swift; sourceTree = ""; }; 5D480E1AF062F866A3A657C2 /* KarhooAdyenClientKeyInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KarhooAdyenClientKeyInteractor.swift; sourceTree = ""; }; - 5D480EA12F7236874F815CF5 /* Keys.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Keys.swift; sourceTree = ""; }; 6BB9405127512AB600478ABD /* LoyaltyUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoyaltyUtils.swift; sourceTree = ""; }; 6F11A47C25713BC2003CFE15 /* NetPrice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetPrice.swift; sourceTree = ""; }; 6F11A48625714549003CFE15 /* FleetRating.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FleetRating.swift; sourceTree = ""; }; @@ -1473,7 +1478,6 @@ 09A9B2962405901B00823FB0 /* Assets.xcassets */, 09A9B2982405901B00823FB0 /* LaunchScreen.storyboard */, 09A9B29B2405901B00823FB0 /* Info.plist */, - 5D480EA12F7236874F815CF5 /* Keys.swift */, 7B28E0092886891300F6FDAE /* Keys.swift */, ); path = Client; @@ -1568,7 +1572,6 @@ 231652D925BADEEA003C449B /* QuoteStatus.swift */, 313DC2EF20221FCE00D9DD1B /* QuoteType.swift */, 5C49848F24C0A89F00F646A4 /* QuoteVehicle.swift */, - 09AF9AA820D174150046D725 /* RefreshToken.swift */, 2377497325DD489D00633BF5 /* ServiceAgreements.swift */, 2377496D25DD489000633BF5 /* ServiceCancellation.swift */, A10F03D5260CA199005743F4 /* ServiceCancellationType.swift */, @@ -1644,6 +1647,7 @@ children = ( 31904CD31FFFC04400BA7402 /* KarhooRefreshTokenInteractor.swift */, 0900D34820D2B17B0082D1E8 /* RefreshTokenInteractor.swift */, + 5128E02228ED8D9E005224F5 /* KarhooTokenRefreshNeedWorker.swift */, ); path = Interactor; sourceTree = ""; @@ -2387,6 +2391,7 @@ FC2D95712113612300201BDB /* Error.swift */, BAA0A4B5934264D356A0E7FA /* Api */, 0981F6C520CEC26000BF7FB5 /* Networking */, + 5128E02428ED8EF0005224F5 /* Utils */, 274213A546BD3548026ADD7A /* Service */, ); path = Mocks; @@ -2623,6 +2628,14 @@ path = Trip; sourceTree = ""; }; + 5128E02428ED8EF0005224F5 /* Utils */ = { + isa = PBXGroup; + children = ( + 5128E02528ED8F06005224F5 /* MockTokenRefreshNeedWorker.swift */, + ); + path = Utils; + sourceTree = ""; + }; 51C3FCDA27FE198700273BA2 /* AdyenAPIVersionProvider */ = { isa = PBXGroup; children = ( @@ -3215,7 +3228,6 @@ BAA0A2139A85B9FF7F56BED7 /* PaymentSDKTokenMock.swift */, BAA0ADA5AD439AA7E9B9ED6C /* TripStatusMock.swift */, 27421D16D44DEC18A835BDB0 /* DriverTrackingInfoMock.swift */, - 09AF9AAC20D17B7D0046D725 /* RefreshTokenMock.swift */, 27421D9042A4F39DF7D69941 /* QuoteMock.swift */, 099AF2FA20F8BDF000A2AA57 /* TripInfoMock.swift */, 274215B1B4ADECE9D9CE2EA2 /* QuoteListMock.swift */, @@ -3371,6 +3383,7 @@ ); dependencies = ( 09B204B321412C3200063632 /* PBXTargetDependency */, + 5124B86628D351F600031CF5 /* PBXTargetDependency */, ); name = KarhooSDKIntegrationTests; packageProductDependencies = ( @@ -3443,6 +3456,7 @@ DevelopmentTeam = U7U4Q7YGDH; LastSwiftMigration = 1020; ProvisioningStyle = Automatic; + TestTargetID = 09A9B28A2405901900823FB0; }; 4387A6401E3BAF6D0024FD55 = { CreatedOnToolsVersion = 8.2.1; @@ -3455,6 +3469,7 @@ DevelopmentTeam = U7U4Q7YGDH; LastSwiftMigration = 1020; ProvisioningStyle = Automatic; + TestTargetID = 09A9B28A2405901900823FB0; }; }; }; @@ -3566,7 +3581,6 @@ 40FBF609240FBB2E007F6A54 /* AuthRequestsTesterViewController.swift in Sources */, 09A9B28E2405901900823FB0 /* AppDelegate.swift in Sources */, 09A9B2902405901900823FB0 /* SceneDelegate.swift in Sources */, - 5D480A8C78D7C81F253BC00C /* Keys.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3627,7 +3641,6 @@ FC861B5E2110B7C0004CC47A /* HTTPError.swift in Sources */, 142CB39424DC30840065149C /* KarhooPaymentProviderInteractor.swift in Sources */, 147B889D24E3F515003F78B8 /* AdyenPaymentMethodsInteractor.swift in Sources */, - 09AF9AA920D174150046D725 /* RefreshToken.swift in Sources */, 5C224EB1223DCD2000C1CFCE /* KarhooAddPaymentDetailsInteractor.swift in Sources */, 43EF91691EE93DF6006ECB75 /* KarhooTripService.swift in Sources */, 312B1AAE1FA0982800BB27CF /* NetworkConnectionTypeProvider.swift in Sources */, @@ -3649,6 +3662,7 @@ 43F939A31F3C85A300914E18 /* JsonHttpRequestBuilder.swift in Sources */, 6F69F34B255A7FFD00F8DA05 /* KarhooQuoteCoverageInteractor.swift in Sources */, 43F939A11F3C85A300914E18 /* Json.swift in Sources */, + 5128E02328ED8D9E005224F5 /* KarhooTokenRefreshNeedWorker.swift in Sources */, 097BF2B72358710400BBE418 /* KarhooSDKConfiguration.swift in Sources */, 237E0C59234782B400798AA0 /* KarhooFareService.swift in Sources */, 231636622747BFF60082EE9B /* LoyaltyPreAuth.swift in Sources */, @@ -3975,6 +3989,7 @@ 0981F6CF20CFDA9B00BF7FB5 /* KarhooRequestSenderSpec.swift in Sources */, 094C1F7F20B2C956001FFE7F /* MockNetworkDateFormatter.swift in Sources */, 2316363F274669CB0082EE9B /* MockLoyaltyStatusInteractor.swift in Sources */, + 5128E02628ED8F06005224F5 /* MockTokenRefreshNeedWorker.swift in Sources */, 0970BA802114671A0015A170 /* KarhooObservableSpec.swift in Sources */, 090670E820A4787600CAFA86 /* KarhooPaymentSDKTokenInteractorSpec.swift in Sources */, FCD32FEF20DAA33A0044BB64 /* KarhooTripsListInteractorSpec.swift in Sources */, @@ -4048,7 +4063,6 @@ 0970BA8C21149FC60015A170 /* KarhooPollableExecutorSpec.swift in Sources */, 0970BA822114685B0015A170 /* MockKarhooCodableModel.swift in Sources */, 6FD94A24258BB46300B21B8B /* KarhooLoyaltyServiceSpec.swift in Sources */, - 09AF9AAD20D17B7D0046D725 /* RefreshTokenMock.swift in Sources */, 0981F6CD20CEEB1000BF7FB5 /* AuthTokenMock.swift in Sources */, FC8F475321555025007841FB /* MockObserverBroadcaster.swift in Sources */, 274211D129AC87080586E523 /* DriverTrackingInfoMock.swift in Sources */, @@ -4080,6 +4094,11 @@ target = 4387A6401E3BAF6D0024FD55 /* KarhooSDK */; targetProxy = 4387A64C1E3BAF6D0024FD55 /* PBXContainerItemProxy */; }; + 5124B86628D351F600031CF5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 09A9B28A2405901900823FB0 /* Client */; + targetProxy = 5124B86528D351F600031CF5 /* PBXContainerItemProxy */; + }; 5CDD26D224BE560C00436F01 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 09A9B28A2405901900823FB0 /* Client */; @@ -4178,6 +4197,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Client.app/Client"; }; name = Debug; }; @@ -4209,6 +4229,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Client.app/Client"; }; name = Release; }; @@ -4346,7 +4367,7 @@ CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 29; + CURRENT_PROJECT_VERSION = 30; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = U7U4Q7YGDH; DYLIB_COMPATIBILITY_VERSION = 1; @@ -4364,13 +4385,13 @@ ); INFOPLIST_FILE = KarhooSDK/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.6.3; + MARKETING_VERSION = 1.7.0; MODULEMAP_PRIVATE_FILE = ""; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.karhoo.KarhooSDK; @@ -4391,7 +4412,7 @@ CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 29; + CURRENT_PROJECT_VERSION = 30; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = U7U4Q7YGDH; DYLIB_COMPATIBILITY_VERSION = 1; @@ -4409,13 +4430,13 @@ ); INFOPLIST_FILE = KarhooSDK/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.6.3; + MARKETING_VERSION = 1.7.0; MODULEMAP_PRIVATE_FILE = ""; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.karhoo.KarhooSDK; @@ -4456,6 +4477,7 @@ SWIFT_INCLUDE_PATHS = "$(SRCROOT)/KarhooSDK/Api/Networking/GRPC/"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Client.app/Client"; }; name = Debug; }; @@ -4488,6 +4510,7 @@ SWIFT_INCLUDE_PATHS = "$(SRCROOT)/KarhooSDK/Api/Networking/GRPC/"; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Client.app/Client"; }; name = Release; }; diff --git a/KarhooSDK.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/KarhooSDK.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 00000000..9bfc1c60 --- /dev/null +++ b/KarhooSDK.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,32 @@ +{ + "pins" : [ + { + "identity" : "keychain-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/evgenyneu/keychain-swift.git", + "state" : { + "revision" : "96fb84f45a96630e7583903bd7e08cf095c7a7ef", + "version" : "19.0.0" + } + }, + { + "identity" : "ohhttpstubs", + "kind" : "remoteSourceControl", + "location" : "https://github.com/AliSoftware/OHHTTPStubs", + "state" : { + "revision" : "e92b5a5746ef16add2a1424f1fc19529d9a75cde", + "version" : "9.0.0" + } + }, + { + "identity" : "reachability.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ashleymills/Reachability.swift", + "state" : { + "revision" : "98e968e7b6c1318fb61df23e347bc319761e8acb", + "version" : "5.0.0" + } + } + ], + "version" : 2 +} diff --git a/KarhooSDK/Api/DataStore/User/Credentials.swift b/KarhooSDK/Api/DataStore/User/Credentials.swift index 988b735d..17e83bbf 100644 --- a/KarhooSDK/Api/DataStore/User/Credentials.swift +++ b/KarhooSDK/Api/DataStore/User/Credentials.swift @@ -8,21 +8,46 @@ import Foundation -struct Credentials { +public struct Credentials { let accessToken: String let expiryDate: Date? let refreshToken: String? - - init(accessToken: String, expiryDate: Date?, refreshToken: String?) { + let refreshTokenExpiryDate: Date? + + init( + accessToken: String, + expiryDate: Date?, + refreshToken: String?, + refreshTokenExpiryDate: Date? + ) { self.accessToken = accessToken self.expiryDate = expiryDate self.refreshToken = refreshToken + self.refreshTokenExpiryDate = refreshTokenExpiryDate } - init(accessToken: String, expiresIn: TimeInterval, refreshToken: String?) { + init( + accessToken: String, + expiresIn: TimeInterval, + refreshToken: String?, + refreshTokenExpiresIn: TimeInterval? + ) { let expiryDate = Date().addingTimeInterval(Double(expiresIn)) - self.init(accessToken: accessToken, - expiryDate: expiryDate, - refreshToken: refreshToken) + let refreshTokenExpiryDate = refreshTokenExpiresIn.map { Date().addingTimeInterval(Double($0)) } + self.init( + accessToken: accessToken, + expiryDate: expiryDate, + refreshToken: refreshToken, + refreshTokenExpiryDate: refreshTokenExpiryDate + ) + } + + func toAuthToken() -> AuthToken { + AuthToken( + accessToken: accessToken, + expiresIn: Int(expiryDate?.timeIntervalSinceNow ?? 0), + refreshToken: refreshToken ?? "", + refreshExpiresIn: Int(refreshTokenExpiryDate?.timeIntervalSinceNow ?? 0) + ) } } diff --git a/KarhooSDK/Api/DataStore/User/CredentialsStoreKeys.swift b/KarhooSDK/Api/DataStore/User/CredentialsStoreKeys.swift index e999516a..5fb06680 100644 --- a/KarhooSDK/Api/DataStore/User/CredentialsStoreKeys.swift +++ b/KarhooSDK/Api/DataStore/User/CredentialsStoreKeys.swift @@ -12,4 +12,5 @@ enum CredentialsStoreKeys: String { case accessToken case expiryDate case refreshToken + case refreshTokenExpiryDate } diff --git a/KarhooSDK/Api/DataStore/User/UserDataStore.swift b/KarhooSDK/Api/DataStore/User/UserDataStore.swift index 879cd3ab..b8dd575a 100644 --- a/KarhooSDK/Api/DataStore/User/UserDataStore.swift +++ b/KarhooSDK/Api/DataStore/User/UserDataStore.swift @@ -76,7 +76,17 @@ final class DefaultUserDataStore: UserDataStore { let expiryTimeInterval = TimeInterval(expiryDateString) { expiryDate = Date(timeIntervalSince1970: expiryTimeInterval) } - return Credentials(accessToken: accessToken, expiryDate: expiryDate, refreshToken: refreshToken) + var refreshTokenExpiryDate: Date? + if let refreshTokenExpiryIntervalString = secretStore.readSecret(withKey: CredentialsStoreKeys.refreshTokenExpiryDate.rawValue), + let refreshTokenExpiryTimeInterval = TimeInterval(refreshTokenExpiryIntervalString) { + refreshTokenExpiryDate = Date(timeIntervalSince1970: refreshTokenExpiryTimeInterval) + } + return Credentials( + accessToken: accessToken, + expiryDate: expiryDate, + refreshToken: refreshToken, + refreshTokenExpiryDate: refreshTokenExpiryDate + ) } func set(credentials: Credentials) { @@ -93,6 +103,11 @@ final class DefaultUserDataStore: UserDataStore { } else { secretStore.deleteSecret(withKey: CredentialsStoreKeys.refreshToken.rawValue) } + if let refreshTokenExpiryTimeInterval = credentials.refreshTokenExpiryDate?.timeIntervalSince1970 { + secretStore.saveSecret(String(refreshTokenExpiryTimeInterval), withKey: CredentialsStoreKeys.refreshTokenExpiryDate.rawValue) + } else { + secretStore.deleteSecret(withKey: CredentialsStoreKeys.refreshTokenExpiryDate.rawValue) + } } func setCurrentUser(user: UserInfo, credentials: Credentials) { @@ -151,6 +166,7 @@ final class DefaultUserDataStore: UserDataStore { secretStore.deleteSecret(withKey: CredentialsStoreKeys.accessToken.rawValue) secretStore.deleteSecret(withKey: CredentialsStoreKeys.expiryDate.rawValue) secretStore.deleteSecret(withKey: CredentialsStoreKeys.refreshToken.rawValue) + secretStore.deleteSecret(withKey: CredentialsStoreKeys.refreshTokenExpiryDate.rawValue) broadcastChange() } diff --git a/KarhooSDK/Api/Response/AuthToken.swift b/KarhooSDK/Api/Response/AuthToken.swift index 2254ece4..72f3073b 100644 --- a/KarhooSDK/Api/Response/AuthToken.swift +++ b/KarhooSDK/Api/Response/AuthToken.swift @@ -33,10 +33,10 @@ public struct AuthToken: KarhooCodableModel { public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) - self.accessToken = (try? container.decode(String.self, forKey: .accessToken)) ?? "" - self.expiresIn = (try? container.decode(Int.self, forKey: .expiresIn)) ?? 0 - self.refreshToken = (try? container.decode(String.self, forKey: .refreshToken)) ?? "" - self.refreshExpiresIn = (try? container.decode(Int.self, forKey: .refreshExpiresIn)) ?? 0 + accessToken = (try? container.decode(String.self, forKey: .accessToken)) ?? "" + expiresIn = (try? container.decode(Int.self, forKey: .expiresIn)) ?? 0 + refreshToken = (try? container.decode(String.self, forKey: .refreshToken)) ?? "" + refreshExpiresIn = (try? container.decode(Int.self, forKey: .refreshExpiresIn)) ?? 0 } public func encode(to encoder: Encoder) throws { @@ -48,8 +48,11 @@ public struct AuthToken: KarhooCodableModel { } func toCredentials(withRefreshToken refreshToken: String? = nil) -> Credentials { - return Credentials(accessToken: accessToken, - expiresIn: TimeInterval(expiresIn), - refreshToken: refreshToken ?? self.refreshToken) + Credentials( + accessToken: accessToken, + expiresIn: TimeInterval(expiresIn), + refreshToken: refreshToken ?? self.refreshToken, + refreshTokenExpiresIn: TimeInterval(refreshExpiresIn) + ) } } diff --git a/KarhooSDK/Api/Response/RefreshToken.swift b/KarhooSDK/Api/Response/RefreshToken.swift deleted file mode 100644 index 998fe293..00000000 --- a/KarhooSDK/Api/Response/RefreshToken.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// RefreshToken.swift -// KarhooSDK -// -// -// Copyright © 2020 Karhoo. All rights reserved. -// - -import Foundation - -struct RefreshToken: KarhooCodableModel { - - var accessToken: String - var expiresIn: Int - - enum CodingKeys: String, CodingKey { - case accessToken = "access_token" - case expiresIn = "expires_in" - } - - func toCredentials(withRefreshToken refreshToken: String?) -> Credentials { - return Credentials(accessToken: accessToken, - expiresIn: TimeInterval(expiresIn), - refreshToken: refreshToken) - } -} diff --git a/KarhooSDK/Api/SDKConfiguration/KarhooSDKConfiguration.swift b/KarhooSDK/Api/SDKConfiguration/KarhooSDKConfiguration.swift index 49318780..97f2feeb 100644 --- a/KarhooSDK/Api/SDKConfiguration/KarhooSDKConfiguration.swift +++ b/KarhooSDK/Api/SDKConfiguration/KarhooSDKConfiguration.swift @@ -15,10 +15,12 @@ public protocol KarhooSDKConfiguration { func authenticationMethod() -> AuthenticationMethod func analyticsProvider() -> AnalyticsProvider + + /// Closure to provide new auth credentials for KarhooSDK usage, when the current one expires and there is no refresh token available. To do it just log in your app into the SDK again. + func requireSDKAuthentication(callback: @escaping () -> Void) } public extension KarhooSDKConfiguration { - func analyticsProvider() -> AnalyticsProvider { return DefaultAnalyticsProvider() } diff --git a/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/Interactor/KarhooRefreshTokenInteractor.swift b/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/Interactor/KarhooRefreshTokenInteractor.swift index 8d6a99ae..302079f5 100644 --- a/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/Interactor/KarhooRefreshTokenInteractor.swift +++ b/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/Interactor/KarhooRefreshTokenInteractor.swift @@ -10,39 +10,70 @@ import Foundation final class KarhooRefreshTokenInteractor: RefreshTokenInteractor { + // MARK: - Nested types + + private enum Constants { + static let allowedExternalAuthTimeInterval: TimeInterval = 60 + } + + // MARK: - Properties + + private let tokenValidityWorker: TokenValidityWorker + private var externalAuthInvalidationTimer: Timer? + private var refreshTokenTimer: Timer? private let dataStore: UserDataStore private let refreshTokenRequest: RequestSender - private var callback: ((Result) -> Void)? - init(dataStore: UserDataStore = DefaultUserDataStore(), - refreshTokenRequest: RequestSender = KarhooRequestSender(httpClient: JsonHttpClient.shared)) { + private var isTokenRefreshInProgress = false + private var isExternalAuthRequestInProgress = false + private var completionWaitingForTokenRefresh: [(Result) -> Void] = [] + + // MARK: - Lifecycle + + init( + dataStore: UserDataStore = DefaultUserDataStore(), + refreshTokenRequest: RequestSender = KarhooRequestSender(httpClient: JsonHttpClient.shared), + tokenValidityWorker: TokenValidityWorker = KarhooTokenValidityWorker() + ) { self.dataStore = dataStore self.refreshTokenRequest = refreshTokenRequest + self.tokenValidityWorker = tokenValidityWorker } + deinit { + invalidateRefreshTokenTimer() + invalidateExternalAuthTimer() + } + + // MARK: - Endpoint methods + func tokenNeedsRefreshing() -> Bool { - guard let credentials = dataStore.getCurrentCredentials() else { - return false - } - return tokenNeedsRefreshing(credentials: credentials) + tokenValidityWorker.tokenNeedsRefreshing() } func refreshToken(completion: @escaping (Result) -> Void) { - self.callback = completion + completionWaitingForTokenRefresh.append(completion) + guard isTokenRefreshInProgress == false else { + // Refresh in progress, completion will be evaluated once the process is done. + return + } guard tokenNeedsRefreshing() else { - completion(Result.success(result: false)) + resolveRefreshCompletions(using: .success(result: false)) return } - guard let refreshToken = dataStore.getCurrentCredentials()?.refreshToken else { - completion(Result.failure(error: RefreshTokenError.noRefreshToken)) + guard let refreshToken = dataStore.getCurrentCredentials()?.refreshToken, + refreshToken.isEmpty == false, + refreshTokenNeedsRefreshing() == false + else { + requestExternalAuthentication() return } switch Karhoo.configuration.authenticationMethod() { case .guest: - completion(Result.success(result: false)) + resolveRefreshCompletions(using: .success(result: false)) case .karhooUser: let refreshPayload = RefreshTokenRequestPayload(refreshToken: refreshToken) refreshTokenRequest.requestAndDecode(payload: refreshPayload, @@ -58,6 +89,36 @@ final class KarhooRefreshTokenInteractor: RefreshTokenInteractor { }) } } + + // MARK: - Private methods + + private func requestExternalAuthentication() { + guard isExternalAuthRequestInProgress == false else { + return + } + isExternalAuthRequestInProgress = true + scheduleExtenalAuthInvalidationTimer() + Karhoo.configuration.requireSDKAuthentication { [weak self] in + guard let self = self else { + // Self not accessible so no way to call callback + assertionFailure() + return + } + if let newCredentials = self.dataStore.getCurrentCredentials() { + let newToken = AuthToken( + accessToken: newCredentials.accessToken, + expiresIn: Int(newCredentials.expiryDate?.timeIntervalSinceNow ?? 0), + refreshToken: newCredentials.refreshToken ?? "", + refreshExpiresIn: Int(newCredentials.refreshTokenExpiryDate?.timeIntervalSinceNow ?? 0) + ) + // The request completion will be called inside `handleRefreshRequest` method. + self.handleRefreshRequest(result: .success(result: newToken)) + } else { + self.resolveRefreshCompletions(using: .failure(error: RefreshTokenError.noAccessToken)) + } + self.isExternalAuthRequestInProgress = false + } + } private func authRefreshUrlComponents() -> URLComponents { var urlComponents = URLComponents() @@ -71,16 +132,17 @@ final class KarhooRefreshTokenInteractor: RefreshTokenInteractor { } private func handleRefreshRequest(result: Result) { - if let token = result.successValue() { - guard self.tokenNeedsRefreshing() == true else { - callback?(Result.success(result: false)) - return - } - - self.saveToDataStore(token: token) - - } else if let error = result.errorValue() { - callback?(Result.failure(error: error)) + guard tokenNeedsRefreshing() else { + resolveRefreshCompletions(using: .success(result: false)) + return + } + + switch result { + case .success(result: let token, _): + tokenValidityWorker.saveRefreshBuffer(token: token) + saveToDataStore(token: token) + case .failure: + requestExternalAuthentication() } } @@ -92,22 +154,71 @@ final class KarhooRefreshTokenInteractor: RefreshTokenInteractor { if let user = user { dataStore.setCurrentUser(user: user, credentials: newCredentials) - callback?(Result.success(result: true)) + resolveRefreshCompletions(using: .success(result: true)) + scheduleRefreshTokenTimer() } else { - callback?(Result.failure(error: RefreshTokenError.userAlreadyLoggedOut)) + resolveRefreshCompletions(using: .failure(error: RefreshTokenError.userAlreadyLoggedOut)) } } - private func tokenNeedsRefreshing(credentials: Credentials) -> Bool { - guard let expiryDate = credentials.expiryDate else { - return true + // MARK: Completion resolvment + + private func resolveRefreshCompletions(using result: Result) { + DispatchQueue.main.async { + self.completionWaitingForTokenRefresh.forEach { completion in + completion(result) + } + self.completionWaitingForTokenRefresh = [] } + } + + // MARK: Timers scheduling + + private func scheduleRefreshTokenTimer() { + invalidateRefreshTokenTimer() - let timeToExpiration = expiryDate.timeIntervalSince1970 - Date().timeIntervalSince1970 - return timeToExpiration < Constants.MaxTimeIntervalToRefreshToken + refreshTokenTimer = Timer.scheduledTimer( + withTimeInterval: tokenValidityWorker.timeToRequiredRefresh(), + repeats: false, + block: { [weak self] _ in + self?.refreshToken { result in + print("KarhooRefreshTokenInteractor.proactivelyRefreshToken result: \(result)") + } + } + ) + RunLoop.main.add(refreshTokenTimer!, forMode: .common) + } + + /// Schedule a timer that will return extenal authentition error if given time interval will be reached. This is designed as fallback in case of invalid DPs implementation of the `requireSDKAuthentication` method. + private func scheduleExtenalAuthInvalidationTimer() { + invalidateExternalAuthTimer() + externalAuthInvalidationTimer = Timer.scheduledTimer( + withTimeInterval: Constants.allowedExternalAuthTimeInterval, + repeats: false, + block: { [weak self] _ in + guard let self else { return } + self.isExternalAuthRequestInProgress = false + self.invalidateExternalAuthTimer() + self.resolveRefreshCompletions(using: .failure(error: RefreshTokenError.extenalAuthenticationRequestExpired)) + } + ) + RunLoop.main.add(externalAuthInvalidationTimer!, forMode: .common) + } + + // MARK: - Utils + + private func refreshTokenNeedsRefreshing() -> Bool { + tokenValidityWorker.refreshTokenNeedsRefreshing() } - private struct Constants { - static let MaxTimeIntervalToRefreshToken = TimeInterval(30) // 30 sec + private func invalidateRefreshTokenTimer() { + refreshTokenTimer?.invalidate() + refreshTokenTimer = nil } + + private func invalidateExternalAuthTimer() { + externalAuthInvalidationTimer?.invalidate() + externalAuthInvalidationTimer = nil + } + } diff --git a/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/Interactor/KarhooTokenRefreshNeedWorker.swift b/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/Interactor/KarhooTokenRefreshNeedWorker.swift new file mode 100644 index 00000000..6a0c7ca0 --- /dev/null +++ b/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/Interactor/KarhooTokenRefreshNeedWorker.swift @@ -0,0 +1,111 @@ +// +// KarhooTokenRefreshNeedWorker.swift +// KarhooSDK +// +// Created by Aleksander Wedrychowski on 05/10/2022. +// Copyright © 2022 Flit Technologies Ltd. All rights reserved. +// + +import Foundation + +protocol TokenValidityWorker: AnyObject { + /// Return a value when a new refresh token should be requested + func timeToRequiredRefresh() -> TimeInterval + func saveRefreshBuffer(token: AuthToken) + func tokenNeedsRefreshing() -> Bool + func refreshTokenNeedsRefreshing() -> Bool +} + +final class KarhooTokenValidityWorker: TokenValidityWorker { + + // MARK: - Nested types + + private enum Constants { + /// Seconds buffer when refresh token should be refreshed proactively, so it never becomes expired. Updated each time new AuthToken is saved. + static var refreshBuffer: TimeInterval? + static let refreshBufferModifierBar: TimeInterval = 60 + static let refreshBufferMinPercentageModifier: Double = 0.05 + static let refreshBufferMaxPercentageModifier: Double = 0.20 + static let minimalTimeToRequiredRefresh: TimeInterval = 30 + } + + // MARK: - Properties + + private let dataStore: UserDataStore + + // MARK: - Lifecycle + + init(dataStore: UserDataStore = DefaultUserDataStore()) { + self.dataStore = dataStore + } + + // MARK: - Endpoints + + func timeToRequiredRefresh() -> TimeInterval { + guard let credentials = dataStore.getCurrentCredentials() else { + assertionFailure("Credentials should be set at this stage") + return Constants.minimalTimeToRequiredRefresh + } + + guard let refreshBuffer = Constants.refreshBuffer else { + calculateRefreshBufferIfNeeded() + return timeToRequiredRefresh() + } + + let timeToRefresh: TimeInterval = max( + Constants.minimalTimeToRequiredRefresh, + (credentials.expiryDate?.timeIntervalSinceNow ?? 0) - refreshBuffer + ) + return timeToRefresh + } + + func saveRefreshBuffer(token: AuthToken) { + setRefreshBuffer(timeToRefresh: TimeInterval(token.expiresIn)) + } + + func tokenNeedsRefreshing() -> Bool { + guard let credentials = dataStore.getCurrentCredentials() else { + return false + } + return checkDateDueTime(for: credentials.expiryDate) + } + + func refreshTokenNeedsRefreshing() -> Bool { + guard let credentials = dataStore.getCurrentCredentials(), + let refreshExpiryDate = credentials.refreshTokenExpiryDate + else { + return false + } + return refreshExpiryDate <= Date() + } + + // Check if expire date for refresh token or token makes it needs to be renewed + private func checkDateDueTime(for date: Date?) -> Bool { + guard let date = date else { + return true + } + + guard let refreshBuffer = Constants.refreshBuffer else { + calculateRefreshBufferIfNeeded() + return checkDateDueTime(for: date) + } + + let timeToExpiration = date.timeIntervalSince1970 - Date().timeIntervalSince1970 + return timeToExpiration < refreshBuffer + } + + /// If the buffer has not been set during the app lifecycle, calculate the value accordingly. + private func calculateRefreshBufferIfNeeded() { + guard let credentials = dataStore.getCurrentCredentials() else { + return + } + setRefreshBuffer(timeToRefresh: credentials.expiryDate?.timeIntervalSinceNow ?? 0) + } + + private func setRefreshBuffer(timeToRefresh: TimeInterval) { + let isTimeShorterThanMinimal = timeToRefresh < Constants.refreshBufferModifierBar + let modifier = isTimeShorterThanMinimal ? Constants.refreshBufferMaxPercentageModifier : Constants.refreshBufferMinPercentageModifier + let calculatedRefreshBuffer = timeToRefresh * modifier + Constants.refreshBuffer = calculatedRefreshBuffer + } +} diff --git a/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/Interactor/RefreshTokenInteractor.swift b/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/Interactor/RefreshTokenInteractor.swift index a9158952..a7e4f3b4 100644 --- a/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/Interactor/RefreshTokenInteractor.swift +++ b/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/Interactor/RefreshTokenInteractor.swift @@ -11,5 +11,8 @@ import Foundation protocol RefreshTokenInteractor { func tokenNeedsRefreshing() -> Bool + /// + /// Bool value inside success results tells if SDK had to make a backend call to refresh token + /// func refreshToken(completion: @escaping (Result) -> Void) } diff --git a/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/RefreshTokenError.swift b/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/RefreshTokenError.swift index 29fb2192..438370d5 100644 --- a/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/RefreshTokenError.swift +++ b/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/RefreshTokenError.swift @@ -9,6 +9,8 @@ import Foundation enum RefreshTokenError: KarhooError { - case noRefreshToken + case memoryAllocationError + case noAccessToken case userAlreadyLoggedOut + case extenalAuthenticationRequestExpired } diff --git a/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/TokenRefreshingHttpClient.swift b/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/TokenRefreshingHttpClient.swift index 7e52e2c8..ae7535ae 100644 --- a/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/TokenRefreshingHttpClient.swift +++ b/KarhooSDK/Network/HttpClient/TokenRefreshingHttpClient/TokenRefreshingHttpClient.swift @@ -37,7 +37,7 @@ final class TokenRefreshingHttpClient: HttpClient { } else { let completion: CallbackClosure = { [weak self] result in - if result.errorValue()?.isUnauthorizedError() == true { + if result.getErrorValue()?.isUnauthorizedError() == true { self?.refreshTokenChainWithRequest(endpoint: endpoint, data: data, completion: completion) @@ -69,12 +69,12 @@ final class TokenRefreshingHttpClient: HttpClient { return } - if let error = result.errorValue(), error.isConnectionError() == true { + if let error = result.getErrorValue(), error.isConnectionError() == true { completion(Result.failure(error: error)) return } - if let error = result.errorValue() { + if let error = result.getErrorValue() { self?.logUserOut() completion(Result.failure(error: error)) return diff --git a/KarhooSDK/Service/Auth/LoginInteractor/KarhooAuthLoginWithTokenInteractor.swift b/KarhooSDK/Service/Auth/LoginInteractor/KarhooAuthLoginWithTokenInteractor.swift index 8782faba..9eb4cae7 100644 --- a/KarhooSDK/Service/Auth/LoginInteractor/KarhooAuthLoginWithTokenInteractor.swift +++ b/KarhooSDK/Service/Auth/LoginInteractor/KarhooAuthLoginWithTokenInteractor.swift @@ -59,13 +59,13 @@ final class KarhooAuthLoginWithTokenInteractor: AuthLoginWithTokenInteractor { tokenExchangeRequestSender.encodedRequest(endpoint: .authTokenExchange, body: authLoginHeaderComponents(), callback: { [weak self] (result: Result) in - guard let authToken = result.successValue() else { - userInfoCallback(.failure(error: result.errorValue())) + guard let authToken = result.getSuccessValue() else { + userInfoCallback(.failure(error: result.getErrorValue())) return } let credentials = authToken.toCredentials() self?.userDataStore.set(credentials: credentials) - self?.getUserInfo(credentials: credentials, callback: userInfoCallback) + self?.getUserInfo(credentials: credentials, callback: userInfoCallback) }) } @@ -74,12 +74,12 @@ final class KarhooAuthLoginWithTokenInteractor: AuthLoginWithTokenInteractor { userInfoSender.requestAndDecode(payload: nil, endpoint: .authUserInfo) { [weak self](result: Result) in switch result { - case .success(let result): - let user = result.result + case .success(let result, _): + let user = result self?.didLogin(user: user, credentials: credentials) callback(.success(result: user)) - case .failure(let error): - callback(.failure(error: error.error)) + case .failure(let error, _): + callback(.failure(error: error)) } } } diff --git a/KarhooSDKTests/Mocks/Api/Response/RefreshTokenMock.swift b/KarhooSDKTests/Mocks/Api/Response/RefreshTokenMock.swift deleted file mode 100644 index a883ba4d..00000000 --- a/KarhooSDKTests/Mocks/Api/Response/RefreshTokenMock.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// RefreshTokenMock.swift -// KarhooSDKTests -// -// -// Copyright © 2020 Karhoo. All rights reserved. -// - -import Foundation -@testable import KarhooSDK - -final class RefreshTokenMock { - - private var refreshToken: RefreshToken - - init() { - self.refreshToken = RefreshToken(accessToken: "", expiresIn: 0) - } - - func set(accessToken: String) -> RefreshTokenMock { - create(accessToken: accessToken) - return self - } - - func set(expiresIn: Int) -> RefreshTokenMock { - create(expiresIn: expiresIn) - return self - } - - func build() -> RefreshToken { - return refreshToken - } - - func getData() -> Data { - return refreshToken.encode() ?? Data() - } - - private func create(accessToken: String? = nil, - expiresIn: Int? = nil) { - self.refreshToken = RefreshToken(accessToken: accessToken ?? refreshToken.accessToken, - expiresIn: expiresIn ?? refreshToken.expiresIn) - } - -} diff --git a/KarhooSDKTests/Mocks/Networking/MockSDKConfig.swift b/KarhooSDKTests/Mocks/Networking/MockSDKConfig.swift index df0af6e0..3de288eb 100644 --- a/KarhooSDKTests/Mocks/Networking/MockSDKConfig.swift +++ b/KarhooSDKTests/Mocks/Networking/MockSDKConfig.swift @@ -22,4 +22,10 @@ class MockSDKConfig: KarhooSDKConfiguration { func authenticationMethod() -> AuthenticationMethod { return Self.authenticationMethod } + + static var requireSDKAuthenticationCompletion: () -> Void = {} + func requireSDKAuthentication(callback: @escaping () -> Void) { + MockSDKConfig.requireSDKAuthenticationCompletion() + callback() + } } diff --git a/KarhooSDKTests/Mocks/ObjectTestFactory.swift b/KarhooSDKTests/Mocks/ObjectTestFactory.swift index 3ac8c7a4..8d4063c5 100644 --- a/KarhooSDKTests/Mocks/ObjectTestFactory.swift +++ b/KarhooSDKTests/Mocks/ObjectTestFactory.swift @@ -13,10 +13,17 @@ import CoreLocation class ObjectTestFactory { - class func getRandomCredentials(expiryDate: Date? = TestUtil.getRandomDate(), - withRefreshToken refreshToken: Bool = true) -> Credentials { - return Credentials(accessToken: TestUtil.getRandomString(), - expiryDate: expiryDate, - refreshToken: (refreshToken ? TestUtil.getRandomString() : nil)) + class func getRandomCredentials( + expiryDate: Date? = TestUtil.getRandomDate(), + withRefreshToken: Bool = true, + refreshTokenExpiryDate: Date? = TestUtil.getRandomDate() + + ) -> Credentials { + return Credentials( + accessToken: TestUtil.getRandomString(), + expiryDate: expiryDate, + refreshToken: (withRefreshToken ? TestUtil.getRandomString() : nil), + refreshTokenExpiryDate: refreshTokenExpiryDate + ) } } diff --git a/KarhooSDKTests/Mocks/Utils/MockTokenRefreshNeedWorker.swift b/KarhooSDKTests/Mocks/Utils/MockTokenRefreshNeedWorker.swift new file mode 100644 index 00000000..f4632e6b --- /dev/null +++ b/KarhooSDKTests/Mocks/Utils/MockTokenRefreshNeedWorker.swift @@ -0,0 +1,33 @@ +// +// MockTokenRefreshNeedWorker.swift +// KarhooSDKTests +// +// Created by Aleksander Wedrychowski on 05/10/2022. +// Copyright © 2022 Flit Technologies Ltd. All rights reserved. +// + +import Foundation +@testable import KarhooSDK + +class MockTokenValidityWorker: TokenValidityWorker { + + var timeToRequiredRefreshToReturn = TimeInterval(0) + func timeToRequiredRefresh() -> TimeInterval { + timeToRequiredRefreshToReturn + } + + var bufferSaved = false + func saveRefreshBuffer(token: KarhooSDK.AuthToken) { + bufferSaved = true + } + + var tokenNeedsRefreshingToReturn = false + func tokenNeedsRefreshing() -> Bool { + tokenNeedsRefreshingToReturn + } + + var refreshTokenNeedsRefreshingToReturn = false + func refreshTokenNeedsRefreshing() -> Bool { + refreshTokenNeedsRefreshingToReturn + } +} diff --git a/KarhooSDKTests/TestCases/Api/DataStore/CredentialsSpec.swift b/KarhooSDKTests/TestCases/Api/DataStore/CredentialsSpec.swift index cb60c49b..1e5594f5 100644 --- a/KarhooSDKTests/TestCases/Api/DataStore/CredentialsSpec.swift +++ b/KarhooSDKTests/TestCases/Api/DataStore/CredentialsSpec.swift @@ -21,9 +21,12 @@ final class CredentialsSpec: XCTestCase { let accessToken = TestUtil.getRandomString() let refreshToken = TestUtil.getRandomString() - let credentials = Credentials(accessToken: accessToken, - expiresIn: expiresIn, - refreshToken: refreshToken) + let credentials = Credentials( + accessToken: accessToken, + expiresIn: expiresIn, + refreshToken: refreshToken, + refreshTokenExpiresIn: expiresIn + ) XCTAssert(credentials.accessToken == accessToken) XCTAssert(credentials.refreshToken == refreshToken) @@ -31,24 +34,4 @@ final class CredentialsSpec: XCTestCase { let expectedExpiryDate = Date().addingTimeInterval(expiresIn) XCTAssert(TestUtil.datesEqual(credentials.expiryDate!, expectedExpiryDate)) } - - /** - * When: Converting from RefreshToken to Credentials - * Then: ExpiryDate should be set correctly - * And: Other fields should be set accordingly - */ - func testInitialiseFromRestRefreshTokenResponse() { - let accessToken = TestUtil.getRandomString() - let expiresIn = TestUtil.getRandomInt() - let refreshToken = TestUtil.getRandomString() - let refreshTokenModel = RefreshToken(accessToken: accessToken, expiresIn: expiresIn) - - let credentials = refreshTokenModel.toCredentials(withRefreshToken: refreshToken) - - XCTAssert(credentials.accessToken == accessToken) - XCTAssert(credentials.refreshToken == refreshToken) - - let expectedExpiryDate = Date().addingTimeInterval(TimeInterval(expiresIn)) - XCTAssert(TestUtil.datesEqual(credentials.expiryDate, expectedExpiryDate)) - } } diff --git a/KarhooSDKTests/TestCases/Networking/DefaultAuthTokenSpec.swift b/KarhooSDKTests/TestCases/Networking/DefaultAuthTokenSpec.swift index 55810817..d9a1e597 100644 --- a/KarhooSDKTests/TestCases/Networking/DefaultAuthTokenSpec.swift +++ b/KarhooSDKTests/TestCases/Networking/DefaultAuthTokenSpec.swift @@ -29,9 +29,12 @@ final class DefaultAuthTokenProviderSpec: XCTestCase { */ func testTokenProvider() { let testToken = "Test token" - mockUserDataStore.credentialsToReturn = Credentials(accessToken: testToken, - expiryDate: nil, - refreshToken: nil) + mockUserDataStore.credentialsToReturn = Credentials( + accessToken: testToken, + expiryDate: nil, + refreshToken: nil, + refreshTokenExpiryDate: nil + ) let capturedToken = testObject.accessToken XCTAssert(capturedToken?.token == testToken) diff --git a/KarhooSDKTests/TestCases/Networking/TokenRefresh/KarhooRefreshTokenInteractorSpec.swift b/KarhooSDKTests/TestCases/Networking/TokenRefresh/KarhooRefreshTokenInteractorSpec.swift index d27f35a1..6e9058c2 100644 --- a/KarhooSDKTests/TestCases/Networking/TokenRefresh/KarhooRefreshTokenInteractorSpec.swift +++ b/KarhooSDKTests/TestCases/Networking/TokenRefresh/KarhooRefreshTokenInteractorSpec.swift @@ -13,15 +13,16 @@ final class KarhooRefreshTokenInteractorSpec: XCTestCase { private var testObject: KarhooRefreshTokenInteractor! private var mockUserDataStore: MockUserDataStore! private var mockRequestSender: MockRefreshTokenRequest! + private var mockTokenValidityWorker: MockTokenValidityWorker! override func setUp() { super.setUp() MockSDKConfig.authenticationMethod = .karhooUser mockUserDataStore = MockUserDataStore() mockRequestSender = MockRefreshTokenRequest() + mockTokenValidityWorker = MockTokenValidityWorker() - testObject = KarhooRefreshTokenInteractor(dataStore: mockUserDataStore, - refreshTokenRequest: mockRequestSender) + buildTestObject() } override class func tearDown() { @@ -34,9 +35,9 @@ final class KarhooRefreshTokenInteractorSpec: XCTestCase { * Then: Request should fire with expected path / method */ func testRefreshRequest() { - let credentials = ObjectTestFactory.getRandomCredentials(expiryDate: dateInTheNearFuture()) + let credentials = ObjectTestFactory.getRandomCredentials(expiryDate: dateInTheNearFuture(), refreshTokenExpiryDate: dateInTheFarFuture()) mockUserDataStore.credentialsToReturn = credentials - + mockTokenValidityWorker.tokenNeedsRefreshingToReturn = true let user = UserInfoMock().set(userId: "some").build() mockUserDataStore.userToReturn = user @@ -47,19 +48,25 @@ final class KarhooRefreshTokenInteractorSpec: XCTestCase { /** * When: Requesting token (Auth settings) - * Then: Request should fire with expected path / method + * And: Refresh token expiry is near future + * Then: Require external authentication should be called */ func testAuthRefreshRequest() { + let expectation = XCTestExpectation(description: "requireSDKAuthenticationCalled") MockSDKConfig.authenticationMethod = .tokenExchange(settings: MockSDKConfig.tokenExchangeSettings) - let credentials = ObjectTestFactory.getRandomCredentials(expiryDate: dateInTheNearFuture()) + MockSDKConfig.requireSDKAuthenticationCompletion = { + expectation.fulfill() + } + let credentials = ObjectTestFactory.getRandomCredentials(expiryDate: dateInTheNearFuture(), refreshTokenExpiryDate: dateInTheNearFuture()) mockUserDataStore.credentialsToReturn = credentials - + mockTokenValidityWorker.tokenNeedsRefreshingToReturn = true + mockTokenValidityWorker.refreshTokenNeedsRefreshingToReturn = true let user = UserInfoMock().set(userId: "some").build() mockUserDataStore.userToReturn = user testObject.refreshToken(completion: { _ in}) - mockRequestSender.assertRequestSend(endpoint: .authRefresh, method: .post) + wait(for: [expectation], timeout: 1) } /** @@ -86,14 +93,16 @@ final class KarhooRefreshTokenInteractorSpec: XCTestCase { } /** - * Given: Credentials authentication token expirationDate is near in the future + * Given: TokenRefreshNeedWorker calculated the token needs refreshing * When: tokenNeedsRefreshing method called * Then: It should return true */ - func testTokenDoesNeedRefreshingDateFarFuture() { + func testTokenDoesNeedRefreshing() { let credentials = ObjectTestFactory.getRandomCredentials(expiryDate: dateInTheNearFuture()) mockUserDataStore.credentialsToReturn = credentials - + mockTokenValidityWorker.tokenNeedsRefreshingToReturn = true + mockTokenValidityWorker.refreshTokenNeedsRefreshingToReturn = true + XCTAssertTrue(testObject.tokenNeedsRefreshing()) } @@ -105,6 +114,8 @@ final class KarhooRefreshTokenInteractorSpec: XCTestCase { func testTokenDoesNeedRefreshingPastDate() { let credentials = ObjectTestFactory.getRandomCredentials(expiryDate: dateInThePast()) mockUserDataStore.credentialsToReturn = credentials + let worker = KarhooTokenValidityWorker(dataStore: mockUserDataStore) + buildTestObject(tokenValidityWorker: worker) XCTAssertTrue(testObject.tokenNeedsRefreshing()) } @@ -119,14 +130,14 @@ final class KarhooRefreshTokenInteractorSpec: XCTestCase { let credentials = ObjectTestFactory.getRandomCredentials(expiryDate: dateInTheFarFuture()) mockUserDataStore.credentialsToReturn = credentials - var capturedResult: Result? + let expectation = XCTestExpectation(description: "correct captured value") testObject.refreshToken { result in - capturedResult = result + result.isSuccess() ? expectation.fulfill() : XCTFail("Result success value expected") + expectation.fulfill() } - + XCTAssertFalse(mockRequestSender.requestCalled) - XCTAssertTrue(capturedResult!.isSuccess()) - XCTAssertFalse(capturedResult!.successValue()!) + wait(for: [expectation], timeout: 1) } /** @@ -135,19 +146,22 @@ final class KarhooRefreshTokenInteractorSpec: XCTestCase { * Then: It should return true */ func testNilExpiryDateRefreshCheck() { - let credentials = Credentials(accessToken: "123", - expiryDate: nil, - refreshToken: "123") + let credentials = Credentials( + accessToken: "123", + expiryDate: nil, + refreshToken: "123", + refreshTokenExpiryDate: Date().addingTimeInterval(300) + ) mockUserDataStore.credentialsToReturn = credentials - + let worker = KarhooTokenValidityWorker(dataStore: mockUserDataStore) + buildTestObject(tokenValidityWorker: worker) XCTAssertTrue(testObject.tokenNeedsRefreshing()) } /** * Given: Refresh token not saved in user data store * And: Token expiration date in near future - * When: refreshToken method called - * Then: Callback should be fired with an error + * Then: request new auth credentials called */ func testMissingRefreshToken() { let user = UserInfoMock().set(userId: "some").build() @@ -155,20 +169,23 @@ final class KarhooRefreshTokenInteractorSpec: XCTestCase { let credentials = ObjectTestFactory.getRandomCredentials(expiryDate: dateInTheNearFuture(), withRefreshToken: false) + let expectation = XCTestExpectation(description: "new auth credentials requested") + mockUserDataStore.credentialsToReturn = credentials + buildTestObject(tokenValidityWorker: KarhooTokenValidityWorker()) - var capturedResult: Result? - testObject.refreshToken { result in - capturedResult = result + MockSDKConfig.requireSDKAuthenticationCompletion = { + expectation.fulfill() } - let returnedError = capturedResult?.errorValue() as? RefreshTokenError - XCTAssertNotNil(returnedError) - XCTAssertEqual(.noRefreshToken, returnedError) + testObject.refreshToken { _ in + } + + wait(for: [expectation], timeout: 1) } /** - * Given: Refresh token expirationDate is near + * Given: TokenRefreshNeedWorker calculated the token needs refreshing * And: refreshToken method called * And: Network request is made to refresh token * When: Network request to refresh token returns @@ -180,38 +197,45 @@ final class KarhooRefreshTokenInteractorSpec: XCTestCase { let credentials = ObjectTestFactory.getRandomCredentials(expiryDate: dateInTheNearFuture()) mockUserDataStore.credentialsToReturn = credentials + mockTokenValidityWorker.tokenNeedsRefreshingToReturn = true let accessTokenAfterRefresh = TestUtil.getRandomString() let successResponse = AuthTokenMock().set(accessToken: accessTokenAfterRefresh).set(expiresIn: 10000) - var capturedResult: Result? + let expectation = XCTestExpectation(description: "correct captured value") testObject.refreshToken { result in - capturedResult = result + result.isSuccess() ? expectation.fulfill() : XCTFail("Result success value expected") } mockRequestSender.success(response: successResponse.build()) XCTAssertTrue(mockRequestSender.requestCalled) - XCTAssertTrue(capturedResult!.isSuccess()) - XCTAssertTrue(capturedResult!.successValue()!) XCTAssertEqual(mockUserDataStore.storedCredentials?.accessToken, accessTokenAfterRefresh) + + wait(for: [expectation], timeout: 1) } /** - * Given: Refresh token expirationDate is near + * Given: Token needs refreshing * And: refreshToken method called * And: Network request is made to refresh token * When: Network request to refresh token fails * Then: New credentials should NOT be saved in user data store - * And: Callback should return httpClient error */ func testRefreshTokenError() { + let externalAuthRequestCalledExpectation = XCTestExpectation(description: "externalAuthRequestCalled") + MockSDKConfig.requireSDKAuthenticationCompletion = { + externalAuthRequestCalledExpectation.fulfill() + } + let user = UserInfoMock().set(userId: "some").build() mockUserDataStore.userToReturn = user let credentials = ObjectTestFactory.getRandomCredentials(expiryDate: dateInTheNearFuture()) mockUserDataStore.credentialsToReturn = credentials + mockTokenValidityWorker.tokenNeedsRefreshingToReturn = true + let expectedError = TestUtil.getRandomError() var capturedResult: Result? @@ -222,13 +246,11 @@ final class KarhooRefreshTokenInteractorSpec: XCTestCase { mockRequestSender.fail(error: expectedError) XCTAssertTrue(mockRequestSender.requestCalled) - XCTAssertFalse(mockUserDataStore.setCurrentUserCalled) - XCTAssert(expectedError.equals(capturedResult!.errorValue()!)) - + wait(for: [externalAuthRequestCalledExpectation], timeout: 1) } /** - * Given: Refresh token expirationDate is near + * Given: Token needs refreshing * And: User credentials stored in user data store * And: refreshToken method called * And: Network request is made to refresh token @@ -243,6 +265,8 @@ final class KarhooRefreshTokenInteractorSpec: XCTestCase { let credentials = ObjectTestFactory.getRandomCredentials(expiryDate: dateInTheNearFuture()) mockUserDataStore.credentialsToReturn = credentials + mockTokenValidityWorker.tokenNeedsRefreshingToReturn = true + mockTokenValidityWorker.refreshTokenNeedsRefreshingToReturn = false let accessTokenAfterRefresh = TestUtil.getRandomString() @@ -252,18 +276,46 @@ final class KarhooRefreshTokenInteractorSpec: XCTestCase { self?.mockUserDataStore.userToReturn = nil } - var capturedResult: Result? + let expectation = XCTestExpectation(description: "correct captured value") testObject.refreshToken { result in - capturedResult = result + !result.isSuccess() ? expectation.fulfill() : XCTFail("Result failure expected") + let expectedError = RefreshTokenError.userAlreadyLoggedOut + let capturedError = result.getErrorValue() as? RefreshTokenError + XCTAssertNotNil(capturedError) + XCTAssertEqual(expectedError, capturedError) + expectation.fulfill() } mockRequestSender.success(response: requestPayload.build()) XCTAssertTrue(mockRequestSender.requestCalled) XCTAssert(mockUserDataStore.setCurrentUserCalled == false) - let expectedError = RefreshTokenError.userAlreadyLoggedOut - let capturedError = capturedResult?.errorValue() as? RefreshTokenError - XCTAssertNotNil(capturedError) - XCTAssertEqual(expectedError, capturedError) + wait(for: [expectation], timeout: 1) + } + + /** + When: at least two refresh request are made + And: Refresh logic is done with any result + Then: All refresh compltions should be triggered + */ + func testMultipleRefreshRequestHandling() { + let request1CompletionCalledExpectation = XCTestExpectation() + let request2CompletionCalledExpectation = XCTestExpectation() + + let credentials = ObjectTestFactory.getRandomCredentials(expiryDate: dateInTheNearFuture()) + mockUserDataStore.credentialsToReturn = credentials + + testObject.refreshToken { _ in + request1CompletionCalledExpectation.fulfill() + } + testObject.refreshToken { _ in + request2CompletionCalledExpectation.fulfill() + } + + let accessTokenAfterRefresh = TestUtil.getRandomString() + let requestPayload = AuthTokenMock().set(accessToken: accessTokenAfterRefresh).set(expiresIn: 10000) + mockRequestSender.success(response: requestPayload.build()) + + wait(for: [request1CompletionCalledExpectation, request2CompletionCalledExpectation], timeout: 1) } /** @@ -292,15 +344,15 @@ final class KarhooRefreshTokenInteractorSpec: XCTestCase { self?.mockUserDataStore.credentialsToReturn = credentials } - var capturedResult: Result? + let expectation = XCTestExpectation(description: "correct captured value") testObject.refreshToken { result in - capturedResult = result + result.isSuccess() ? expectation.fulfill() : XCTFail("Result success value expected") + XCTAssertFalse(self.mockUserDataStore.setCurrentUserCalled) + expectation.fulfill() } mockRequestSender.success(response: requestPayload.build()) - - XCTAssertFalse(mockUserDataStore.setCurrentUserCalled) - XCTAssertFalse(capturedResult!.successValue()!) + wait(for: [expectation], timeout: 1) } private func dateInTheFarFuture() -> Date { @@ -308,11 +360,23 @@ final class KarhooRefreshTokenInteractorSpec: XCTestCase { } private func dateInTheNearFuture() -> Date { - let shortInterval = TimeInterval(Double(TestUtil.getRandomInt(lessThan: 100)) * 0.01) + let shortInterval = TimeInterval(Double(TestUtil.getRandomInt(lessThan: 60)) * 0.01) return Date().addingTimeInterval(shortInterval) } private func dateInThePast() -> Date { return Date().addingTimeInterval(-400) } + + private func buildTestObject( + dataStore: UserDataStore? = nil, + refreshTokenRequest: RequestSender? = nil, + tokenValidityWorker: TokenValidityWorker? = nil + ) { + testObject = KarhooRefreshTokenInteractor( + dataStore: dataStore ?? mockUserDataStore, + refreshTokenRequest: refreshTokenRequest ?? mockRequestSender, + tokenValidityWorker: tokenValidityWorker ?? mockTokenValidityWorker + ) + } } diff --git a/Package.swift b/Package.swift index 501c9c06..21cae7f4 100644 --- a/Package.swift +++ b/Package.swift @@ -6,7 +6,7 @@ import PackageDescription let package = Package( name: "KarhooSDK", defaultLocalization: "en", - platforms: [.iOS(.v11)], + platforms: [.iOS(.v13)], products: [ .library( name: "KarhooSDK", diff --git a/README.md b/README.md index 11716908..dc6f25f6 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ You can use [CocoaPods](http://cocoapods.org/) to install `KarhooSDK` by adding ```ruby use_frameworks! -pod 'KarhooSDK', '~> 1.6.3' +pod 'KarhooSDK', '~> 1.7.0' ``` then import `KarhooSDK` wherever you want to access Karhoo services @@ -52,7 +52,7 @@ Once you have your Swift package set up, adding Karhoo as a dependency is as eas ```swift dependencies: [ -.package(url: "https://github.com/Karhoo/karhoo-ios-sdk.git", .upToNextMajor(from: "1.6.3")) +.package(url: "https://github.com/Karhoo/karhoo-ios-sdk.git", .upToNextMajor(from: "1.7.0")) ] ```