├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .gitmodules ├── .jazzy.json ├── .swift-version ├── .swiftformat ├── .swiftlint.yml ├── .swiftpm └── xcode │ └── package.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDETemplateMacros.plist ├── Format ├── generate_docs.sh └── jazzy.json ├── Images ├── InfoPlistExample.png ├── OAuthFlowApproval.png └── OAuthFlowInit.png ├── LICENSE ├── Package.swift ├── README.md ├── Source ├── SwiftyDropbox │ ├── Platform │ │ ├── SwiftyDropbox_iOS │ │ │ ├── Info.plist │ │ │ ├── LoadingViewController.swift │ │ │ ├── OAuthMobile.swift │ │ │ └── UtilitiesMobile.swift │ │ └── SwiftyDropbox_macOS │ │ │ ├── Info.plist │ │ │ └── OAuthDesktop.swift │ ├── PrivacyInfo.xcprivacy │ └── Shared │ │ ├── Generated │ │ ├── Account.swift │ │ ├── AccountRoutes.swift │ │ ├── AppAuthReconnectionHelpers.swift │ │ ├── Async.swift │ │ ├── Auth.swift │ │ ├── AuthAppAuthRoutes.swift │ │ ├── AuthRoutes.swift │ │ ├── Base.swift │ │ ├── BaseApp.swift │ │ ├── BaseTeam.swift │ │ ├── Check.swift │ │ ├── CheckAppAuthRoutes.swift │ │ ├── CheckRoutes.swift │ │ ├── Common.swift │ │ ├── Contacts.swift │ │ ├── ContactsRoutes.swift │ │ ├── DropboxAppBaseRequestBox.swift │ │ ├── DropboxBaseRequestBox.swift │ │ ├── FileProperties.swift │ │ ├── FilePropertiesRoutes.swift │ │ ├── FileRequests.swift │ │ ├── FileRequestsRoutes.swift │ │ ├── Files.swift │ │ ├── FilesAppAuthRoutes.swift │ │ ├── FilesRoutes.swift │ │ ├── Openid.swift │ │ ├── OpenidRoutes.swift │ │ ├── Paper.swift │ │ ├── PaperRoutes.swift │ │ ├── ReconnectionHelpers.swift │ │ ├── SecondaryEmails.swift │ │ ├── SeenState.swift │ │ ├── Sharing.swift │ │ ├── SharingAppAuthRoutes.swift │ │ ├── SharingRoutes.swift │ │ ├── StoneBase.swift │ │ ├── StoneSerializers.swift │ │ ├── StoneValidators.swift │ │ ├── Team.swift │ │ ├── TeamCommon.swift │ │ ├── TeamLog.swift │ │ ├── TeamLogRoutes.swift │ │ ├── TeamPolicies.swift │ │ ├── TeamRoutes.swift │ │ ├── Users.swift │ │ ├── UsersCommon.swift │ │ └── UsersRoutes.swift │ │ └── Handwritten │ │ ├── BackgroundClientSetupInfo.swift │ │ ├── CertificatePinning.swift │ │ ├── Custom │ │ ├── ChunkInputStream.swift │ │ ├── Custom.swift │ │ ├── CustomRoutes.swift │ │ └── CustomTasks.swift │ │ ├── DropboxAppClient.swift │ │ ├── DropboxClient.swift │ │ ├── DropboxClientsManager.swift │ │ ├── DropboxTeamClient.swift │ │ ├── DropboxTransportClient.swift │ │ ├── DropboxTransportClientInterface.swift │ │ ├── Errors.swift │ │ ├── FilesAcccess.swift │ │ ├── GlobalErrorResponseHandler.swift │ │ ├── MockApiRequest.swift │ │ ├── MockDropboxTransportClient.swift │ │ ├── NetworkSession │ │ ├── Mocks │ │ │ ├── MockNetworkDataTask.swift │ │ │ └── MockNetworkSession.swift │ │ ├── NetworkSession.swift │ │ ├── NetworkSessionConfiguration.swift │ │ ├── NetworkSessionManager.swift │ │ └── NetworkTask.swift │ │ ├── NoopRequest.swift │ │ ├── OAuth │ │ ├── AccessTokenProvider.swift │ │ ├── AuthSession.swift │ │ ├── OAuth.swift │ │ ├── OAuthConstants.swift │ │ ├── OAuthImpl.swift │ │ ├── OAuthTokenRequest.swift │ │ ├── OAuthUtils.swift │ │ ├── Reachability.swift │ │ └── SecureStorageAccess.swift │ │ ├── ReconnectionHelpers+Handwritten.swift │ │ ├── Request+Async.swift │ │ ├── Request+TokenRefresh.swift │ │ ├── Request.swift │ │ ├── RequestMap.swift │ │ ├── SDKConstants.swift │ │ └── Utilities.swift ├── SwiftyDropboxObjC │ ├── Platform │ │ ├── SwiftyDropbox_iOS │ │ │ ├── DBXOAuthMobile.swift │ │ │ └── Info.plist │ │ └── SwiftyDropbox_macOS │ │ │ ├── DBXOAuthDesktop.swift │ │ │ └── Info.plist │ ├── PrivacyInfo.xcprivacy │ └── Shared │ │ ├── Generated │ │ ├── DBXAccount.swift │ │ ├── DBXAccountRoutes.swift │ │ ├── DBXAsync.swift │ │ ├── DBXAuth.swift │ │ ├── DBXAuthAppAuthRoutes.swift │ │ ├── DBXAuthRoutes.swift │ │ ├── DBXBase.swift │ │ ├── DBXBaseApp.swift │ │ ├── DBXBaseTeam.swift │ │ ├── DBXCheck.swift │ │ ├── DBXCheckAppAuthRoutes.swift │ │ ├── DBXCheckRoutes.swift │ │ ├── DBXCommon.swift │ │ ├── DBXContacts.swift │ │ ├── DBXContactsRoutes.swift │ │ ├── DBXDropboxAppBaseRequestBox.swift │ │ ├── DBXDropboxBaseRequestBox.swift │ │ ├── DBXFileProperties.swift │ │ ├── DBXFilePropertiesRoutes.swift │ │ ├── DBXFileRequests.swift │ │ ├── DBXFileRequestsRoutes.swift │ │ ├── DBXFiles.swift │ │ ├── DBXFilesAppAuthRoutes.swift │ │ ├── DBXFilesRoutes.swift │ │ ├── DBXOpenid.swift │ │ ├── DBXOpenidRoutes.swift │ │ ├── DBXPaper.swift │ │ ├── DBXPaperRoutes.swift │ │ ├── DBXSecondaryEmails.swift │ │ ├── DBXSeenState.swift │ │ ├── DBXSharing.swift │ │ ├── DBXSharingAppAuthRoutes.swift │ │ ├── DBXSharingRoutes.swift │ │ ├── DBXTeam.swift │ │ ├── DBXTeamCommon.swift │ │ ├── DBXTeamLog.swift │ │ ├── DBXTeamLogRoutes.swift │ │ ├── DBXTeamPolicies.swift │ │ ├── DBXTeamRoutes.swift │ │ ├── DBXUsers.swift │ │ ├── DBXUsersCommon.swift │ │ └── DBXUsersRoutes.swift │ │ └── Handwritten │ │ ├── DBXCallError.swift │ │ ├── DBXCertificatePinning.swift │ │ ├── DBXDropboxAppClient.swift │ │ ├── DBXDropboxClient.swift │ │ ├── DBXDropboxClientsManager.swift │ │ ├── DBXDropboxTeamClient.swift │ │ ├── DBXDropboxTransportClient.swift │ │ ├── DBXReconnectionHelpers.swift │ │ ├── DBXRequest.swift │ │ ├── NetworkSession │ │ └── DBXNetworkSessionConfiguration.swift │ │ └── OAuth │ │ ├── DBXAccessTokenProvider.swift │ │ ├── DBXAuthSession.swift │ │ ├── DBXOAuth.swift │ │ ├── DBXOAuthImpl.swift │ │ └── DBXSecureStorageAccess.swift └── SwiftyDropboxUnitTests │ ├── GlobalErrorResponseHandlerTests.swift │ ├── OAuthImplTests.swift │ ├── ReconnectionHelperPersistedRequestInfoTests.swift │ ├── ReconnectionHelperRouteNameTests.swift │ ├── Request+Async.test.swift │ ├── TestAsciiEncoding.swift │ ├── TestDropboxTransportClient.swift │ ├── TestMockingUtilities.swift │ ├── TestNetworkSessionManager+Background.swift │ ├── TestNetworkSessionManager.swift │ ├── TestOAuthTokenRequest.swift │ ├── TestRequest.swift │ ├── TestRequestMap.swift │ ├── TestRequestWithTokenRefresh.swift │ └── TestSecureStorageAccess.swift ├── SwiftyDropbox.podspec ├── SwiftyDropboxObjc.podspec ├── TestSwiftyDropbox ├── .swiftpm │ └── xcode │ │ └── package.xcworkspace │ │ └── contents.xcworkspacedata ├── IntegrationTests │ ├── BackgroundSessionTestClasses.swift │ ├── ObjC │ │ ├── ObjCTestClasses.h │ │ ├── ObjCTestClasses.m │ │ └── ObjCTestData.swift │ ├── TestAppType.swift │ ├── TestClasses.swift │ └── TestData.swift ├── Package.swift ├── Podfile ├── Podfile.lock ├── TestSwiftyDropbox.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ ├── TestSwiftyDropbox_ActionExtension.xcscheme │ │ ├── TestSwiftyDropbox_iOS.xcscheme │ │ └── TestSwiftyDropbox_macOS.xcscheme ├── TestSwiftyDropbox.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── TestSwiftyDropbox_ActionExtension │ ├── ActionRequestHandler.swift │ ├── Info.plist │ └── TestSwiftyDropbox_ActionExtension.entitlements ├── TestSwiftyDropbox_SwiftUI │ ├── Shared │ │ └── Assets.xcassets │ │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ │ └── Contents.json │ ├── iOS │ │ ├── AppDelegate.swift │ │ ├── ContentView.swift │ │ ├── Info.plist │ │ └── TestSwiftyDropboxApp.swift │ └── macOS │ │ ├── AppDelegate.swift │ │ ├── ContentView.swift │ │ ├── Info.plist │ │ ├── TestSwiftyDropboxApp.swift │ │ └── macOS.entitlements ├── TestSwiftyDropbox_iOS │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── DebugBackgroundSessionView.swift │ ├── DebugBackgroundSessionViewModel.swift │ ├── FileBrowserView.swift │ ├── FileTextView.swift │ ├── Info.plist │ ├── Main.storyboard │ ├── TestSwiftyDropbox.entitlements │ ├── TestUtilities.swift │ └── ViewController.swift ├── TestSwiftyDropbox_iOSTests │ ├── CustomRoutesTests.swift │ ├── FilesRoutesTests.swift │ ├── Info.plist │ ├── ObjCFilesRoutesTests.h │ ├── ObjCFilesRoutesTests.m │ ├── ObjCTeamRoutesTests.h │ ├── ObjCTeamRoutesTests.m │ ├── SwiftyDropboxTestExtensions.swift │ └── TeamRoutesTests.swift ├── TestSwiftyDropbox_macOS │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ └── Main.storyboard │ ├── Info.plist │ └── ViewController.swift ├── TestSwiftyDropbox_macOSTests │ └── Info.plist └── TestUtils │ └── TestTokenAuthGenerator.swift ├── generate_base_client.py ├── update_repo_check.sh └── update_version.sh /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [pull_request, workflow_dispatch] 3 | 4 | jobs: 5 | test: 6 | name: Run Unit Tests 7 | runs-on: macos-13 8 | timeout-minutes: 45 9 | 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v2 13 | - name: Pod Install 14 | run: | 15 | cd TestSwiftyDropbox 16 | pod install --repo-update 17 | - name: Test iOS 18 | env: 19 | FULL_DROPBOX_API_APP_KEY: ${{ secrets.FULL_DROPBOX_API_APP_KEY }} 20 | FULL_DROPBOX_TESTER_TEAM_REFRESH_TOKEN: ${{ secrets.FULL_DROPBOX_TESTER_TEAM_REFRESH_TOKEN }} 21 | FULL_DROPBOX_TESTER_USER_REFRESH_TOKEN: ${{ secrets.FULL_DROPBOX_TESTER_USER_REFRESH_TOKEN }} 22 | TEAM_MEMBER_EMAIL: ${{ secrets.TEAM_MEMBER_EMAIL }} 23 | EMAIL_TO_ADD_AS_TEAM_MEMBER: ${{ secrets.EMAIL_TO_ADD_AS_TEAM_MEMBER }} 24 | ACCOUNT_ID: ${{ secrets.ACCOUNT_ID }} 25 | ACCOUNT_ID_2: ${{ secrets.ACCOUNT_ID_2 }} 26 | ACCOUNT_ID_3: ${{ secrets.ACCOUNT_ID_3 }} 27 | platform: ${{ 'iOS Simulator' }} 28 | device: ${{ 'iPhone 14' }} 29 | run: | 30 | xcodebuild -workspace TestSwiftyDropbox/TestSwiftyDropbox.xcworkspace/ -scheme TestSwiftyDropbox_iOS -sdk iphonesimulator \ 31 | -destination "platform=$platform,name=$device" \ 32 | FULL_DROPBOX_API_APP_KEY=$FULL_DROPBOX_API_APP_KEY \ 33 | FULL_DROPBOX_TESTER_TEAM_REFRESH_TOKEN=$FULL_DROPBOX_TESTER_TEAM_REFRESH_TOKEN \ 34 | FULL_DROPBOX_TESTER_USER_REFRESH_TOKEN=$FULL_DROPBOX_TESTER_USER_REFRESH_TOKEN \ 35 | TEAM_MEMBER_EMAIL=$TEAM_MEMBER_EMAIL \ 36 | EMAIL_TO_ADD_AS_TEAM_MEMBER=$EMAIL_TO_ADD_AS_TEAM_MEMBER \ 37 | ACCOUNT_ID=$ACCOUNT_ID \ 38 | ACCOUNT_ID_2=$ACCOUNT_ID_2 \ 39 | ACCOUNT_ID_3=$ACCOUNT_ID_3 \ 40 | test 41 | 42 | - name: Test macOS 43 | env: 44 | FULL_DROPBOX_API_APP_KEY: ${{ secrets.FULL_DROPBOX_API_APP_KEY }} 45 | FULL_DROPBOX_TESTER_TEAM_REFRESH_TOKEN: ${{ secrets.FULL_DROPBOX_TESTER_TEAM_REFRESH_TOKEN }} 46 | FULL_DROPBOX_TESTER_USER_REFRESH_TOKEN: ${{ secrets.FULL_DROPBOX_TESTER_USER_REFRESH_TOKEN }} 47 | TEAM_MEMBER_EMAIL: ${{ secrets.TEAM_MEMBER_EMAIL }} 48 | EMAIL_TO_ADD_AS_TEAM_MEMBER: ${{ secrets.EMAIL_TO_ADD_AS_TEAM_MEMBER }} 49 | ACCOUNT_ID: ${{ secrets.ACCOUNT_ID }} 50 | ACCOUNT_ID_2: ${{ secrets.ACCOUNT_ID_2 }} 51 | ACCOUNT_ID_3: ${{ secrets.ACCOUNT_ID_3 }} 52 | platform: ${{ 'macOS' }} 53 | run: | 54 | xcodebuild -workspace TestSwiftyDropbox/TestSwiftyDropbox.xcworkspace/ -scheme TestSwiftyDropbox_macOS \ 55 | -destination "platform=$platform,arch=x86_64" \ 56 | FULL_DROPBOX_API_APP_KEY=$FULL_DROPBOX_API_APP_KEY \ 57 | FULL_DROPBOX_TESTER_TEAM_REFRESH_TOKEN=$FULL_DROPBOX_TESTER_TEAM_REFRESH_TOKEN \ 58 | FULL_DROPBOX_TESTER_USER_REFRESH_TOKEN=$FULL_DROPBOX_TESTER_USER_REFRESH_TOKEN \ 59 | TEAM_MEMBER_EMAIL=$TEAM_MEMBER_EMAIL \ 60 | EMAIL_TO_ADD_AS_TEAM_MEMBER=$EMAIL_TO_ADD_AS_TEAM_MEMBER \ 61 | ACCOUNT_ID=$ACCOUNT_ID \ 62 | ACCOUNT_ID_2=$ACCOUNT_ID_2 \ 63 | ACCOUNT_ID_3=$ACCOUNT_ID_3 \ 64 | test 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## macOS 2 | .DS_Store 3 | .arcconfig 4 | 5 | ## Xcode 6 | xcuserdata/ 7 | build/ 8 | 9 | ## CocoaPods 10 | Pods/ 11 | 12 | ## Swift Package Manager 13 | Packages/ 14 | .build/ 15 | .swiftpm/xcode/xcuserdata 16 | .swiftpm/xcode/package.xcworkspace/xcuserdata 17 | 18 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "stone"] 2 | path = stone 3 | url = https://github.com/dropbox/stone.git 4 | [submodule "spec"] 5 | path = spec 6 | url = https://github.com/dropbox/dropbox-api-spec.git 7 | -------------------------------------------------------------------------------- /.jazzy.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Dropbox, Inc.", 3 | "author_url": "https://dropbox.com/developers", 4 | "skip_undocumented": true, 5 | "hide_documentation_coverage": true, 6 | "exclude": [ 7 | "Source/StoneSerializers.swift", 8 | "Source/StoneValidators.swift", 9 | "Source/DropboxTransportClient.swift" 10 | ], 11 | "custom_categories": [ 12 | { 13 | "name": "Routes", 14 | "children": [ 15 | "AccountRoutes", 16 | "AuthRoutes", 17 | "CheckRoutes", 18 | "ContactsRoutes", 19 | "FilePropertiesRoutes", 20 | "FileRequestsRoutes", 21 | "FilesRoutes", 22 | "OpenidRoutes", 23 | "PaperRoutes", 24 | "SharingRoutes", 25 | "TeamRoutes", 26 | "TeamLogRoutes", 27 | "UsersRoutes" 28 | ] 29 | }, 30 | { 31 | "name": "Data Types", 32 | "children": [ 33 | "Account", 34 | "Async", 35 | "Auth", 36 | "Check", 37 | "Common", 38 | "Contacts", 39 | "FileProperties", 40 | "FileRequests", 41 | "Files", 42 | "Openid", 43 | "Paper", 44 | "SecondaryEmails", 45 | "SeenState", 46 | "Sharing", 47 | "Team", 48 | "TeamCommon", 49 | "TeamLog", 50 | "TeamPolicies", 51 | "Users", 52 | "UsersCommon" 53 | ] 54 | }, 55 | { 56 | "name": "Authentication", 57 | "children": [ 58 | "DropboxOAuthManager", 59 | "DropboxOAuthResult", 60 | "DropboxAccessToken", 61 | "OAuth2Error" 62 | ] 63 | }, 64 | { 65 | "name": "Client Classes", 66 | "children": [ 67 | "DropboxClient", 68 | "DropboxTeamClient", 69 | "DropboxClientsManager" 70 | ] 71 | } 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 5.6 2 | -------------------------------------------------------------------------------- /.swiftformat: -------------------------------------------------------------------------------- 1 | --exclude stone,spec 2 | --ifdef no-indent 3 | --maxwidth 160 4 | --trimwhitespace always 5 | --hexliteralcase lowercase 6 | --semicolons never 7 | --stripunusedargs closure-only 8 | --decimalgrouping 3 9 | --disable trailingClosures 10 | --wraparguments before-first 11 | --wrapcollections before-first 12 | --wrapparameters before-first 13 | --closingparen balanced 14 | --self init-only 15 | --disable andOperator 16 | --disable linebreakAtEndOfFile 17 | --disable hoistPatternLet 18 | --specifierorder public,open,override 19 | --disable extensionAccessControl 20 | --disable wrapMultilineStatementBraces 21 | --disable redundantType 22 | --disable enumNamespaces 23 | --disable redundantClosure 24 | --disable redundantVoidReturnType 25 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | disabled_rules: # rule identifiers to exclude from running 2 | # - colon 3 | # - comma 4 | # - control_statement 5 | opt_in_rules: # some rules are only opt-in 6 | - empty_count 7 | - missing_docs 8 | # Find all the available rules by running: 9 | # swiftlint rules 10 | included: # paths to include during linting. `--path` is ignored if present. 11 | - Source 12 | excluded: # paths to ignore during linting. Takes precedence over `included`. 13 | - Carthage 14 | - Pods 15 | - Source/ExcludedFolder 16 | - Source/ExcludedFile.swift 17 | 18 | # configurable rules can be customized from this configuration file 19 | # binary rules can set their severity level 20 | force_cast: warning # implicitly 21 | force_try: 22 | severity: warning # explicitly 23 | # rules that have both warning and error levels, can set just the warning level 24 | # implicitly 25 | line_length: 26 | - 50 # warning 27 | - 70 # error 28 | # they can set both implicitly with an array 29 | type_body_length: 30 | - 300 # warning 31 | - 400 # error 32 | # or they can set both explicitly 33 | file_length: 34 | warning: 500 35 | error: 1200 36 | # naming rules can set warnings/errors for min_length and max_length 37 | # additionally they can set excluded names 38 | type_name: 39 | min_length: 4 # only warning 40 | max_length: # warning and error 41 | warning: 40 42 | error: 50 43 | excluded: iPhone # excluded via string 44 | variable_name: 45 | min_length: # only min_length 46 | error: 4 # only error 47 | excluded: # excluded via string array 48 | - id 49 | - URL 50 | - GlobalAPIKey 51 | reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, junit) -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/xcshareddata/IDETemplateMacros.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | FILEHEADER 6 | / 7 | /// Copyright (c) ___YEAR___ Dropbox, Inc. All rights reserved. 8 | /// 9 | 10 | 11 | -------------------------------------------------------------------------------- /Format/generate_docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Script for generating jazzy docs 3 | 4 | if [ "$#" -ne 2 ]; then 5 | echo "Script requires two arguments: 1. path to docs repo checkout 2. path to updated SDK checkout." 6 | else 7 | sdk_version="$(git describe --abbrev=0 --tags)" 8 | docs_repo_location="$1" 9 | sdk_repo_location="$2" 10 | 11 | echo "Checking doc repo exists..." 12 | 13 | if [ -d $docs_repo_location ]; then 14 | if [ -d $sdk_repo_location ]; then 15 | docs_location="$docs_repo_location/api-docs/$sdk_version" 16 | if [ -d $docs_location ]; then 17 | rm -rf $docs_location 18 | fi 19 | 20 | mkdir $docs_location 21 | 22 | echo "Generating documents..." 23 | cd .. 24 | jazzy --readme $sdk_repo_location/README.md --config $sdk_repo_location/.jazzy.json --github_url https://github.com/dropbox/SwiftyDropbox --module-version $sdk_version --podspec SwiftyDropbox.podspec -o $docs_location 25 | cd - 26 | 27 | cd $docs_repo_location/api-docs 28 | rm -rf latest 29 | mkdir latest 30 | cp -R $sdk_version/* latest/ 31 | cd - 32 | 33 | echo "Finished generating docs to: $docs_repo_location/api-docs." 34 | else 35 | echo "SDK directory does not exist" 36 | fi 37 | else 38 | echo "Docs directory does not exist" 39 | fi 40 | fi 41 | -------------------------------------------------------------------------------- /Format/jazzy.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Dropbox, Inc.", 3 | "author_url": "https://dropbox.com/developers", 4 | "skip_undocumented": true, 5 | "hide_documentation_coverage": true, 6 | "exclude": [ 7 | "Source/StoneSerializers.swift", 8 | "Source/StoneValidators.swift", 9 | "Source/DropboxTransportClient.swift" 10 | ], 11 | "custom_categories": [ 12 | { 13 | "name": "Routes", 14 | "children": [] 15 | }, 16 | { 17 | "name": "Data Types", 18 | "children": [] 19 | }, 20 | { 21 | "name": "Authentication", 22 | "children": [ 23 | "DropboxOAuthManager", 24 | "DropboxOAuthResult", 25 | "DropboxAccessToken", 26 | "OAuth2Error" 27 | ] 28 | }, 29 | { 30 | "name": "Client Classes", 31 | "children": [ 32 | "DropboxClient", 33 | "DropboxTeamClient", 34 | "DropboxClientsManager" 35 | ] 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /Images/InfoPlistExample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dropbox/SwiftyDropbox/ce29a217890382615934425f0696b02839cbacbe/Images/InfoPlistExample.png -------------------------------------------------------------------------------- /Images/OAuthFlowApproval.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dropbox/SwiftyDropbox/ce29a217890382615934425f0696b02839cbacbe/Images/OAuthFlowApproval.png -------------------------------------------------------------------------------- /Images/OAuthFlowInit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dropbox/SwiftyDropbox/ce29a217890382615934425f0696b02839cbacbe/Images/OAuthFlowInit.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2021 Dropbox Inc., http://www.dropbox.com/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.6 2 | /// 3 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 4 | /// 5 | 6 | import PackageDescription 7 | 8 | let package = Package( 9 | name: "SwiftyDropbox", 10 | platforms: [ 11 | .macOS(.v10_13), 12 | .iOS(.v11), 13 | ], 14 | products: [ 15 | .library(name: "SwiftyDropbox", targets: ["SwiftyDropbox"]), 16 | .library(name: "SwiftyDropboxObjC", targets: ["SwiftyDropboxObjC"]), 17 | ], 18 | targets: [ 19 | .target( 20 | name: "SwiftyDropbox", 21 | path: "Source/SwiftyDropbox", 22 | resources: [.process("PrivacyInfo.xcprivacy")] 23 | ), 24 | .target( 25 | name: "SwiftyDropboxObjC", 26 | dependencies: ["SwiftyDropbox"], 27 | path: "Source/SwiftyDropboxObjC", 28 | resources: [.process("PrivacyInfo.xcprivacy")] 29 | ), 30 | .testTarget( 31 | name: "SwiftyDropboxUnitTests", 32 | dependencies: ["SwiftyDropbox"] 33 | ), 34 | ], 35 | swiftLanguageVersions: [.v5] 36 | ) 37 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Platform/SwiftyDropbox_iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 7.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 10.2.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Platform/SwiftyDropbox_iOS/LoadingViewController.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2020 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | #if canImport(UIKit) 6 | 7 | import Foundation 8 | import UIKit 9 | 10 | /// A VC with a loading spinner at its view center. 11 | class LoadingViewController: UIViewController { 12 | private let loadingSpinner: UIActivityIndicatorView 13 | 14 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { 15 | if #available(iOS 13.0, *) { 16 | loadingSpinner = UIActivityIndicatorView(style: .large) 17 | } else { 18 | self.loadingSpinner = UIActivityIndicatorView(style: .whiteLarge) 19 | } 20 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 21 | } 22 | 23 | @available(*, unavailable, message: "init(coder:) has not been implemented") 24 | required init?(coder: NSCoder) { 25 | fatalError("init(coder:) has not been implemented") 26 | } 27 | 28 | override func viewDidLoad() { 29 | view.backgroundColor = UIColor.black.withAlphaComponent(0.4) 30 | view.addSubview(loadingSpinner) 31 | loadingSpinner.translatesAutoresizingMaskIntoConstraints = false 32 | NSLayoutConstraint.activate([ 33 | loadingSpinner.centerXAnchor.constraint(equalTo: view.centerXAnchor), 34 | loadingSpinner.centerYAnchor.constraint(equalTo: view.centerYAnchor), 35 | ]) 36 | loadingSpinner.startAnimating() 37 | } 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Platform/SwiftyDropbox_iOS/UtilitiesMobile.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2022 Dropbox Inc. All rights reserved. 3 | // 4 | 5 | #if os(iOS) 6 | 7 | import Foundation 8 | import UIKit 9 | 10 | @available(iOS 13.0, *) 11 | extension UIApplication { 12 | public func findKeyWindow() -> UIWindow? { 13 | connectedScenes 14 | .filter({ $0.activationState == .foregroundActive }) 15 | .compactMap({ $0 as? UIWindowScene }) 16 | .first?.windows 17 | .filter(\.isKeyWindow).first 18 | } 19 | } 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Platform/SwiftyDropbox_macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 7.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 10.2.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2016 Dropbox. All rights reserved. 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/AccountRoutes.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | /// Routes for the account namespace 10 | /// For Objective-C compatible routes see DBAccountRoutes 11 | public class AccountRoutes: DropboxTransportClientOwning { 12 | public let client: DropboxTransportClient 13 | required init(client: DropboxTransportClient) { 14 | self.client = client 15 | } 16 | 17 | /// Sets a user's profile photo. 18 | /// 19 | /// - scope: account_info.write 20 | /// 21 | /// - parameter photo: Image to set as the user's new profile photo. 22 | /// 23 | /// - returns: Through the response callback, the caller will receive a `Account.SetProfilePhotoResult` object on 24 | /// success or a `Account.SetProfilePhotoError` object on failure. 25 | @discardableResult public func setProfilePhoto( 26 | photo: Account 27 | .PhotoSourceArg 28 | ) -> RpcRequest { 29 | let route = Account.setProfilePhoto 30 | let serverArgs = Account.SetProfilePhotoArg(photo: photo) 31 | return client.request(route, serverArgs: serverArgs) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/AppAuthReconnectionHelpers.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | // The case string below must match those created by ReconnectionHelpers+Handwritten.swift using 8 | // the route name and namespace as formatted for the generated `Route` object in SwiftTypes.jinja 9 | // Format: "/" e.g., "files/upload_session/append_v2" for Files.uploadSessionAppendV2 10 | enum AppAuthReconnectionHelpers: ReconnectionHelpersShared { 11 | static func rebuildRequest(apiRequest: ApiRequest, client: DropboxTransportClientInternal) throws -> DropboxAppBaseRequestBox { 12 | let info = try persistedRequestInfo(from: apiRequest) 13 | 14 | switch info.namespaceRouteName { 15 | case "files/get_thumbnail_v2": 16 | return .files_getThumbnailV2( 17 | rebuildRequest( 18 | apiRequest: apiRequest, 19 | info: info, 20 | route: Files.getThumbnailV2, 21 | client: client 22 | ) 23 | ) 24 | default: 25 | throw ReconnectionErrorKind.missingReconnectionCase 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/AuthAppAuthRoutes.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | /// Routes for the authAppAuth namespace 10 | /// For Objective-C compatible routes see DBAuthRoutes 11 | public class AuthAppAuthRoutes: DropboxTransportClientOwning { 12 | public let client: DropboxTransportClient 13 | required init(client: DropboxTransportClient) { 14 | self.client = client 15 | } 16 | 17 | /// Creates an OAuth 2.0 access token from the supplied OAuth 1.0 access token. 18 | /// 19 | /// - parameter oauth1Token: The supplied OAuth 1.0 access token. 20 | /// - parameter oauth1TokenSecret: The token secret associated with the supplied access token. 21 | /// 22 | /// - returns: Through the response callback, the caller will receive a `Auth.TokenFromOAuth1Result` object on 23 | /// success or a `Auth.TokenFromOAuth1Error` object on failure. 24 | @available(*, unavailable, message: "tokenFromOauth1 is deprecated.") 25 | @discardableResult public func tokenFromOauth1( 26 | oauth1Token: String, 27 | oauth1TokenSecret: String 28 | ) -> RpcRequest { 29 | let route = Auth.tokenFromOauth1 30 | let serverArgs = Auth.TokenFromOAuth1Arg(oauth1Token: oauth1Token, oauth1TokenSecret: oauth1TokenSecret) 31 | return client.request(route, serverArgs: serverArgs) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/AuthRoutes.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | /// Routes for the auth namespace 10 | /// For Objective-C compatible routes see DBAuthRoutes 11 | public class AuthRoutes: DropboxTransportClientOwning { 12 | public let client: DropboxTransportClient 13 | required init(client: DropboxTransportClient) { 14 | self.client = client 15 | } 16 | 17 | /// Disables the access token used to authenticate the call. If there is a corresponding refresh token for the 18 | /// access token, this disables that refresh token, as well as any other access tokens for that refresh token. 19 | /// 20 | /// 21 | /// - returns: Through the response callback, the caller will receive a `Void` object on success or a `Void` object 22 | /// on failure. 23 | @discardableResult public func tokenRevoke() -> RpcRequest { 24 | let route = Auth.tokenRevoke 25 | return client.request(route) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/Base.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | public class DropboxBase: DropboxTransportClientOwning { 10 | public var client: DropboxTransportClient 11 | 12 | /// Routes within the account namespace. See AccountRoutes for details. 13 | public var account: AccountRoutes! 14 | /// Routes within the auth namespace. See AuthRoutes for details. 15 | public var auth: AuthRoutes! 16 | /// Routes within the check namespace. See CheckRoutes for details. 17 | public var check: CheckRoutes! 18 | /// Routes within the contacts namespace. See ContactsRoutes for details. 19 | public var contacts: ContactsRoutes! 20 | /// Routes within the fileProperties namespace. See FilePropertiesRoutes for details. 21 | public var fileProperties: FilePropertiesRoutes! 22 | /// Routes within the fileRequests namespace. See FileRequestsRoutes for details. 23 | public var fileRequests: FileRequestsRoutes! 24 | /// Routes within the files namespace. See FilesRoutes for details. 25 | public var files: FilesRoutes! 26 | /// Routes within the openid namespace. See OpenidRoutes for details. 27 | public var openid: OpenidRoutes! 28 | /// Routes within the paper namespace. See PaperRoutes for details. 29 | public var paper: PaperRoutes! 30 | /// Routes within the sharing namespace. See SharingRoutes for details. 31 | public var sharing: SharingRoutes! 32 | /// Routes within the teamLog namespace. See TeamLogRoutes for details. 33 | public var teamLog: TeamLogRoutes! 34 | /// Routes within the users namespace. See UsersRoutes for details. 35 | public var users: UsersRoutes! 36 | 37 | public required init(client: DropboxTransportClient) { 38 | self.client = client 39 | 40 | self.account = AccountRoutes(client: client) 41 | self.auth = AuthRoutes(client: client) 42 | self.check = CheckRoutes(client: client) 43 | self.contacts = ContactsRoutes(client: client) 44 | self.fileProperties = FilePropertiesRoutes(client: client) 45 | self.fileRequests = FileRequestsRoutes(client: client) 46 | self.files = FilesRoutes(client: client) 47 | self.openid = OpenidRoutes(client: client) 48 | self.paper = PaperRoutes(client: client) 49 | self.sharing = SharingRoutes(client: client) 50 | self.teamLog = TeamLogRoutes(client: client) 51 | self.users = UsersRoutes(client: client) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/BaseApp.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | public class DropboxAppBase: DropboxTransportClientOwning { 10 | public var client: DropboxTransportClient 11 | 12 | /// Routes within the auth namespace. See AuthAppAuthRoutes for details. 13 | public var auth: AuthAppAuthRoutes! 14 | /// Routes within the check namespace. See CheckAppAuthRoutes for details. 15 | public var check: CheckAppAuthRoutes! 16 | /// Routes within the files namespace. See FilesAppAuthRoutes for details. 17 | public var files: FilesAppAuthRoutes! 18 | /// Routes within the sharing namespace. See SharingAppAuthRoutes for details. 19 | public var sharing: SharingAppAuthRoutes! 20 | 21 | public required init(client: DropboxTransportClient) { 22 | self.client = client 23 | 24 | self.auth = AuthAppAuthRoutes(client: client) 25 | self.check = CheckAppAuthRoutes(client: client) 26 | self.files = FilesAppAuthRoutes(client: client) 27 | self.sharing = SharingAppAuthRoutes(client: client) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/BaseTeam.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | public class DropboxTeamBase: DropboxTransportClientOwning { 10 | public var client: DropboxTransportClient 11 | 12 | /// Routes within the team namespace. See TeamRoutes for details. 13 | public var team: TeamRoutes! 14 | 15 | public required init(client: DropboxTransportClient) { 16 | self.client = client 17 | 18 | self.team = TeamRoutes(client: client) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/CheckAppAuthRoutes.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | /// Routes for the checkAppAuth namespace 10 | /// For Objective-C compatible routes see DBCheckRoutes 11 | public class CheckAppAuthRoutes: DropboxTransportClientOwning { 12 | public let client: DropboxTransportClient 13 | required init(client: DropboxTransportClient) { 14 | self.client = client 15 | } 16 | 17 | /// This endpoint performs App Authentication, validating the supplied app key and secret, and returns the supplied 18 | /// string, to allow you to test your code and connection to the Dropbox API. It has no other effect. If you 19 | /// receive an HTTP 200 response with the supplied query, it indicates at least part of the Dropbox API 20 | /// infrastructure is working and that the app key and secret valid. 21 | /// 22 | /// - parameter query: The string that you'd like to be echoed back to you. 23 | /// 24 | /// - returns: Through the response callback, the caller will receive a `Check.EchoResult` object on success or a 25 | /// `Void` object on failure. 26 | @discardableResult public func app(query: String = "") -> RpcRequest { 27 | let route = Check.app 28 | let serverArgs = Check.EchoArg(query: query) 29 | return client.request(route, serverArgs: serverArgs) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/CheckRoutes.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | /// Routes for the check namespace 10 | /// For Objective-C compatible routes see DBCheckRoutes 11 | public class CheckRoutes: DropboxTransportClientOwning { 12 | public let client: DropboxTransportClient 13 | required init(client: DropboxTransportClient) { 14 | self.client = client 15 | } 16 | 17 | /// This endpoint performs User Authentication, validating the supplied access token, and returns the supplied 18 | /// string, to allow you to test your code and connection to the Dropbox API. It has no other effect. If you 19 | /// receive an HTTP 200 response with the supplied query, it indicates at least part of the Dropbox API 20 | /// infrastructure is working and that the access token is valid. 21 | /// 22 | /// - scope: account_info.read 23 | /// 24 | /// - parameter query: The string that you'd like to be echoed back to you. 25 | /// 26 | /// - returns: Through the response callback, the caller will receive a `Check.EchoResult` object on success or a 27 | /// `Void` object on failure. 28 | @discardableResult public func user(query: String = "") -> RpcRequest { 29 | let route = Check.user 30 | let serverArgs = Check.EchoArg(query: query) 31 | return client.request(route, serverArgs: serverArgs) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/ContactsRoutes.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | /// Routes for the contacts namespace 10 | /// For Objective-C compatible routes see DBContactsRoutes 11 | public class ContactsRoutes: DropboxTransportClientOwning { 12 | public let client: DropboxTransportClient 13 | required init(client: DropboxTransportClient) { 14 | self.client = client 15 | } 16 | 17 | /// Removes all manually added contacts. You'll still keep contacts who are on your team or who you imported. New 18 | /// contacts will be added when you share. 19 | /// 20 | /// - scope: contacts.write 21 | /// 22 | /// 23 | /// - returns: Through the response callback, the caller will receive a `Void` object on success or a `Void` object 24 | /// on failure. 25 | @discardableResult public func deleteManualContacts() -> RpcRequest { 26 | let route = Contacts.deleteManualContacts 27 | return client.request(route) 28 | } 29 | 30 | /// Removes manually added contacts from the given list. 31 | /// 32 | /// - scope: contacts.write 33 | /// 34 | /// - parameter emailAddresses: List of manually added contacts to be deleted. 35 | /// 36 | /// - returns: Through the response callback, the caller will receive a `Void` object on success or a 37 | /// `Contacts.DeleteManualContactsError` object on failure. 38 | @discardableResult public func deleteManualContactsBatch(emailAddresses: [String]) 39 | -> RpcRequest { 40 | let route = Contacts.deleteManualContactsBatch 41 | let serverArgs = Contacts.DeleteManualContactsArg(emailAddresses: emailAddresses) 42 | return client.request(route, serverArgs: serverArgs) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/DropboxAppBaseRequestBox.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | /// Allows for heterogenous collections of typed requests 10 | public enum DropboxAppBaseRequestBox: CustomStringConvertible { 11 | case files_getThumbnailV2(DownloadRequestFile) 12 | 13 | public var description: String { 14 | switch self { 15 | case .files_getThumbnailV2: 16 | return "files/get_thumbnail_v2" 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/OpenidRoutes.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | /// Routes for the openid namespace 10 | /// For Objective-C compatible routes see DBOpenidRoutes 11 | public class OpenidRoutes: DropboxTransportClientOwning { 12 | public let client: DropboxTransportClient 13 | required init(client: DropboxTransportClient) { 14 | self.client = client 15 | } 16 | 17 | /// This route is used for refreshing the info that is found in the id_token during the OIDC flow. This route 18 | /// doesn't require any arguments and will use the scopes approved for the given access token. 19 | /// 20 | /// - scope: openid 21 | /// 22 | /// 23 | /// - returns: Through the response callback, the caller will receive a `Openid.UserInfoResult` object on success or 24 | /// a `Openid.UserInfoError` object on failure. 25 | @discardableResult public func userinfo() -> RpcRequest { 26 | let route = Openid.userinfo 27 | let serverArgs = Openid.UserInfoArgs() 28 | return client.request(route, serverArgs: serverArgs) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/SecondaryEmails.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | /// Datatypes and serializers for the secondary_emails namespace 10 | public class SecondaryEmails { 11 | /// The SecondaryEmail struct 12 | public class SecondaryEmail: CustomStringConvertible, JSONRepresentable { 13 | /// Secondary email address. 14 | public let email: String 15 | /// Whether or not the secondary email address is verified to be owned by a user. 16 | public let isVerified: Bool 17 | public init(email: String, isVerified: Bool) { 18 | stringValidator(maxLength: 255, pattern: "^['#&A-Za-z0-9._%+-]+@[A-Za-z0-9-][A-Za-z0-9.-]*\\.[A-Za-z]{2,15}$")(email) 19 | self.email = email 20 | self.isVerified = isVerified 21 | } 22 | 23 | func json() throws -> JSON { 24 | try SecondaryEmailSerializer().serialize(self) 25 | } 26 | 27 | public var description: String { 28 | do { 29 | return "\(SerializeUtil.prepareJSONForSerialization(try SecondaryEmailSerializer().serialize(self)))" 30 | } catch { 31 | return "Failed to generate description for SecondaryEmail: \(error)" 32 | } 33 | } 34 | } 35 | 36 | public class SecondaryEmailSerializer: JSONSerializer { 37 | public init() {} 38 | public func serialize(_ value: SecondaryEmail) throws -> JSON { 39 | let output = [ 40 | "email": try Serialization._StringSerializer.serialize(value.email), 41 | "is_verified": try Serialization._BoolSerializer.serialize(value.isVerified), 42 | ] 43 | return .dictionary(output) 44 | } 45 | 46 | public func deserialize(_ json: JSON) throws -> SecondaryEmail { 47 | switch json { 48 | case .dictionary(let dict): 49 | let email = try Serialization._StringSerializer.deserialize(dict["email"] ?? .null) 50 | let isVerified = try Serialization._BoolSerializer.deserialize(dict["is_verified"] ?? .null) 51 | return SecondaryEmail(email: email, isVerified: isVerified) 52 | default: 53 | throw JSONSerializerError.deserializeError(type: SecondaryEmail.self, json: json) 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/SharingAppAuthRoutes.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | /// Routes for the sharingAppAuth namespace 10 | /// For Objective-C compatible routes see DBSharingRoutes 11 | public class SharingAppAuthRoutes: DropboxTransportClientOwning { 12 | public let client: DropboxTransportClient 13 | required init(client: DropboxTransportClient) { 14 | self.client = client 15 | } 16 | 17 | /// Get the shared link's metadata. 18 | /// 19 | /// - scope: sharing.read 20 | /// 21 | /// - parameter url: URL of the shared link. 22 | /// - parameter path: If the shared link is to a folder, this parameter can be used to retrieve the metadata for a 23 | /// specific file or sub-folder in this folder. A relative path should be used. 24 | /// - parameter linkPassword: If the shared link has a password, this parameter can be used. 25 | /// 26 | /// - returns: Through the response callback, the caller will receive a `Sharing.SharedLinkMetadata` object on 27 | /// success or a `Sharing.SharedLinkError` object on failure. 28 | @discardableResult public func getSharedLinkMetadata( 29 | url: String, 30 | path: String? = nil, 31 | linkPassword: String? = nil 32 | ) -> RpcRequest { 33 | let route = Sharing.getSharedLinkMetadata 34 | let serverArgs = Sharing.GetSharedLinkMetadataArg(url: url, path: path, linkPassword: linkPassword) 35 | return client.request(route, serverArgs: serverArgs) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/StoneBase.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | // The objects in this file are used by generated code and should not need to be invoked manually. 8 | 9 | public enum RouteAuth: String { 10 | case app 11 | case user 12 | case team 13 | case noauth 14 | } 15 | 16 | public enum RouteHost: String { 17 | case api 18 | case content 19 | case notify 20 | } 21 | 22 | public enum RouteStyle: String { 23 | case rpc 24 | case upload 25 | case download 26 | } 27 | 28 | public struct RouteAttributes { 29 | let auth: [RouteAuth] 30 | let host: RouteHost 31 | let style: RouteStyle 32 | } 33 | 34 | public class Route { 35 | public let name: String 36 | public let version: Int32 37 | public let namespace: String 38 | public let deprecated: Bool 39 | public let argSerializer: ASerial 40 | public let responseSerializer: RSerial 41 | public let errorSerializer: ESerial 42 | public let attributes: RouteAttributes 43 | 44 | public init( 45 | name: String, 46 | version: Int32, 47 | namespace: String, 48 | deprecated: Bool, 49 | argSerializer: ASerial, 50 | responseSerializer: RSerial, 51 | errorSerializer: ESerial, 52 | attributes: RouteAttributes 53 | ) { 54 | self.name = name 55 | self.version = version 56 | self.namespace = namespace 57 | self.deprecated = deprecated 58 | self.argSerializer = argSerializer 59 | self.responseSerializer = responseSerializer 60 | self.errorSerializer = errorSerializer 61 | self.attributes = attributes 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/StoneValidators.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | // The objects in this file are used by generated code and should not need to be invoked manually. 8 | 9 | var _assertFunc: (Bool, String) -> Void = { cond, message in precondition(cond, message) } 10 | 11 | public func setAssertFunc(_ assertFunc: @escaping (Bool, String) -> Void) { 12 | _assertFunc = assertFunc 13 | } 14 | 15 | public func arrayValidator(minItems: Int? = nil, maxItems: Int? = nil, itemValidator: @escaping (T) -> Void) -> ([T]) -> Void { 16 | { (value: [T]) -> Void in 17 | if let minItems = minItems { 18 | _assertFunc(value.count >= minItems, "\(value) must have at least \(minItems) items") 19 | } 20 | 21 | if let maxItems = maxItems { 22 | _assertFunc(value.count <= maxItems, "\(value) must have at most \(maxItems) items") 23 | } 24 | 25 | for el in value { 26 | itemValidator(el) 27 | } 28 | } 29 | } 30 | 31 | public func stringValidator(minLength: Int? = nil, maxLength: Int? = nil, pattern: String? = nil) -> (String) -> Void { 32 | { (value: String) -> Void in 33 | let length = value.count 34 | if let minLength = minLength { 35 | _assertFunc(length >= minLength, "\"\(value)\" must be at least \(minLength) characters") 36 | } 37 | if let maxLength = maxLength { 38 | _assertFunc(length <= maxLength, "\"\(value)\" must be at most \(maxLength) characters") 39 | } 40 | 41 | if let pat = pattern { 42 | // patterns much match entire input sequence 43 | let re = try! NSRegularExpression(pattern: "\\A(?:\(pat))\\z", options: NSRegularExpression.Options()) 44 | let matches = re.matches(in: value, options: NSRegularExpression.MatchingOptions(), range: NSRange(location: 0, length: length)) 45 | _assertFunc(matches.count > 0, "\"\(value) must match pattern \"\(re.pattern)\"") 46 | } 47 | } 48 | } 49 | 50 | public func comparableValidator(minValue: T? = nil, maxValue: T? = nil) -> (T) -> Void { 51 | { (value: T) -> Void in 52 | if let minValue = minValue { 53 | _assertFunc(minValue <= value, "\(value) must be at least \(minValue)") 54 | } 55 | 56 | if let maxValue = maxValue { 57 | _assertFunc(maxValue >= value, "\(value) must be at most \(maxValue)") 58 | } 59 | } 60 | } 61 | 62 | public func nullableValidator(_ internalValidator: @escaping (T) -> Void) -> (T?) -> Void { 63 | { (value: T?) -> Void in 64 | if let value = value { 65 | internalValidator(value) 66 | } 67 | } 68 | } 69 | 70 | public func binaryValidator(minLength: Int?, maxLength: Int?) -> (Data) -> Void { 71 | { (value: Data) -> Void in 72 | let length = value.count 73 | if let minLength = minLength { 74 | _assertFunc(length >= minLength, "\"\(value)\" must be at least \(minLength) bytes") 75 | } 76 | 77 | if let maxLength = maxLength { 78 | _assertFunc(length <= maxLength, "\"\(value)\" must be at most \(maxLength) bytes") 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/TeamLogRoutes.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | /// Routes for the team_log namespace 10 | /// For Objective-C compatible routes see DBTeamLogRoutes 11 | public class TeamLogRoutes: DropboxTransportClientOwning { 12 | public let client: DropboxTransportClient 13 | required init(client: DropboxTransportClient) { 14 | self.client = client 15 | } 16 | 17 | /// Retrieves team events. If the result's hasMore in GetTeamEventsResult field is true, call getEventsContinue with 18 | /// the returned cursor to retrieve more entries. If end_time is not specified in your request, you may use the 19 | /// returned cursor to poll getEventsContinue for new events. Many attributes note 'may be missing due to 20 | /// historical data gap'. Note that the file_operations category and & analogous paper events are not available 21 | /// on all Dropbox Business plans /business/plans-comparison. Use features/get_values 22 | /// /developers/documentation/http/teams#team-features-get_values to check for this feature. Permission : Team 23 | /// Auditing. 24 | /// 25 | /// - scope: events.read 26 | /// 27 | /// - parameter limit: The maximal number of results to return per call. Note that some calls may not return limit 28 | /// number of events, and may even return no events, even with `has_more` set to true. In this case, callers 29 | /// should fetch again using getEventsContinue. 30 | /// - parameter accountId: Filter the events by account ID. Return only events with this account_id as either Actor, 31 | /// Context, or Participants. 32 | /// - parameter time: Filter by time range. 33 | /// - parameter category: Filter the returned events to a single category. Note that category shouldn't be provided 34 | /// together with event_type. 35 | /// - parameter eventType: Filter the returned events to a single event type. Note that event_type shouldn't be 36 | /// provided together with category. 37 | /// 38 | /// - returns: Through the response callback, the caller will receive a `TeamLog.GetTeamEventsResult` object on 39 | /// success or a `TeamLog.GetTeamEventsError` object on failure. 40 | @discardableResult public func getEvents( 41 | limit: UInt32 = 1_000, 42 | accountId: String? = nil, 43 | time: TeamCommon.TimeRange? = nil, 44 | category: TeamLog.EventCategory? = nil, 45 | eventType: TeamLog.EventTypeArg? = nil 46 | ) -> RpcRequest { 47 | let route = TeamLog.getEvents 48 | let serverArgs = TeamLog.GetTeamEventsArg(limit: limit, accountId: accountId, time: time, category: category, eventType: eventType) 49 | return client.request(route, serverArgs: serverArgs) 50 | } 51 | 52 | /// Once a cursor has been retrieved from getEvents, use this to paginate through all events. Permission : Team 53 | /// Auditing. 54 | /// 55 | /// - scope: events.read 56 | /// 57 | /// - parameter cursor: Indicates from what point to get the next set of events. 58 | /// 59 | /// - returns: Through the response callback, the caller will receive a `TeamLog.GetTeamEventsResult` object on 60 | /// success or a `TeamLog.GetTeamEventsContinueError` object on failure. 61 | @discardableResult public func getEventsContinue(cursor: String) 62 | -> RpcRequest { 63 | let route = TeamLog.getEventsContinue 64 | let serverArgs = TeamLog.GetTeamEventsContinueArg(cursor: cursor) 65 | return client.request(route, serverArgs: serverArgs) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Generated/UsersCommon.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | 9 | /// Datatypes and serializers for the users_common namespace 10 | public class UsersCommon { 11 | /// What type of account this user has. 12 | public enum AccountType: CustomStringConvertible, JSONRepresentable { 13 | /// The basic account type. 14 | case basic 15 | /// The Dropbox Pro account type. 16 | case pro 17 | /// The Dropbox Business account type. 18 | case business 19 | 20 | func json() throws -> JSON { 21 | try AccountTypeSerializer().serialize(self) 22 | } 23 | 24 | public var description: String { 25 | do { 26 | return "\(SerializeUtil.prepareJSONForSerialization(try AccountTypeSerializer().serialize(self)))" 27 | } catch { 28 | return "Failed to generate description for AccountType: \(error)" 29 | } 30 | } 31 | } 32 | 33 | public class AccountTypeSerializer: JSONSerializer { 34 | public init() {} 35 | public func serialize(_ value: AccountType) throws -> JSON { 36 | switch value { 37 | case .basic: 38 | var d = [String: JSON]() 39 | d[".tag"] = .str("basic") 40 | return .dictionary(d) 41 | case .pro: 42 | var d = [String: JSON]() 43 | d[".tag"] = .str("pro") 44 | return .dictionary(d) 45 | case .business: 46 | var d = [String: JSON]() 47 | d[".tag"] = .str("business") 48 | return .dictionary(d) 49 | } 50 | } 51 | 52 | public func deserialize(_ json: JSON) throws -> AccountType { 53 | switch json { 54 | case .dictionary(let d): 55 | let tag = try Serialization.getTag(d) 56 | switch tag { 57 | case "basic": 58 | return AccountType.basic 59 | case "pro": 60 | return AccountType.pro 61 | case "business": 62 | return AccountType.business 63 | default: 64 | throw JSONSerializerError.unknownTag(type: AccountType.self, json: json, tag: tag) 65 | } 66 | default: 67 | throw JSONSerializerError.deserializeError(type: AccountType.self, json: json) 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/BackgroundClientSetupInfo.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2023 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | public class DefaultBackgroundExtensionSessionCreationInfo { 8 | let backgroundSessionIdentifier: String 9 | let sharedContainerIdentifier: String 10 | 11 | public init(backgroundSessionIdentifier: String, sharedContainerIdentifier: String) { 12 | self.backgroundSessionIdentifier = backgroundSessionIdentifier 13 | self.sharedContainerIdentifier = sharedContainerIdentifier 14 | } 15 | } 16 | 17 | public class CustomBackgroundExtensionSessionCreationInfo { 18 | let backgroundTransportClient: DropboxTransportClient? 19 | let backgroundSessionConfiguration: NetworkSessionConfiguration? 20 | 21 | var backgroundSessionIdentifier: String? { 22 | if let backgroundTransportClient = backgroundTransportClient { 23 | return backgroundTransportClient.identifier 24 | } else { 25 | return backgroundSessionConfiguration?.identifier 26 | } 27 | } 28 | 29 | public init(backgroundTransportClient: DropboxTransportClient?) { 30 | self.backgroundTransportClient = backgroundTransportClient 31 | self.backgroundSessionConfiguration = nil 32 | } 33 | 34 | public init(backgroundSessionConfiguration: NetworkSessionConfiguration?) { 35 | self.backgroundTransportClient = nil 36 | self.backgroundSessionConfiguration = backgroundSessionConfiguration 37 | } 38 | } 39 | 40 | public class BackgroundExtensionSessionCreationInfo { 41 | let defaultInfo: DefaultBackgroundExtensionSessionCreationInfo? 42 | let customInfo: CustomBackgroundExtensionSessionCreationInfo? 43 | 44 | var identifier: String? { 45 | if let defaultInfo = defaultInfo { 46 | return defaultInfo.backgroundSessionIdentifier 47 | } else { 48 | return customInfo?.backgroundSessionIdentifier 49 | } 50 | } 51 | 52 | public init(defaultInfo: DefaultBackgroundExtensionSessionCreationInfo) { 53 | self.defaultInfo = defaultInfo 54 | self.customInfo = nil 55 | } 56 | 57 | public init(customInfo: CustomBackgroundExtensionSessionCreationInfo) { 58 | self.defaultInfo = nil 59 | self.customInfo = customInfo 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/CertificatePinning.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | public enum AuthChallenge { 8 | public typealias Handler = (URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?) 9 | } 10 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/Custom/CustomTasks.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | public class BatchUploadTask { 8 | let uploadData: BatchUploadData 9 | 10 | init(uploadData: BatchUploadData) { 11 | self.uploadData = uploadData 12 | } 13 | 14 | public func cancel() { 15 | uploadData.cancel = true 16 | uploadData.startRequests.values.forEach { $0.cancel() } 17 | uploadData.appendRequests.values.forEach { $0.cancel() } 18 | uploadData.finishRequest?.cancel() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/DropboxAppClient.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | /// The client for the App API. Call routes using the namespaces inside this object (inherited from parent). 8 | 9 | public class DropboxAppClient: DropboxAppBase { 10 | private var transportClient: DropboxTransportClient 11 | 12 | /// Designated Initializer. 13 | /// 14 | /// - Parameter transportClient: The underlying DropboxTransportClient to make API calls. 15 | public init(transportClient: DropboxTransportClient) { 16 | self.transportClient = transportClient 17 | super.init(client: transportClient) 18 | } 19 | 20 | /// Initializer used by DropboxTransportClientOwning in tests. 21 | /// 22 | /// - Parameter client: The underlying DropboxTransportClient to make API calls. 23 | required convenience init(client: DropboxTransportClient) { 24 | self.init(transportClient: client) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/DropboxTeamClient.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | /// The client for the Business API. Call routes using the namespaces inside this object (inherited from parent). 8 | 9 | public class DropboxTeamClient: DropboxTeamBase { 10 | public let accessTokenProvider: AccessTokenProvider 11 | 12 | /// Initialize a client with a static accessToken string. 13 | /// Use this method if your access token is long-lived. 14 | /// 15 | /// - Parameter accessToken: Static access token string. 16 | public convenience init(accessToken: String) { 17 | let transportClient = DropboxTransportClientImpl(accessToken: accessToken) 18 | self.init(transportClient: transportClient) 19 | } 20 | 21 | /// Initialize a client with an `AccessTokenProvider`. 22 | /// Use this method if your access token is short-lived. 23 | /// See `ShortLivedAccessTokenProvider` for a default implementation. 24 | /// 25 | /// - Parameters: 26 | /// - accessTokenProvider: Access token provider that wraps a short-lived token and its refresh logic. 27 | /// - sessionConfiguration: Optional custom network session configuration 28 | public convenience init( 29 | accessTokenProvider: AccessTokenProvider, 30 | sessionConfiguration: NetworkSessionConfiguration? = nil 31 | ) { 32 | let transportClient = DropboxTransportClientImpl(accessTokenProvider: accessTokenProvider, sessionConfiguration: sessionConfiguration) 33 | self.init(transportClient: transportClient) 34 | } 35 | 36 | /// Initialize a client with an `DropboxAccessToken`. 37 | /// 38 | /// - Parameters: 39 | /// - accessToken: The token itself, could be long or short lived. 40 | /// - dropboxOauthManager: an oauthManager, used for creating the token provider. 41 | /// - sessionConfiguration: Optional custom network session configuration 42 | public convenience init( 43 | accessToken: DropboxAccessToken, 44 | dropboxOauthManager: DropboxOAuthManager, 45 | sessionConfiguration: NetworkSessionConfiguration? = nil 46 | ) { 47 | let accessTokenProvider = dropboxOauthManager.accessTokenProviderForToken(accessToken) 48 | let transportClient = DropboxTransportClientImpl(accessTokenProvider: accessTokenProvider, sessionConfiguration: sessionConfiguration) 49 | self.init(transportClient: transportClient) 50 | } 51 | 52 | /// Designated Initializer. 53 | /// 54 | /// - Parameter transportClient: The underlying DropboxTransportClient to make API calls. 55 | public init(transportClient: DropboxTransportClient) { 56 | guard let accessTokenProvider = transportClient.accessTokenProvider else { 57 | fatalError("misconfigured user auth transport client") 58 | } 59 | self.accessTokenProvider = accessTokenProvider 60 | super.init(client: transportClient) 61 | } 62 | 63 | /// Initializer used by DropboxTransportClientOwning in tests. 64 | /// 65 | /// - Parameter client: The underlying DropboxTransportClient to make API calls. 66 | required convenience init(client: DropboxTransportClient) { 67 | self.init(transportClient: client) 68 | } 69 | 70 | /// Creates a new DropboxClient instance for the team member id. 71 | /// 72 | /// - Parameter memberId: Team member id. 73 | /// - Returns: A new DropboxClient instance that can be used to call APIs on the team member's behalf. 74 | public func asMember(_ memberId: String) -> DropboxClient { 75 | DropboxClient(accessTokenProvider: accessTokenProvider, selectUser: memberId) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/DropboxTransportClientInterface.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2023 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | public protocol DropboxTransportClient { 8 | var selectUser: String? { get set } 9 | var pathRoot: Common.PathRoot? { get set } 10 | var didFinishBackgroundEvents: (() -> Void)? { get set } 11 | var accessTokenProvider: AccessTokenProvider? { get set } 12 | var isBackgroundClient: Bool { get } 13 | 14 | static var serializeOnBackgroundThread: Bool { get set } 15 | 16 | var identifier: String? { get } 17 | 18 | func request( 19 | _ route: Route 20 | ) -> RpcRequest 21 | 22 | func request( 23 | _ route: Route, 24 | serverArgs: ASerial.ValueType? 25 | ) -> RpcRequest 26 | 27 | func request( 28 | _ route: Route, 29 | serverArgs: ASerial.ValueType, 30 | input: UploadBody 31 | ) -> UploadRequest 32 | 33 | func request( 34 | _ route: Route, 35 | serverArgs: ASerial.ValueType, 36 | overwrite: Bool, 37 | destination: URL 38 | ) -> DownloadRequestFile 39 | 40 | func request( 41 | _ route: Route, 42 | serverArgs: ASerial.ValueType 43 | ) -> DownloadRequestMemory 44 | 45 | func shutdown() 46 | } 47 | 48 | protocol DropboxTransportClientInternal: DropboxTransportClient { 49 | var manager: NetworkSessionManager { get } 50 | var longpollManager: NetworkSessionManager { get } 51 | 52 | func reconnectRequest( 53 | _ route: Route, 54 | apiRequest: ApiRequest 55 | ) -> UploadRequest 56 | 57 | func reconnectRequest( 58 | _ route: Route, 59 | apiRequest: ApiRequest, 60 | overwrite: Bool, 61 | destination: URL 62 | ) -> DownloadRequestFile 63 | } 64 | 65 | typealias SessionCreation = (NetworkSessionConfiguration, CombinedURLSessionDelegate, OperationQueue) -> NetworkSession 66 | let DefaultSessionCreation: SessionCreation = { configuration, delegate, queue in 67 | URLSession(configuration: configuration.urlSessionConfiguration, delegate: delegate, delegateQueue: queue) 68 | } 69 | 70 | public typealias HeadersForRouteRequest = (RouteHost) -> [String: String] 71 | 72 | public enum AuthStrategy { 73 | case accessToken(AccessTokenProvider) 74 | case appKeyAndSecret(String, String) 75 | 76 | var accessTokenHeaderValue: String? { 77 | if case .accessToken(let provider) = self { 78 | return "Bearer \(provider.accessToken)" 79 | } 80 | return nil 81 | } 82 | 83 | var appKeyAndSecretHeaderValue: String? { 84 | if case .appKeyAndSecret(let appKey, let appSecret) = self { 85 | let authString = "\(appKey):\(appSecret)" 86 | let authData = authString.data(using: .utf8) ?? .init() 87 | return "Basic \(authData.base64EncodedString())" 88 | } 89 | return nil 90 | } 91 | 92 | var accessTokenProvider: AccessTokenProvider? { 93 | if case .accessToken(let provider) = self { 94 | return provider 95 | } 96 | return nil 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/FilesAcccess.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2022 Dropbox Inc. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | public enum FilesAccessError: Error { 8 | case errorMovingToTempLocation(Error) 9 | case errorMovingFromTempLocation(Error) 10 | case errorMovingFromTempLocationDestinationCollision(String) 11 | case couldNotReadErrorDataAtUrl(Error) 12 | } 13 | 14 | @objc(DBFilesAccess) 15 | public protocol FilesAccess { 16 | func moveFileToTemporaryLocation(from networkSessionTemporaryLocation: URL) throws -> URL 17 | func moveFile(from temporaryLocation: URL, to finalUrl: URL, overwrite: Bool) throws -> URL 18 | func errorData(from location: URL) throws -> Data 19 | } 20 | 21 | public class FilesAccessImpl: FilesAccess { 22 | var fileManager: FileManagerProtocol 23 | let tempFolder = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true) 24 | 25 | public convenience init() { 26 | self.init(fileManager: FileManager.default) 27 | } 28 | 29 | init(fileManager: FileManagerProtocol) { 30 | self.fileManager = fileManager 31 | setupDirectories() 32 | } 33 | 34 | private func setupDirectories() { 35 | if !fileManager.fileExists(atPath: tempFolder.path) { 36 | try! fileManager.createDirectory(at: tempFolder, withIntermediateDirectories: true, attributes: nil) 37 | } 38 | } 39 | 40 | public func moveFileToTemporaryLocation(from networkSessionTemporaryLocation: URL) throws -> URL { 41 | do { 42 | let tempOutputURL = tempFolder.appendingPathComponent(UUID().uuidString) 43 | try fileManager.moveItem(at: networkSessionTemporaryLocation, to: tempOutputURL) 44 | return tempOutputURL 45 | } catch { 46 | throw FilesAccessError.errorMovingToTempLocation(error) 47 | } 48 | } 49 | 50 | public func moveFile(from temporaryLocation: URL, to finalUrl: URL, overwrite: Bool) throws -> URL { 51 | if fileManager.fileExists(atPath: finalUrl.path) { 52 | if overwrite { 53 | do { 54 | try fileManager.removeItem(at: finalUrl) 55 | } catch { 56 | throw FilesAccessError.errorMovingFromTempLocation(error) 57 | } 58 | } else { 59 | throw FilesAccessError.errorMovingFromTempLocationDestinationCollision(finalUrl.path) 60 | } 61 | } 62 | 63 | do { 64 | try fileManager.moveItem(at: temporaryLocation, to: finalUrl) 65 | return finalUrl 66 | } catch { 67 | throw FilesAccessError.errorMovingFromTempLocation(error) 68 | } 69 | } 70 | 71 | public func errorData(from location: URL) throws -> Data { 72 | do { 73 | let data = try fileManager.contents(atPath: location.path).orThrow() 74 | try fileManager.removeItem(at: location) 75 | return data 76 | } catch { 77 | throw FilesAccessError.couldNotReadErrorDataAtUrl(error) 78 | } 79 | } 80 | } 81 | 82 | protocol FileManagerProtocol { 83 | func fileExists(atPath: String) -> Bool 84 | func contents(atPath: String) -> Data? 85 | func createDirectory(at: URL, withIntermediateDirectories: Bool, attributes: [FileAttributeKey: Any]?) throws 86 | func moveItem(atPath: String, toPath: String) throws 87 | func moveItem(at: URL, to: URL) throws 88 | func removeItem(at: URL) throws 89 | } 90 | 91 | extension FileManager: FileManagerProtocol {} 92 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/GlobalErrorResponseHandler.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Similar to `DBGlobalErrorResponseHandler` in the Objc SDK 4 | /// It does not have special handling for route errors, which end up type-erased right now 5 | /// It also does not allow you to easily retry requests yet, like Objc's does. 6 | /// Call `registerGlobalErrorHandler` to register a global error handler callback 7 | /// Call `deregisterGlobalErrorHandler` to deregister it 8 | /// Call `deregisterAllGlobalErrorHandlers` to deregister all global error handler callbacks 9 | public class GlobalErrorResponseHandler { 10 | /// Singleton instance of `GlobalErrorResponseHandler` 11 | public static var shared = { GlobalErrorResponseHandler() }() 12 | 13 | private struct Handler { 14 | let callback: (CallError) -> Void 15 | let queue: OperationQueue 16 | } 17 | 18 | // Locked state 19 | private struct State { 20 | var handlers: [String:Handler] = [:] 21 | } 22 | 23 | private var state = UnfairLock(value: State()) 24 | 25 | internal init() { } 26 | 27 | internal func reportGlobalError(_ error: CallError) { 28 | state.read { lockedState in 29 | lockedState.handlers.forEach { _, handler in 30 | handler.queue.addOperation { 31 | handler.callback(error) 32 | } 33 | } 34 | } 35 | } 36 | 37 | 38 | /// Register a callback to be called in addition to the normal completion handler for a request. 39 | /// You can use the callback to accomplish global error handling, such as logging errors or logging a user out after an `AuthError`. 40 | /// - Parameters: 41 | /// - callback: The function you'd like called when an error occurs, it is provided a type-erased `CallError` that you can switch on. If you know the specific route error type you want to look for, you can unbox and cast the contained route error value to that type, in the case of a route error. 42 | /// - queue: The queue on which the callback should be called. Defaults to the main queue via `OperationQueue.main`. 43 | /// - Returns: A key you can use to deregister the callback later. It's just a UUID string. 44 | @discardableResult 45 | public func registerGlobalErrorHandler(_ callback: @escaping (CallError) -> Void, queue: OperationQueue = .main) -> String { 46 | let key = UUID().uuidString 47 | state.mutate { lockedState in 48 | lockedState.handlers[key] = Handler(callback: callback, queue: queue) 49 | } 50 | return key 51 | } 52 | 53 | 54 | /// Remove a global error handler callback by its key 55 | /// - Parameter key: The key returned when you registered the callback 56 | public func deregisterGlobalErrorHandler(key: String) { 57 | state.mutate { lockedState in 58 | lockedState.handlers[key] = nil 59 | } 60 | } 61 | 62 | 63 | /// Remove all global error handler callbacks, regardless of key. 64 | public func deregisterAllGlobalErrorHandlers() { 65 | state.mutate { lockedState in 66 | lockedState.handlers = [:] 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/NetworkSession/Mocks/MockNetworkSession.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2022 Dropbox Inc. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | class MockNetworkSession: NetworkSession { 8 | var identifier: String? 9 | 10 | init() {} 11 | 12 | required init(configuration: URLSessionConfiguration) { 13 | fatalError() 14 | } 15 | 16 | var tasksPendingReconnection: [NetworkTask] = [] 17 | var tasks: [NetworkTaskTag: NetworkTask] = [:] 18 | var mockInputs: [NetworkTaskTag: MockInput] = [:] 19 | 20 | var invalidateCalled = false 21 | 22 | func dataTask(request: URLRequest, networkTaskTag: NetworkTaskTag?) -> NetworkDataTask { 23 | register( 24 | task: MockNetworkTaskDelegate(request: request), 25 | networkTaskTag: networkTaskTag 26 | ) 27 | } 28 | 29 | func dataTask(request: URLRequest, networkTaskTag: NetworkTaskTag?, completionHandler: @escaping NetworkDataTaskCompletion) -> NetworkDataTask { 30 | register( 31 | task: MockNetworkDataTaskCompletion( 32 | request: request, 33 | mockInput: { [weak self] in 34 | networkTaskTag.flatMap { self?.mockInputs[$0] } 35 | }, 36 | completionHandler: completionHandler 37 | ), 38 | networkTaskTag: networkTaskTag 39 | ) 40 | } 41 | 42 | func uploadTaskData(request: URLRequest, data: Data, networkTaskTag: NetworkTaskTag?) -> NetworkUploadTask { 43 | register( 44 | task: MockNetworkTaskDelegate(request: request), 45 | networkTaskTag: networkTaskTag 46 | ) 47 | } 48 | 49 | func uploadTaskStream(request: URLRequest, networkTaskTag: NetworkTaskTag?) -> NetworkUploadTask { 50 | register( 51 | task: MockNetworkTaskDelegate(request: request), 52 | networkTaskTag: networkTaskTag 53 | ) 54 | } 55 | 56 | func uploadTaskFile(request: URLRequest, file: URL, networkTaskTag: NetworkTaskTag?) -> NetworkUploadTask { 57 | register( 58 | task: MockNetworkTaskDelegate(request: request), 59 | networkTaskTag: networkTaskTag 60 | ) 61 | } 62 | 63 | func downloadTask(request: URLRequest, networkTaskTag: NetworkTaskTag?) -> NetworkDownloadTask { 64 | register( 65 | task: MockNetworkTaskDelegate(request: request), 66 | networkTaskTag: networkTaskTag 67 | ) 68 | } 69 | 70 | func register(task: T, networkTaskTag: NetworkTaskTag?) -> T { 71 | tasks[networkTaskTag ?? UUID().uuidString] = task 72 | return task 73 | } 74 | 75 | func getAllNetworkTasks(completionHandler: ([NetworkTask]) -> Void) { 76 | completionHandler(tasksPendingReconnection) 77 | } 78 | 79 | func invalidateAndCancel() { 80 | invalidateCalled = true 81 | } 82 | } 83 | 84 | enum MockInput { 85 | case none 86 | case success(json: [String: Any]) 87 | case downloadSuccess(json: [String: Any], downloadLocation: URL) 88 | case requestError(json: [String: Any], code: NetworkStatusCode) 89 | case routeError(json: [String: Any]) 90 | case clientError(error: ClientError) 91 | } 92 | 93 | enum MockInputWithModel { 94 | case none 95 | case success(model: JSONRepresentable) 96 | case downloadSuccess(model: JSONRepresentable, downloadLocation: URL) 97 | case requestError(model: JSONRepresentable, code: NetworkStatusCode) 98 | case routeError(model: JSONRepresentable) 99 | } 100 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/NoopRequest.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2023 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | /// Used internally when a URLSessionTask cannot be constructed during shutdown 8 | class NoopApiRequest: ApiRequest { 9 | init() {} 10 | 11 | func handleCompletion(error: ClientError?) {} 12 | 13 | func handleRecieve(data: Data) {} 14 | 15 | func handleDownloadFinished(location: URL) {} 16 | 17 | func handleSentBodyData(totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {} 18 | 19 | func handleWroteDownloadData(totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {} 20 | 21 | var identifier: Int { 22 | networkTask?.taskIdentifier ?? -1 23 | } 24 | 25 | var taskDescription: String? 26 | 27 | var earliestBeginDate: Date? 28 | 29 | func setProgressHandler(_ handler: @escaping (Progress) -> Void) -> Self { 30 | self 31 | } 32 | 33 | func setCompletionHandlerProvider(queue: DispatchQueue?, completionHandlerProvider: RequestCompletionHandlerProvider) -> Self { 34 | self 35 | } 36 | 37 | func cancel() {} 38 | 39 | func setCleanupHandler(_ handler: @escaping () -> Void) {} 40 | 41 | var networkTask: NetworkTask? = NoopNetworkTask() 42 | } 43 | 44 | class NoopNetworkTask: NetworkTask { 45 | func resume() {} 46 | 47 | func cancel() {} 48 | 49 | var response: URLResponse? 50 | 51 | var error: Error? 52 | 53 | var originalRequest: URLRequest? 54 | 55 | var taskIdentifier: Int = Int.random(in: 1 ..< Int.max) 56 | 57 | var taskDescription: String? 58 | 59 | var earliestBeginDate: Date? 60 | } 61 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/OAuth/OAuthConstants.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2020 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | /// Contains the keys of URL queries and responses in auth flow. 8 | enum OAuthConstants { 9 | static let codeChallengeKey = "code_challenge" 10 | static let codeChallengeMethodKey = "code_challenge_method" 11 | static let tokenAccessTypeKey = "token_access_type" 12 | static let responseTypeKey = "response_type" 13 | static let scopeKey = "scope" 14 | static let includeGrantedScopesKey = "include_granted_scopes" 15 | static let stateKey = "state" 16 | static let extraQueryParamsKey = "extra_query_params" 17 | static let oauthCodeKey = "oauth_code" 18 | static let oauthTokenKey = "oauth_token" 19 | static let oauthSecretKey = "oauth_token_secret" 20 | static let uidKey = "uid" 21 | static let errorKey = "error" 22 | static let errorDescription = "error_description" 23 | } 24 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/OAuth/OAuthUtils.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2020 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | /// Contains utility methods used in auth flow. e.g. method to construct URL query. 8 | enum OAuthUtils { 9 | static func createPkceCodeFlowParams(for authSession: OAuthPKCESession) -> [URLQueryItem] { 10 | var params = [URLQueryItem]() 11 | if let scopeString = authSession.scopeRequest?.scopeString { 12 | params.append(URLQueryItem(name: OAuthConstants.scopeKey, value: scopeString)) 13 | } 14 | if let scopeRequest = authSession.scopeRequest, scopeRequest.includeGrantedScopes { 15 | params.append( 16 | URLQueryItem(name: OAuthConstants.includeGrantedScopesKey, value: scopeRequest.scopeType.rawValue) 17 | ) 18 | } 19 | let pkceData = authSession.pkceData 20 | params.append(contentsOf: [ 21 | URLQueryItem(name: OAuthConstants.codeChallengeKey, value: pkceData.codeChallenge), 22 | URLQueryItem(name: OAuthConstants.codeChallengeMethodKey, value: pkceData.codeChallengeMethod), 23 | URLQueryItem(name: OAuthConstants.tokenAccessTypeKey, value: authSession.tokenAccessType), 24 | URLQueryItem(name: OAuthConstants.responseTypeKey, value: authSession.responseType), 25 | ]) 26 | return params 27 | } 28 | 29 | /// Extracts auth response parameters from URL and removes percent encoding. 30 | /// Response parameters from DAuth via the Dropbox app are in the query component. 31 | static func extractDAuthResponseFromUrl(_ url: URL) -> [String: String] { 32 | extractQueryParamsFromUrlString(url.absoluteString) 33 | } 34 | 35 | /// Extracts auth response parameters from URL and removes percent encoding. 36 | /// Response parameters OAuth 2 code flow (RFC6749 4.1.2) are in the query component. 37 | static func extractOAuthResponseFromCodeFlowUrl(_ url: URL) -> [String: String] { 38 | extractQueryParamsFromUrlString(url.absoluteString) 39 | } 40 | 41 | /// Extracts auth response parameters from URL and removes percent encoding. 42 | /// Response parameters from OAuth 2 token flow (RFC6749 4.2.2) are in the fragment component. 43 | static func extractOAuthResponseFromTokenFlowUrl(_ url: URL) -> [String: String] { 44 | guard let urlComponents = URLComponents(string: url.absoluteString), 45 | let responseString = urlComponents.fragment else { 46 | return [:] 47 | } 48 | // Create a query only URL string and extract its individual query parameters. 49 | return extractQueryParamsFromUrlString("?\(responseString)") 50 | } 51 | 52 | /// Extracts query parameters from URL and removes percent encoding. 53 | private static func extractQueryParamsFromUrlString(_ urlString: String) -> [String: String] { 54 | guard let urlComponents = URLComponents(string: urlString), 55 | let queryItems = urlComponents.queryItems else { 56 | return [:] 57 | } 58 | return queryItems.reduce(into: [String: String]()) { result, queryItem in 59 | result[queryItem.name] = queryItem.value 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/OAuth/Reachability.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2022 Dropbox Inc. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | import SystemConfiguration 7 | 8 | class Reachability { 9 | /// From http://stackoverflow.com/questions/25623272/how-to-use-scnetworkreachability-in-swift/25623647#25623647. 10 | /// 11 | /// This method uses `SCNetworkReachabilityCreateWithAddress` to create a reference to monitor the example host 12 | /// defined by our zeroed `zeroAddress` struct. From this reference, we can extract status flags regarding the 13 | /// reachability of this host, using `SCNetworkReachabilityGetFlags`. 14 | 15 | class func connectedToNetwork() -> Bool { 16 | var zeroAddress = sockaddr_in() 17 | zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress)) 18 | zeroAddress.sin_family = sa_family_t(AF_INET) 19 | 20 | guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, { 21 | $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { 22 | SCNetworkReachabilityCreateWithAddress(nil, $0) 23 | } 24 | }) else { 25 | return false 26 | } 27 | 28 | var flags: SCNetworkReachabilityFlags = [] 29 | if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) { 30 | return false 31 | } 32 | 33 | let isReachable = flags.contains(.reachable) 34 | let needsConnection = flags.contains(.connectionRequired) 35 | return (isReachable && !needsConnection) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/Request+Async.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 Dropbox Inc. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | public protocol HasRequestResponse { 8 | associatedtype ValueType 9 | associatedtype ESerial: JSONSerializer 10 | 11 | @discardableResult 12 | func response( 13 | queue: DispatchQueue?, 14 | completionHandler: @escaping (ValueType?, CallError?) -> Void 15 | ) -> Self 16 | } 17 | 18 | @available(iOS 13.0, macOS 10.15, *) 19 | extension HasRequestResponse { 20 | /// Async wrapper for retrieving a request's response 21 | /// 22 | /// This could have a better name, but this avoids a collision with the other `response` methods 23 | public func responseResult( 24 | ) async -> Result> { 25 | await withCheckedContinuation { continuation in 26 | self.response(queue: nil) { result, error in 27 | if let result { 28 | continuation.resume(returning: .success(result)) 29 | } else if let error { 30 | continuation.resume(returning: .failure(error)) 31 | } else { 32 | // this should never happen 33 | continuation.resume(returning: .failure(.clientError(.unexpectedState))) 34 | } 35 | } 36 | } 37 | } 38 | 39 | /// Async wrapper for retrieving a request's response 40 | /// 41 | /// Same thing as `responseResult` but using async throws instead of returing a Result 42 | public func response( 43 | ) async throws -> ValueType { 44 | try await responseResult().get() 45 | } 46 | } 47 | 48 | extension RpcRequest: HasRequestResponse {} 49 | extension UploadRequest: HasRequestResponse {} 50 | extension DownloadRequestFile: HasRequestResponse {} 51 | extension DownloadRequestMemory: HasRequestResponse {} 52 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/RequestMap.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2022 Dropbox Inc. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | protocol ApiRequestBox { 8 | var value: ApiRequest? { get } 9 | init(value: ApiRequest) 10 | } 11 | 12 | class WeakApiRequestBox: ApiRequestBox { 13 | weak var value: ApiRequest? 14 | required init(value: ApiRequest) { 15 | self.value = value 16 | } 17 | } 18 | 19 | class PendingReconnectionStrongApiRequestBox: ApiRequestBox { 20 | var value: ApiRequest? { 21 | strongValue 22 | } 23 | 24 | var strongValue: ApiRequest 25 | required init(value: ApiRequest) { 26 | self.strongValue = value 27 | } 28 | } 29 | 30 | protocol RequestMap { 31 | func set(request: ApiRequest, taskIdentifier: Int) 32 | func setPendingReconnection(request: ApiRequest, taskIdentifier: Int) 33 | func getRequest(taskIdentifier: Int) -> ApiRequest? 34 | func getAllRequests() -> [ApiRequest] 35 | func getAllPendingReconnectionRequests() -> [ApiRequest] 36 | func weakifyReferencesToReconnectedRequests() 37 | func removeRequest(taskIdentifier: Int) 38 | func removeAllRequests() 39 | } 40 | 41 | class RequestMapImpl: RequestMap { 42 | private var map: [Int: ApiRequestBox] = [:] 43 | private var cleanupThreshold: Int = 250 44 | 45 | init() {} 46 | 47 | func setPendingReconnection(request: ApiRequest, taskIdentifier: Int) { 48 | map[taskIdentifier] = PendingReconnectionStrongApiRequestBox(value: request) 49 | } 50 | 51 | func set(request: ApiRequest, taskIdentifier: Int) { 52 | map[taskIdentifier] = WeakApiRequestBox(value: request) 53 | 54 | if map.count >= cleanupThreshold { 55 | cleanupEmptyBoxes() 56 | } 57 | } 58 | 59 | func getRequest(taskIdentifier: Int) -> ApiRequest? { 60 | map[taskIdentifier]?.value 61 | } 62 | 63 | func getAllRequests() -> [ApiRequest] { 64 | Array(map.values.compactMap(\.value)) 65 | } 66 | 67 | func getAllPendingReconnectionRequests() -> [ApiRequest] { 68 | let isPending: (ApiRequestBox) -> Bool = { $0 is PendingReconnectionStrongApiRequestBox } 69 | return Array(map.values.filter(isPending).compactMap(\.value)) 70 | } 71 | 72 | func weakifyReferencesToReconnectedRequests() { 73 | map = map.mapValues { box in 74 | if let box = box as? PendingReconnectionStrongApiRequestBox { 75 | return WeakApiRequestBox(value: box.strongValue) 76 | } 77 | return box 78 | } 79 | } 80 | 81 | func cleanupEmptyBoxes() { 82 | map = map.filter { _, box in 83 | if let box = box as? WeakApiRequestBox, box.value == nil { 84 | return false 85 | } 86 | return true 87 | } 88 | } 89 | 90 | func removeRequest(taskIdentifier: Int) { 91 | map[taskIdentifier] = nil 92 | } 93 | 94 | func removeAllRequests() { 95 | map = [:] 96 | } 97 | 98 | func __test_only_setCleanupThreshold(value: Int) { 99 | cleanupThreshold = value 100 | } 101 | 102 | var __test_only_map: [Int: ApiRequestBox] { 103 | map 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Source/SwiftyDropbox/Shared/Handwritten/SDKConstants.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | public struct Constants { 8 | public static let versionSDK = "10.2.0" 9 | static let kCSRFKey = "kCSRFKeySwiftSDK" 10 | } 11 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Platform/SwiftyDropbox_iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 7.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 10.2.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Platform/SwiftyDropbox_macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 7.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 10.2.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2016 Dropbox. All rights reserved. 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Generated/DBXAuthAppAuthRoutes.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | import SwiftyDropbox 9 | 10 | /// Objective-C compatible routes for the auth namespace 11 | /// For Swift routes see AuthAppAuthRoutes 12 | @objc 13 | public class DBXAuthAppAuthRoutes: NSObject { 14 | private let swift: AuthAppAuthRoutes 15 | init(swift: AuthAppAuthRoutes) { 16 | self.swift = swift 17 | self.client = swift.client.objc 18 | } 19 | 20 | public let client: DBXDropboxTransportClient 21 | } 22 | 23 | @objc 24 | public class DBXAuthTokenFromOauth1RpcRequest: NSObject, DBXRequest { 25 | var swift: RpcRequest 26 | 27 | init(swift: RpcRequest) { 28 | self.swift = swift 29 | } 30 | 31 | @objc 32 | @discardableResult public func response( 33 | completionHandler: @escaping (DBXAuthTokenFromOAuth1Result?, DBXAuthTokenFromOAuth1Error?, DBXCallError?) -> Void 34 | ) -> Self { 35 | response(queue: nil, completionHandler: completionHandler) 36 | } 37 | 38 | @objc 39 | @discardableResult public func response( 40 | queue: DispatchQueue?, 41 | completionHandler: @escaping (DBXAuthTokenFromOAuth1Result?, DBXAuthTokenFromOAuth1Error?, DBXCallError?) -> Void 42 | ) -> Self { 43 | swift.response(queue: queue) { result, error in 44 | var routeError: DBXAuthTokenFromOAuth1Error? 45 | var callError: DBXCallError? 46 | switch error { 47 | case .routeError(let box, _, _, _): 48 | routeError = DBXAuthTokenFromOAuth1Error(swift: box.unboxed) 49 | callError = nil 50 | default: 51 | routeError = nil 52 | callError = error?.objc 53 | } 54 | 55 | var objc: DBXAuthTokenFromOAuth1Result? 56 | if let swift = result { 57 | objc = DBXAuthTokenFromOAuth1Result(swift: swift) 58 | } 59 | completionHandler(objc, routeError, callError) 60 | } 61 | return self 62 | } 63 | 64 | @objc 65 | public var clientPersistedString: String? { swift.clientPersistedString } 66 | 67 | @available(iOS 13.0, macOS 10.13, *) 68 | @objc 69 | public var earliestBeginDate: Date? { swift.earliestBeginDate } 70 | 71 | @objc 72 | public func persistingString(string: String?) -> Self { 73 | swift.persistingString(string: string) 74 | return self 75 | } 76 | 77 | @available(iOS 13.0, macOS 10.13, *) 78 | @objc 79 | public func settingEarliestBeginDate(date: Date?) -> Self { 80 | swift.settingEarliestBeginDate(date: date) 81 | return self 82 | } 83 | 84 | @objc 85 | public func cancel() { 86 | swift.cancel() 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Generated/DBXAuthRoutes.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | import SwiftyDropbox 9 | 10 | /// Objective-C compatible routes for the auth namespace 11 | /// For Swift routes see AuthRoutes 12 | @objc 13 | public class DBXAuthRoutes: NSObject { 14 | private let swift: AuthRoutes 15 | init(swift: AuthRoutes) { 16 | self.swift = swift 17 | self.client = swift.client.objc 18 | } 19 | 20 | public let client: DBXDropboxTransportClient 21 | 22 | /// Disables the access token used to authenticate the call. If there is a corresponding refresh token for the 23 | /// access token, this disables that refresh token, as well as any other access tokens for that refresh token. 24 | /// 25 | /// 26 | /// - returns: Through the response callback, the caller will receive a `Void` object on success or a `Void` object 27 | /// on failure. 28 | @objc 29 | @discardableResult public func tokenRevoke() -> DBXAuthTokenRevokeRpcRequest { 30 | let swift = swift.tokenRevoke() 31 | return DBXAuthTokenRevokeRpcRequest(swift: swift) 32 | } 33 | } 34 | 35 | @objc 36 | public class DBXAuthTokenRevokeRpcRequest: NSObject, DBXRequest { 37 | var swift: RpcRequest 38 | 39 | init(swift: RpcRequest) { 40 | self.swift = swift 41 | } 42 | 43 | @objc 44 | @discardableResult public func response( 45 | completionHandler: @escaping (DBXCallError?) -> Void 46 | ) -> Self { 47 | response(queue: nil, completionHandler: completionHandler) 48 | } 49 | 50 | @objc 51 | @discardableResult public func response( 52 | queue: DispatchQueue?, 53 | completionHandler: @escaping (DBXCallError?) -> Void 54 | ) -> Self { 55 | swift.response(queue: queue) { _, error in 56 | completionHandler(error?.objc) 57 | } 58 | return self 59 | } 60 | 61 | @objc 62 | public var clientPersistedString: String? { swift.clientPersistedString } 63 | 64 | @available(iOS 13.0, macOS 10.13, *) 65 | @objc 66 | public var earliestBeginDate: Date? { swift.earliestBeginDate } 67 | 68 | @objc 69 | public func persistingString(string: String?) -> Self { 70 | swift.persistingString(string: string) 71 | return self 72 | } 73 | 74 | @available(iOS 13.0, macOS 10.13, *) 75 | @objc 76 | public func settingEarliestBeginDate(date: Date?) -> Self { 77 | swift.settingEarliestBeginDate(date: date) 78 | return self 79 | } 80 | 81 | @objc 82 | public func cancel() { 83 | swift.cancel() 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Generated/DBXBase.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | import SwiftyDropbox 9 | 10 | /// Objective-C compatible DropboxBase. 11 | /// For Swift see DropboxBase. 12 | @objc 13 | public class DBXDropboxBase: NSObject { 14 | let swift: DropboxBase 15 | 16 | /// Routes within the account namespace. See DBAccountRoutes for details. 17 | @objc 18 | public var account: DBXAccountRoutes! 19 | /// Routes within the auth namespace. See DBAuthRoutes for details. 20 | @objc 21 | public var auth: DBXAuthRoutes! 22 | /// Routes within the check namespace. See DBCheckRoutes for details. 23 | @objc 24 | public var check: DBXCheckRoutes! 25 | /// Routes within the contacts namespace. See DBContactsRoutes for details. 26 | @objc 27 | public var contacts: DBXContactsRoutes! 28 | /// Routes within the fileProperties namespace. See DBFilePropertiesRoutes for details. 29 | @objc 30 | public var fileProperties: DBXFilePropertiesRoutes! 31 | /// Routes within the fileRequests namespace. See DBFileRequestsRoutes for details. 32 | @objc 33 | public var fileRequests: DBXFileRequestsRoutes! 34 | /// Routes within the files namespace. See DBFilesRoutes for details. 35 | @objc 36 | public var files: DBXFilesRoutes! 37 | /// Routes within the openid namespace. See DBOpenidRoutes for details. 38 | @objc 39 | public var openid: DBXOpenidRoutes! 40 | /// Routes within the paper namespace. See DBPaperRoutes for details. 41 | @objc 42 | public var paper: DBXPaperRoutes! 43 | /// Routes within the sharing namespace. See DBSharingRoutes for details. 44 | @objc 45 | public var sharing: DBXSharingRoutes! 46 | /// Routes within the teamLog namespace. See DBTeamLogRoutes for details. 47 | @objc 48 | public var teamLog: DBXTeamLogRoutes! 49 | /// Routes within the users namespace. See DBUsersRoutes for details. 50 | @objc 51 | public var users: DBXUsersRoutes! 52 | 53 | @objc 54 | public convenience init(client: DBXDropboxTransportClient) { 55 | self.init(swiftClient: client.swift) 56 | } 57 | 58 | public init(swiftClient: DropboxTransportClient) { 59 | self.swift = DropboxBase(client: swiftClient) 60 | 61 | self.account = DBXAccountRoutes(swift: swift.account) 62 | self.auth = DBXAuthRoutes(swift: swift.auth) 63 | self.check = DBXCheckRoutes(swift: swift.check) 64 | self.contacts = DBXContactsRoutes(swift: swift.contacts) 65 | self.fileProperties = DBXFilePropertiesRoutes(swift: swift.fileProperties) 66 | self.fileRequests = DBXFileRequestsRoutes(swift: swift.fileRequests) 67 | self.files = DBXFilesRoutes(swift: swift.files) 68 | self.openid = DBXOpenidRoutes(swift: swift.openid) 69 | self.paper = DBXPaperRoutes(swift: swift.paper) 70 | self.sharing = DBXSharingRoutes(swift: swift.sharing) 71 | self.teamLog = DBXTeamLogRoutes(swift: swift.teamLog) 72 | self.users = DBXUsersRoutes(swift: swift.users) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Generated/DBXBaseApp.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | import SwiftyDropbox 9 | 10 | /// Objective-C compatible DropboxAppBase. 11 | /// For Swift see DropboxAppBase. 12 | @objc 13 | public class DBXDropboxAppBase: NSObject { 14 | let swift: DropboxAppBase 15 | 16 | /// Routes within the auth namespace. See DBAuthAppAuthRoutes for details. 17 | @objc 18 | public var auth: DBXAuthAppAuthRoutes! 19 | /// Routes within the check namespace. See DBCheckAppAuthRoutes for details. 20 | @objc 21 | public var check: DBXCheckAppAuthRoutes! 22 | /// Routes within the files namespace. See DBFilesAppAuthRoutes for details. 23 | @objc 24 | public var files: DBXFilesAppAuthRoutes! 25 | /// Routes within the sharing namespace. See DBSharingAppAuthRoutes for details. 26 | @objc 27 | public var sharing: DBXSharingAppAuthRoutes! 28 | 29 | @objc 30 | public convenience init(client: DBXDropboxTransportClient) { 31 | self.init(swiftClient: client.swift) 32 | } 33 | 34 | public init(swiftClient: DropboxTransportClient) { 35 | self.swift = DropboxAppBase(client: swiftClient) 36 | 37 | self.auth = DBXAuthAppAuthRoutes(swift: swift.auth) 38 | self.check = DBXCheckAppAuthRoutes(swift: swift.check) 39 | self.files = DBXFilesAppAuthRoutes(swift: swift.files) 40 | self.sharing = DBXSharingAppAuthRoutes(swift: swift.sharing) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Generated/DBXBaseTeam.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | import SwiftyDropbox 9 | 10 | /// Objective-C compatible DropboxTeamBase. 11 | /// For Swift see DropboxTeamBase. 12 | @objc 13 | public class DBXDropboxTeamBase: NSObject { 14 | let swift: DropboxTeamBase 15 | 16 | /// Routes within the team namespace. See DBTeamRoutes for details. 17 | @objc 18 | public var team: DBXTeamRoutes! 19 | 20 | @objc 21 | public convenience init(client: DBXDropboxTransportClient) { 22 | self.init(swiftClient: client.swift) 23 | } 24 | 25 | public init(swiftClient: DropboxTransportClient) { 26 | self.swift = DropboxTeamBase(client: swiftClient) 27 | 28 | self.team = DBXTeamRoutes(swift: swift.team) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Generated/DBXCheck.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | import SwiftyDropbox 9 | 10 | /// Objective-C compatible datatypes for the check namespace 11 | /// For Swift see check 12 | 13 | /// Contains the arguments to be sent to the Dropbox servers. 14 | @objc 15 | public class DBXCheckEchoArg: NSObject { 16 | /// The string that you'd like to be echoed back to you. 17 | @objc 18 | public var query: String { swift.query } 19 | 20 | @objc 21 | public init(query: String) { 22 | self.swift = Check.EchoArg(query: query) 23 | } 24 | 25 | let swift: Check.EchoArg 26 | 27 | public init(swift: Check.EchoArg) { 28 | self.swift = swift 29 | } 30 | 31 | @objc 32 | public override var description: String { swift.description } 33 | } 34 | 35 | /// EchoResult contains the result returned from the Dropbox servers. 36 | @objc 37 | public class DBXCheckEchoResult: NSObject { 38 | /// If everything worked correctly, this would be the same as query. 39 | @objc 40 | public var result: String { swift.result } 41 | 42 | @objc 43 | public init(result: String) { 44 | self.swift = Check.EchoResult(result: result) 45 | } 46 | 47 | let swift: Check.EchoResult 48 | 49 | public init(swift: Check.EchoResult) { 50 | self.swift = swift 51 | } 52 | 53 | @objc 54 | public override var description: String { swift.description } 55 | } 56 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Generated/DBXContacts.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | import SwiftyDropbox 9 | 10 | /// Objective-C compatible datatypes for the contacts namespace 11 | /// For Swift see contacts 12 | 13 | /// Objective-C compatible DeleteManualContactsArg struct 14 | @objc 15 | public class DBXContactsDeleteManualContactsArg: NSObject { 16 | /// List of manually added contacts to be deleted. 17 | @objc 18 | public var emailAddresses: [String] { swift.emailAddresses } 19 | 20 | @objc 21 | public init(emailAddresses: [String]) { 22 | self.swift = Contacts.DeleteManualContactsArg(emailAddresses: emailAddresses) 23 | } 24 | 25 | let swift: Contacts.DeleteManualContactsArg 26 | 27 | public init(swift: Contacts.DeleteManualContactsArg) { 28 | self.swift = swift 29 | } 30 | 31 | @objc 32 | public override var description: String { swift.description } 33 | } 34 | 35 | /// Objective-C compatible DeleteManualContactsError union 36 | @objc 37 | public class DBXContactsDeleteManualContactsError: NSObject { 38 | let swift: Contacts.DeleteManualContactsError 39 | 40 | public init(swift: Contacts.DeleteManualContactsError) { 41 | self.swift = swift 42 | } 43 | 44 | public static func factory(swift: Contacts.DeleteManualContactsError) -> DBXContactsDeleteManualContactsError { 45 | switch swift { 46 | case .contactsNotFound(let swiftArg): 47 | let arg = swiftArg 48 | return DBXContactsDeleteManualContactsErrorContactsNotFound(arg) 49 | case .other: 50 | return DBXContactsDeleteManualContactsErrorOther() 51 | } 52 | } 53 | 54 | @objc 55 | public override var description: String { swift.description } 56 | 57 | @objc 58 | public var asContactsNotFound: DBXContactsDeleteManualContactsErrorContactsNotFound? { 59 | self as? DBXContactsDeleteManualContactsErrorContactsNotFound 60 | } 61 | 62 | @objc 63 | public var asOther: DBXContactsDeleteManualContactsErrorOther? { 64 | self as? DBXContactsDeleteManualContactsErrorOther 65 | } 66 | } 67 | 68 | /// Can't delete contacts from this list. Make sure the list only has manually added contacts. The deletion was 69 | /// cancelled. 70 | @objc 71 | public class DBXContactsDeleteManualContactsErrorContactsNotFound: DBXContactsDeleteManualContactsError { 72 | @objc 73 | public var contactsNotFound: [String] 74 | 75 | @objc 76 | public init(_ arg: [String]) { 77 | self.contactsNotFound = arg 78 | let swift = Contacts.DeleteManualContactsError.contactsNotFound(arg) 79 | super.init(swift: swift) 80 | } 81 | } 82 | 83 | /// An unspecified error. 84 | @objc 85 | public class DBXContactsDeleteManualContactsErrorOther: DBXContactsDeleteManualContactsError { 86 | @objc 87 | public init() { 88 | let swift = Contacts.DeleteManualContactsError.other 89 | super.init(swift: swift) 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Generated/DBXDropboxAppBaseRequestBox.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | import SwiftyDropbox 9 | 10 | extension DropboxAppBaseRequestBox { 11 | var objc: DBXRequest { 12 | if case .files_getThumbnailV2(let swift) = self { 13 | return DBXFilesGetThumbnailDownloadRequestFileV2(swift: swift) 14 | } else { 15 | fatalError("For Obj-C compatibility, add this route to the Objective-C compatibility module allow-list") 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Generated/DBXDropboxBaseRequestBox.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | import SwiftyDropbox 9 | 10 | extension DropboxBaseRequestBox { 11 | var objc: DBXRequest { 12 | if case .files_alphaUpload(let swift) = self { 13 | return DBXFilesAlphaUploadUploadRequest(swift: swift) 14 | } 15 | if case .files_download(let swift) = self { 16 | return DBXFilesDownloadDownloadRequestFile(swift: swift) 17 | } 18 | if case .files_downloadZip(let swift) = self { 19 | return DBXFilesDownloadZipDownloadRequestFile(swift: swift) 20 | } 21 | if case .files_export(let swift) = self { 22 | return DBXFilesExportDownloadRequestFile(swift: swift) 23 | } 24 | if case .files_getPreview(let swift) = self { 25 | return DBXFilesGetPreviewDownloadRequestFile(swift: swift) 26 | } 27 | if case .files_getThumbnail(let swift) = self { 28 | return DBXFilesGetThumbnailDownloadRequestFile(swift: swift) 29 | } 30 | if case .files_getThumbnailV2(let swift) = self { 31 | return DBXFilesGetThumbnailDownloadRequestFileV2(swift: swift) 32 | } 33 | if case .files_paperCreate(let swift) = self { 34 | return DBXFilesPaperCreateUploadRequest(swift: swift) 35 | } 36 | if case .files_paperUpdate(let swift) = self { 37 | return DBXFilesPaperUpdateUploadRequest(swift: swift) 38 | } 39 | if case .files_upload(let swift) = self { 40 | return DBXFilesUploadUploadRequest(swift: swift) 41 | } 42 | if case .files_uploadSessionAppend(let swift) = self { 43 | return DBXFilesUploadSessionAppendUploadRequest(swift: swift) 44 | } 45 | if case .files_uploadSessionAppendV2(let swift) = self { 46 | return DBXFilesUploadSessionAppendUploadRequestV2(swift: swift) 47 | } 48 | if case .files_uploadSessionFinish(let swift) = self { 49 | return DBXFilesUploadSessionFinishUploadRequest(swift: swift) 50 | } 51 | if case .files_uploadSessionStart(let swift) = self { 52 | return DBXFilesUploadSessionStartUploadRequest(swift: swift) 53 | } 54 | if case .paper_docsCreate(let swift) = self { 55 | return DBXPaperDocsCreateUploadRequest(swift: swift) 56 | } 57 | if case .paper_docsDownload(let swift) = self { 58 | return DBXPaperDocsDownloadDownloadRequestFile(swift: swift) 59 | } 60 | if case .paper_docsUpdate(let swift) = self { 61 | return DBXPaperDocsUpdateUploadRequest(swift: swift) 62 | } 63 | if case .sharing_getSharedLinkFile(let swift) = self { 64 | return DBXSharingGetSharedLinkFileDownloadRequestFile(swift: swift) 65 | } else { 66 | fatalError("For Obj-C compatibility, add this route to the Objective-C compatibility module allow-list") 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Generated/DBXOpenidRoutes.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | import SwiftyDropbox 9 | 10 | /// Objective-C compatible routes for the openid namespace 11 | /// For Swift routes see OpenidRoutes 12 | @objc 13 | public class DBXOpenidRoutes: NSObject { 14 | private let swift: OpenidRoutes 15 | init(swift: OpenidRoutes) { 16 | self.swift = swift 17 | self.client = swift.client.objc 18 | } 19 | 20 | public let client: DBXDropboxTransportClient 21 | 22 | /// This route is used for refreshing the info that is found in the id_token during the OIDC flow. This route 23 | /// doesn't require any arguments and will use the scopes approved for the given access token. 24 | /// 25 | /// - scope: openid 26 | /// 27 | /// 28 | /// - returns: Through the response callback, the caller will receive a `Openid.UserInfoResult` object on success or 29 | /// a `Openid.UserInfoError` object on failure. 30 | @objc 31 | @discardableResult public func userinfo() -> DBXOpenidUserinfoRpcRequest { 32 | let swift = swift.userinfo() 33 | return DBXOpenidUserinfoRpcRequest(swift: swift) 34 | } 35 | } 36 | 37 | @objc 38 | public class DBXOpenidUserinfoRpcRequest: NSObject, DBXRequest { 39 | var swift: RpcRequest 40 | 41 | init(swift: RpcRequest) { 42 | self.swift = swift 43 | } 44 | 45 | @objc 46 | @discardableResult public func response( 47 | completionHandler: @escaping (DBXOpenidUserInfoResult?, DBXOpenidUserInfoError?, DBXCallError?) -> Void 48 | ) -> Self { 49 | response(queue: nil, completionHandler: completionHandler) 50 | } 51 | 52 | @objc 53 | @discardableResult public func response( 54 | queue: DispatchQueue?, 55 | completionHandler: @escaping (DBXOpenidUserInfoResult?, DBXOpenidUserInfoError?, DBXCallError?) -> Void 56 | ) -> Self { 57 | swift.response(queue: queue) { result, error in 58 | var routeError: DBXOpenidUserInfoError? 59 | var callError: DBXCallError? 60 | switch error { 61 | case .routeError(let box, _, _, _): 62 | routeError = DBXOpenidUserInfoError(swift: box.unboxed) 63 | callError = nil 64 | default: 65 | routeError = nil 66 | callError = error?.objc 67 | } 68 | 69 | var objc: DBXOpenidUserInfoResult? 70 | if let swift = result { 71 | objc = DBXOpenidUserInfoResult(swift: swift) 72 | } 73 | completionHandler(objc, routeError, callError) 74 | } 75 | return self 76 | } 77 | 78 | @objc 79 | public var clientPersistedString: String? { swift.clientPersistedString } 80 | 81 | @available(iOS 13.0, macOS 10.13, *) 82 | @objc 83 | public var earliestBeginDate: Date? { swift.earliestBeginDate } 84 | 85 | @objc 86 | public func persistingString(string: String?) -> Self { 87 | swift.persistingString(string: string) 88 | return self 89 | } 90 | 91 | @available(iOS 13.0, macOS 10.13, *) 92 | @objc 93 | public func settingEarliestBeginDate(date: Date?) -> Self { 94 | swift.settingEarliestBeginDate(date: date) 95 | return self 96 | } 97 | 98 | @objc 99 | public func cancel() { 100 | swift.cancel() 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Generated/DBXSecondaryEmails.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | import SwiftyDropbox 9 | 10 | /// Objective-C compatible datatypes for the secondary_emails namespace 11 | /// For Swift see secondary_emails 12 | 13 | /// Objective-C compatible SecondaryEmail struct 14 | @objc 15 | public class DBXSecondaryEmailsSecondaryEmail: NSObject { 16 | /// Secondary email address. 17 | @objc 18 | public var email: String { swift.email } 19 | /// Whether or not the secondary email address is verified to be owned by a user. 20 | @objc 21 | public var isVerified: NSNumber { swift.isVerified as NSNumber } 22 | 23 | @objc 24 | public init(email: String, isVerified: NSNumber) { 25 | self.swift = SecondaryEmails.SecondaryEmail(email: email, isVerified: isVerified.boolValue) 26 | } 27 | 28 | let swift: SecondaryEmails.SecondaryEmail 29 | 30 | public init(swift: SecondaryEmails.SecondaryEmail) { 31 | self.swift = swift 32 | } 33 | 34 | @objc 35 | public override var description: String { swift.description } 36 | } 37 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Generated/DBXSharingAppAuthRoutes.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | import SwiftyDropbox 9 | 10 | /// Objective-C compatible routes for the sharing namespace 11 | /// For Swift routes see SharingAppAuthRoutes 12 | @objc 13 | public class DBXSharingAppAuthRoutes: NSObject { 14 | private let swift: SharingAppAuthRoutes 15 | init(swift: SharingAppAuthRoutes) { 16 | self.swift = swift 17 | self.client = swift.client.objc 18 | } 19 | 20 | public let client: DBXDropboxTransportClient 21 | 22 | /// Get the shared link's metadata. 23 | /// 24 | /// - scope: sharing.read 25 | /// 26 | /// - parameter url: URL of the shared link. 27 | /// - parameter path: If the shared link is to a folder, this parameter can be used to retrieve the metadata for a 28 | /// specific file or sub-folder in this folder. A relative path should be used. 29 | /// - parameter linkPassword: If the shared link has a password, this parameter can be used. 30 | /// 31 | /// - returns: Through the response callback, the caller will receive a `Sharing.SharedLinkMetadata` object on 32 | /// success or a `Sharing.SharedLinkError` object on failure. 33 | @objc 34 | @discardableResult public func getSharedLinkMetadata(url: String, path: String?, linkPassword: String?) -> DBXSharingGetSharedLinkMetadataRpcRequest { 35 | let swift = swift.getSharedLinkMetadata(url: url, path: path, linkPassword: linkPassword) 36 | return DBXSharingGetSharedLinkMetadataRpcRequest(swift: swift) 37 | } 38 | 39 | /// Get the shared link's metadata. 40 | /// 41 | /// - scope: sharing.read 42 | /// 43 | /// - returns: Through the response callback, the caller will receive a `Sharing.SharedLinkMetadata` object on 44 | /// success or a `Sharing.SharedLinkError` object on failure. 45 | @objc 46 | @discardableResult public func getSharedLinkMetadata(url: String) -> DBXSharingGetSharedLinkMetadataRpcRequest { 47 | let swift = swift.getSharedLinkMetadata(url: url) 48 | return DBXSharingGetSharedLinkMetadataRpcRequest(swift: swift) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Generated/DBXUsersCommon.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | /// Auto-generated by Stone, do not modify. 5 | /// 6 | 7 | import Foundation 8 | import SwiftyDropbox 9 | 10 | /// Objective-C compatible datatypes for the users_common namespace 11 | /// For Swift see users_common 12 | 13 | /// What type of account this user has. 14 | @objc 15 | public class DBXUsersCommonAccountType: NSObject { 16 | let swift: UsersCommon.AccountType 17 | 18 | public init(swift: UsersCommon.AccountType) { 19 | self.swift = swift 20 | } 21 | 22 | public static func factory(swift: UsersCommon.AccountType) -> DBXUsersCommonAccountType { 23 | switch swift { 24 | case .basic: 25 | return DBXUsersCommonAccountTypeBasic() 26 | case .pro: 27 | return DBXUsersCommonAccountTypePro() 28 | case .business: 29 | return DBXUsersCommonAccountTypeBusiness() 30 | } 31 | } 32 | 33 | @objc 34 | public override var description: String { swift.description } 35 | 36 | @objc 37 | public var asBasic: DBXUsersCommonAccountTypeBasic? { 38 | self as? DBXUsersCommonAccountTypeBasic 39 | } 40 | 41 | @objc 42 | public var asPro: DBXUsersCommonAccountTypePro? { 43 | self as? DBXUsersCommonAccountTypePro 44 | } 45 | 46 | @objc 47 | public var asBusiness: DBXUsersCommonAccountTypeBusiness? { 48 | self as? DBXUsersCommonAccountTypeBusiness 49 | } 50 | } 51 | 52 | /// The basic account type. 53 | @objc 54 | public class DBXUsersCommonAccountTypeBasic: DBXUsersCommonAccountType { 55 | @objc 56 | public init() { 57 | let swift = UsersCommon.AccountType.basic 58 | super.init(swift: swift) 59 | } 60 | } 61 | 62 | /// The Dropbox Pro account type. 63 | @objc 64 | public class DBXUsersCommonAccountTypePro: DBXUsersCommonAccountType { 65 | @objc 66 | public init() { 67 | let swift = UsersCommon.AccountType.pro 68 | super.init(swift: swift) 69 | } 70 | } 71 | 72 | /// The Dropbox Business account type. 73 | @objc 74 | public class DBXUsersCommonAccountTypeBusiness: DBXUsersCommonAccountType { 75 | @objc 76 | public init() { 77 | let swift = UsersCommon.AccountType.business 78 | super.init(swift: swift) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Handwritten/DBXCertificatePinning.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | import SwiftyDropbox 7 | 8 | @objc 9 | public protocol DBXAuthChallengeHandler { 10 | func handle(challenge: URLAuthenticationChallenge) -> DBXAuthChallengeHandlerResult 11 | } 12 | 13 | extension DBXAuthChallengeHandler { 14 | var swift: AuthChallenge.Handler { 15 | { [weak self] challenge in 16 | guard let self = self else { 17 | return (.cancelAuthenticationChallenge, nil) 18 | } 19 | let result = self.handle(challenge: challenge) 20 | return (result.disposition, result.credential) 21 | } 22 | } 23 | } 24 | 25 | public class DBXAuthChallengeHandlerResult: NSObject { 26 | @objc 27 | public let disposition: URLSession.AuthChallengeDisposition 28 | @objc 29 | public let credential: URLCredential? 30 | 31 | @objc 32 | init(disposition: URLSession.AuthChallengeDisposition, credential: URLCredential?) { 33 | self.disposition = disposition 34 | self.credential = credential 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Handwritten/DBXDropboxAppClient.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | import SwiftyDropbox 7 | 8 | /// The client for the App API. Call routes using the namespaces inside this object (inherited from parent). 9 | @objc 10 | public class DBXDropboxAppClient: DBXDropboxAppBase { 11 | let subSwift: DropboxAppClient 12 | 13 | /// Initialize a client from swift using an existing Swift client. 14 | /// 15 | /// - Parameter swift: The underlying DropboxAppClient to make API calls. 16 | public init(swift: DropboxAppClient) { 17 | self.subSwift = swift 18 | super.init(swiftClient: swift.client) 19 | } 20 | 21 | /// Designated Initializer. 22 | /// 23 | /// - Parameter transportClient: The underlying DropboxTransportClient to make API calls. 24 | @objc 25 | public convenience init(transportClient: DBXDropboxTransportClient) { 26 | self.init(swift: DropboxAppClient(transportClient: transportClient.swift)) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Handwritten/DBXDropboxTeamClient.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | import SwiftyDropbox 7 | 8 | /// The client for the Business API. Call routes using the namespaces inside this object (inherited from parent). 9 | 10 | extension DropboxTeamClient { 11 | var objc: DBXDropboxTeamClient { 12 | DBXDropboxTeamClient(swift: self) 13 | } 14 | } 15 | 16 | @objc 17 | public class DBXDropboxTeamClient: DBXDropboxTeamBase { 18 | let subSwift: DropboxTeamClient 19 | 20 | fileprivate init(swift: DropboxTeamClient) { 21 | self.subSwift = swift 22 | super.init(swiftClient: swift.client) 23 | } 24 | 25 | /// Initialize a client with a static accessToken string. 26 | /// Use this method if your access token is long-lived. 27 | /// 28 | /// - Parameters: 29 | /// - accessToken: Static access token string. 30 | /// - sessionConfiguration: Optional custom network session configuration 31 | /// 32 | @objc 33 | public convenience init( 34 | accessToken: String, 35 | sessionConfiguration: DBXNetworkSessionConfiguration? = nil 36 | ) { 37 | let transportClient = DBXDropboxTransportClient(accessToken: accessToken) 38 | self.init(transportClient: transportClient) 39 | } 40 | 41 | /// Initialize a client with an `AccessTokenProvider`. 42 | /// Use this method if your access token is short-lived. 43 | /// See `ShortLivedAccessTokenProvider` for a default implementation. 44 | /// 45 | /// - Parameter accessTokenProvider: Access token provider that wraps a short-lived token and its refresh logic. 46 | @objc 47 | public convenience init( 48 | accessTokenProvider: DBXAccessTokenProvider, 49 | sessionConfiguration: DBXNetworkSessionConfiguration? = nil 50 | ) { 51 | let transportClient = DBXDropboxTransportClient(accessTokenProvider: accessTokenProvider) 52 | self.init(transportClient: transportClient) 53 | } 54 | 55 | /// Initialize a client with an `DropboxAccessToken`. 56 | /// 57 | /// - Parameters: 58 | /// - accessToken: The token itself, could be long or short lived. 59 | /// - dropboxOauthManager: an oauthManager, used for creating the token provider. 60 | /// - sessionConfiguration: Optional custom network session configuration 61 | @objc 62 | public convenience init( 63 | accessToken: DBXDropboxAccessToken, 64 | dropboxOauthManager: DBXDropboxOAuthManager, 65 | sessionConfiguration: DBXNetworkSessionConfiguration? = nil 66 | ) { 67 | let accessTokenProvider = dropboxOauthManager.accessTokenProviderForToken(accessToken) 68 | let transportClient = DBXDropboxTransportClient(accessTokenProvider: accessTokenProvider) 69 | self.init(transportClient: transportClient) 70 | } 71 | 72 | /// Designated Initializer. 73 | /// 74 | /// - Parameter transportClient: The underlying DropboxTransportClient to make API calls. 75 | @objc 76 | public convenience init(transportClient: DBXDropboxTransportClient) { 77 | self.init(swift: DropboxTeamClient(transportClient: transportClient.swift)) 78 | } 79 | 80 | /// Creates a new DropboxClient instance for the team member id. 81 | /// 82 | /// - Parameter memberId: Team member id. 83 | /// - Returns: A new DropboxClient instance that can be used to call APIs on the team member's behalf. 84 | @objc 85 | public func asMember(_ memberId: String) -> DBXDropboxClient { 86 | DropboxClient(accessTokenProvider: subSwift.accessTokenProvider, selectUser: memberId).objc 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Handwritten/DBXReconnectionHelpers.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | import SwiftyDropbox 7 | 8 | extension ReconnectionError { 9 | var objc: DBXReconnectionHelperError { 10 | DBXReconnectionHelperError(swift: self) 11 | } 12 | } 13 | 14 | @objc 15 | public class DBXReconnectionHelperError: NSObject { 16 | let swift: ReconnectionError 17 | 18 | @objc 19 | public var errorMessage: String { swift.reconnectionErrorKind.rawValue } 20 | 21 | @objc 22 | public var taskDescription: String? { swift.taskDescription } 23 | 24 | init(swift: ReconnectionError) { 25 | self.swift = swift 26 | } 27 | } 28 | 29 | @objc 30 | public class DBXReconnectionResult: NSObject { 31 | @objc 32 | public let request: DBXRequest? 33 | @objc 34 | public let error: DBXReconnectionHelperError? 35 | 36 | init(request: DBXRequest?, error: DBXReconnectionHelperError?) { 37 | self.request = request 38 | self.error = error 39 | } 40 | } 41 | 42 | @objc 43 | public class DBXDefaultBackgroundExtensionSessionCreationInfo: NSObject { 44 | let swift: DefaultBackgroundExtensionSessionCreationInfo 45 | 46 | public init(swift: DefaultBackgroundExtensionSessionCreationInfo) { 47 | self.swift = swift 48 | } 49 | 50 | @objc 51 | public init(backgroundSessionIdentifier: String, sharedContainerIdentifier: String) { 52 | self.swift = DefaultBackgroundExtensionSessionCreationInfo( 53 | backgroundSessionIdentifier: backgroundSessionIdentifier, 54 | sharedContainerIdentifier: sharedContainerIdentifier 55 | ) 56 | } 57 | } 58 | 59 | @objc 60 | public class DBXCustomBackgroundExtensionSessionCreationInfo: NSObject { 61 | let swift: CustomBackgroundExtensionSessionCreationInfo 62 | 63 | @objc 64 | public init(backgroundTransportClient: DBXDropboxTransportClient) { 65 | self.swift = .init(backgroundTransportClient: backgroundTransportClient.swift) 66 | } 67 | 68 | @objc 69 | public init(backgroundSessionConfiguration: DBXNetworkSessionConfiguration) { 70 | self.swift = .init(backgroundSessionConfiguration: backgroundSessionConfiguration.swift) 71 | } 72 | 73 | init(swift: CustomBackgroundExtensionSessionCreationInfo) { 74 | self.swift = swift 75 | } 76 | } 77 | 78 | @objc 79 | public class DBXBackgroundExtensionSessionCreationInfo: NSObject { 80 | let swift: BackgroundExtensionSessionCreationInfo 81 | 82 | @objc 83 | public init(defaultInfo: DBXDefaultBackgroundExtensionSessionCreationInfo) { 84 | self.swift = .init(defaultInfo: defaultInfo.swift) 85 | } 86 | 87 | @objc 88 | public init(customInfo: DBXCustomBackgroundExtensionSessionCreationInfo) { 89 | self.swift = .init(customInfo: customInfo.swift) 90 | } 91 | 92 | init(swift: BackgroundExtensionSessionCreationInfo) { 93 | self.swift = swift 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Handwritten/DBXRequest.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | @objc 8 | public protocol DBXRequest { 9 | var clientPersistedString: String? { get } 10 | 11 | @available(iOS 13.0, macOS 10.13, *) 12 | var earliestBeginDate: Date? { get } 13 | 14 | @discardableResult 15 | func persistingString(string: String?) -> Self 16 | 17 | @available(iOS 13.0, macOS 10.13, *) 18 | @discardableResult 19 | func settingEarliestBeginDate(date: Date?) -> Self 20 | 21 | func cancel() 22 | } 23 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Handwritten/NetworkSession/DBXNetworkSessionConfiguration.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | import SwiftyDropbox 7 | 8 | extension NetworkSessionConfiguration { 9 | var objc: DBXNetworkSessionConfiguration { 10 | DBXNetworkSessionConfiguration(swift: self) 11 | } 12 | } 13 | 14 | public class DBXNetworkSessionConfiguration: NSObject { 15 | var swift: NetworkSessionConfiguration 16 | 17 | fileprivate init(swift: NetworkSessionConfiguration) { 18 | self.swift = swift 19 | } 20 | 21 | @objc 22 | public var timeoutIntervalForRequest: Double { 23 | get { 24 | swift.timeoutIntervalForRequest 25 | } 26 | set { 27 | swift.timeoutIntervalForRequest = newValue 28 | } 29 | } 30 | 31 | @objc 32 | public var timeoutIntervalForResource: Double { 33 | get { 34 | swift.timeoutIntervalForResource 35 | } 36 | set { 37 | swift.timeoutIntervalForResource = newValue 38 | } 39 | } 40 | 41 | @objc 42 | public var allowsCellularAccess: Bool { 43 | get { 44 | swift.allowsCellularAccess 45 | } 46 | set { 47 | swift.allowsCellularAccess = newValue 48 | } 49 | } 50 | 51 | @objc 52 | @available(iOS 13.0, macOS 10.15, *) 53 | public var allowsExpensiveNetworkAccess: Bool { 54 | get { 55 | swift.allowsExpensiveNetworkAccess 56 | } 57 | set { 58 | swift.allowsExpensiveNetworkAccess = newValue 59 | } 60 | } 61 | 62 | @objc 63 | @available(iOS 13.0, macOS 10.15, *) 64 | public var allowsConstrainedNetworkAccess: Bool { 65 | get { 66 | swift.allowsConstrainedNetworkAccess 67 | } 68 | set { 69 | swift.allowsConstrainedNetworkAccess = newValue 70 | } 71 | } 72 | 73 | @objc 74 | public var sharedContainerIdentifier: String? { 75 | get { 76 | swift.sharedContainerIdentifier 77 | } 78 | set { 79 | swift.sharedContainerIdentifier = newValue 80 | } 81 | } 82 | 83 | @objc 84 | public var httpMaximumConnectionsPerHost: Int { 85 | get { 86 | swift.httpMaximumConnectionsPerHost 87 | } 88 | set { 89 | swift.httpMaximumConnectionsPerHost = newValue 90 | } 91 | } 92 | 93 | @objc 94 | public static var `default` = DBXNetworkSessionConfiguration(swift: NetworkSessionConfiguration.default) 95 | @objc 96 | public static var defaultLongpoll = DBXNetworkSessionConfiguration(swift: NetworkSessionConfiguration.defaultLongpoll) 97 | @objc 98 | public static func background(withIdentifier identifier: String) -> DBXNetworkSessionConfiguration { 99 | DBXNetworkSessionConfiguration(swift: NetworkSessionConfiguration(kind: .background(identifier))) 100 | } 101 | 102 | @objc 103 | public static func background(withIdentifier identifier: String, sharedContainerIdentifier: String) -> DBXNetworkSessionConfiguration { 104 | DBXNetworkSessionConfiguration( 105 | swift: NetworkSessionConfiguration 106 | .background(withIdentifier: identifier, sharedContainerIdentifier: sharedContainerIdentifier) 107 | ) 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Handwritten/OAuth/DBXAccessTokenProvider.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | import SwiftyDropbox 7 | 8 | extension AccessTokenProvider { 9 | var objc: DBXAccessTokenProvider { 10 | DBXAccessTokenProvider(swift: self) 11 | } 12 | } 13 | 14 | @objc 15 | public class DBXAccessTokenProvider: NSObject { 16 | @objc 17 | public var accessToken: String { swift.accessToken } 18 | 19 | let swift: AccessTokenProvider 20 | 21 | fileprivate init(swift: AccessTokenProvider) { 22 | self.swift = swift 23 | } 24 | } 25 | 26 | extension DBXAccessTokenProvider: AccessTokenProvider { 27 | public func refreshAccessTokenIfNecessary(completion: @escaping DropboxOAuthCompletion) { 28 | swift.refreshAccessTokenIfNecessary(completion: completion) 29 | } 30 | } 31 | 32 | extension LongLivedAccessTokenProvider { 33 | var objc: DBXLongLivedAccessTokenProvider { 34 | DBXLongLivedAccessTokenProvider(swift: self) 35 | } 36 | } 37 | 38 | public class DBXLongLivedAccessTokenProvider: DBXAccessTokenProvider { 39 | fileprivate init(swift: LongLivedAccessTokenProvider) { 40 | super.init(swift: swift) 41 | } 42 | 43 | @objc 44 | public init(accessToken: String) { 45 | super.init(swift: LongLivedAccessTokenProvider(accessToken: accessToken)) 46 | } 47 | } 48 | 49 | extension ShortLivedAccessTokenProvider { 50 | var objc: DBXShortLivedAccessTokenProvider { 51 | DBXShortLivedAccessTokenProvider(swift: self) 52 | } 53 | } 54 | 55 | @objc 56 | public class DBXShortLivedAccessTokenProvider: DBXAccessTokenProvider { 57 | fileprivate init(swift: ShortLivedAccessTokenProvider) { 58 | super.init(swift: swift) 59 | } 60 | 61 | /// - Parameters: 62 | /// - token: The `DropboxAccessToken` object for a short-lived token. 63 | /// - tokenRefresher: Helper object that refreshes a token over network. 64 | @objc 65 | init(token: DBXDropboxAccessToken, tokenRefresher: DBXAccessTokenRefreshing) { 66 | super.init(swift: ShortLivedAccessTokenProvider(token: token.swift, tokenRefresher: tokenRefresher.swift)) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Handwritten/OAuth/DBXAuthSession.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | import SwiftyDropbox 7 | 8 | extension ScopeRequest { 9 | var objc: DBXScopeRequest { 10 | DBXScopeRequest(swift: self) 11 | } 12 | } 13 | 14 | @objc 15 | public class DBXScopeRequest: NSObject { 16 | let swift: ScopeRequest 17 | 18 | /// Type of the requested scopes. 19 | @objc public enum DBXScopeType: Int { 20 | case team 21 | case user 22 | } 23 | 24 | /// An array of scopes to be granted. 25 | @objc 26 | var scopes: [String] { swift.scopes } 27 | /// Boolean indicating whether to keep all previously granted scopes. 28 | @objc 29 | var includeGrantedScopes: Bool { swift.includeGrantedScopes } 30 | /// Type of the scopes to be granted. 31 | @objc 32 | var scopeType: DBXScopeType { 33 | switch swift.scopeType { 34 | case .team: 35 | return .team 36 | case .user: 37 | return .user 38 | } 39 | } 40 | 41 | /// String representation of the scopes, used in URL query. Nil if the array is empty. 42 | @objc 43 | var scopeString: String? { 44 | swift.scopeString 45 | } 46 | 47 | /// Designated Initializer. 48 | /// 49 | /// - Parameters: 50 | /// - scopeType: Type of the requested scopes. 51 | /// - scopes: A list of scope returned by Dropbox server. Each scope correspond to a group of API endpoints. 52 | /// To call one API endpoint you have to obtains the scope first otherwise you will get HTTP 401. 53 | /// - includeGrantedScopes: If false, Dropbox will give you the scopes in scopes array. 54 | /// Otherwise Dropbox server will return a token with all scopes user previously granted your app 55 | /// together with the new scopes. 56 | @objc 57 | public init(scopeType: DBXScopeType, scopes: [String], includeGrantedScopes: Bool) { 58 | let swiftScopeType: ScopeRequest.ScopeType = scopeType == .team ? .team : .user 59 | self.swift = ScopeRequest(scopeType: swiftScopeType, scopes: scopes, includeGrantedScopes: includeGrantedScopes) 60 | } 61 | 62 | fileprivate init(swift: ScopeRequest) { 63 | self.swift = swift 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxObjC/Shared/Handwritten/OAuth/DBXSecureStorageAccess.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2022 Dropbox Inc. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | import SwiftyDropbox 7 | 8 | @objc 9 | public protocol DBXSecureStorageAccess { 10 | func checkAccessibilityMigrationOneTime() 11 | func setAccessTokenData(for userId: String, data: Data) -> Bool 12 | func getAllUserIds() -> [String] 13 | func getDropboxAccessToken(for key: String) -> DBXDropboxAccessToken? 14 | func deleteInfo(for key: String) -> Bool 15 | func deleteInfoForAllKeys() -> Bool 16 | } 17 | 18 | extension SecureStorageAccessDefaultImpl { 19 | var objc: DBXSecureStorageAccessDefaultImpl { 20 | DBXSecureStorageAccessDefaultImpl(swift: self) 21 | } 22 | } 23 | 24 | @objc 25 | open class DBXSecureStorageAccessImpl: NSObject, DBXSecureStorageAccess { 26 | let swift: SecureStorageAccess 27 | 28 | public init(swift: SecureStorageAccess) { 29 | self.swift = swift 30 | } 31 | 32 | public func checkAccessibilityMigrationOneTime() { 33 | swift.checkAccessibilityMigrationOneTime() 34 | } 35 | 36 | public func setAccessTokenData(for userId: String, data: Data) -> Bool { 37 | swift.setAccessTokenData(for: userId, data: data) 38 | } 39 | 40 | public func getAllUserIds() -> [String] { 41 | swift.getAllUserIds() 42 | } 43 | 44 | public func getDropboxAccessToken(for key: String) -> DBXDropboxAccessToken? { 45 | swift.getDropboxAccessToken(for: key)?.objc 46 | } 47 | 48 | public func deleteInfo(for key: String) -> Bool { 49 | swift.deleteInfo(for: key) 50 | } 51 | 52 | public func deleteInfoForAllKeys() -> Bool { 53 | swift.deleteInfoForAllKeys() 54 | } 55 | } 56 | 57 | @objc 58 | public class DBXSecureStorageAccessDefaultImpl: DBXSecureStorageAccessImpl { 59 | @objc 60 | public convenience init() { 61 | self.init(swift: SecureStorageAccessDefaultImpl()) 62 | } 63 | 64 | fileprivate init(swift: SecureStorageAccessDefaultImpl) { 65 | super.init(swift: swift) 66 | } 67 | } 68 | 69 | extension DBXSecureStorageAccess { 70 | var swift: SecureStorageAccess { 71 | SecureStorageAccessBridge(objc: self) 72 | } 73 | } 74 | 75 | public class SecureStorageAccessBridge: NSObject, SecureStorageAccess { 76 | let objc: DBXSecureStorageAccess 77 | 78 | init(objc: DBXSecureStorageAccess) { 79 | self.objc = objc 80 | } 81 | 82 | public func checkAccessibilityMigrationOneTime() { 83 | objc.checkAccessibilityMigrationOneTime() 84 | } 85 | 86 | public func setAccessTokenData(for userId: String, data: Data) -> Bool { 87 | objc.setAccessTokenData(for: userId, data: data) 88 | } 89 | 90 | public func getAllUserIds() -> [String] { 91 | objc.getAllUserIds() 92 | } 93 | 94 | public func getDropboxAccessToken(for key: String) -> DropboxAccessToken? { 95 | objc.getDropboxAccessToken(for: key)?.swift 96 | } 97 | 98 | public func deleteInfo(for key: String) -> Bool { 99 | objc.deleteInfo(for: key) 100 | } 101 | 102 | public func deleteInfoForAllKeys() -> Bool { 103 | objc.deleteInfoForAllKeys() 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxUnitTests/ReconnectionHelperPersistedRequestInfoTests.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | @testable import SwiftyDropbox 8 | import XCTest 9 | 10 | final class TestReconnectionHelperPersistedRequestInfo: XCTestCase { 11 | let routeName = "deleteV2" 12 | let routeNamespace = "files" 13 | let clientProvidedInfo = "example" 14 | 15 | let destination = URL(string: "/some/file.jpg")! 16 | let overwrite = true 17 | 18 | lazy var uploadInfo: ReconnectionHelpers.PersistedRequestInfo = .upload( 19 | ReconnectionHelpers.PersistedRequestInfo.StandardInfo( 20 | originalSDKVersion: DropboxClientsManager.sdkVersion, 21 | routeName: routeName, 22 | routeNamespace: routeNamespace, 23 | clientProvidedInfo: clientProvidedInfo 24 | ) 25 | ) 26 | 27 | lazy var downloadFileInfo: ReconnectionHelpers.PersistedRequestInfo = .downloadFile( 28 | ReconnectionHelpers.PersistedRequestInfo.DownloadFileInfo( 29 | originalSDKVersion: DropboxClientsManager.sdkVersion, 30 | routeName: routeName, 31 | routeNamespace: routeNamespace, 32 | clientProvidedInfo: clientProvidedInfo, 33 | destination: destination, 34 | overwrite: overwrite 35 | ) 36 | ) 37 | 38 | func testCodingRoundtrip() throws { 39 | XCTAssertEqual( 40 | uploadInfo, 41 | try ReconnectionHelpers.PersistedRequestInfo.from(jsonString: try uploadInfo.asJsonString()) 42 | ) 43 | } 44 | 45 | func testDownloadFileCodingRoundtrip() throws { 46 | XCTAssertEqual( 47 | downloadFileInfo, 48 | try ReconnectionHelpers.PersistedRequestInfo.from(jsonString: try downloadFileInfo.asJsonString()) 49 | ) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxUnitTests/ReconnectionHelperRouteNameTests.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2024 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | @testable import SwiftyDropbox 8 | import XCTest 9 | 10 | final class TestReconnectionHelperRouteNameMatching: XCTestCase { 11 | private let destination = URL(string: "/some/file.jpg")! 12 | 13 | func testMatchingFilesUploadSessionAppendV2() throws { 14 | try executeMatchingTest(route: Files.uploadSessionAppendV2, expectedRebuiltDescription: "files/upload_session/append_v2", upload: true) 15 | } 16 | 17 | func testMatchingFilesDownloadZip() throws { 18 | try executeMatchingTest(route: Files.downloadZip, expectedRebuiltDescription: "files/download_zip", upload: false) 19 | } 20 | 21 | func testMatchingSharingGetSharedLinkFile() throws { 22 | try executeMatchingTest(route: Sharing.getSharedLinkFile, expectedRebuiltDescription: "sharing/get_shared_link_file", upload: false) 23 | } 24 | 25 | func testMatchingPaperDocsDownload() throws { 26 | try executeMatchingTest(route: Paper.docsDownload, expectedRebuiltDescription: "paper/docs/download", upload: false) 27 | } 28 | 29 | private func executeMatchingTest(route: Route, expectedRebuiltDescription: String, upload: Bool) throws { 30 | let persistedInfo: ReconnectionHelpers.PersistedRequestInfo = upload 31 | ? .upload( 32 | .init( 33 | originalSDKVersion: DropboxClientsManager.sdkVersion, 34 | routeName: route.name, 35 | routeNamespace: route.namespace, 36 | clientProvidedInfo: nil 37 | ) 38 | ) 39 | : .downloadFile( 40 | .init( 41 | originalSDKVersion: DropboxClientsManager.sdkVersion, 42 | routeName: route.name, 43 | routeNamespace: route.namespace, 44 | destination: destination, 45 | overwrite: true 46 | ) 47 | ) 48 | 49 | let request = MockApiRequest(identifier: 0) 50 | request.taskDescription = try persistedInfo.asJsonString() 51 | 52 | let rebuiltRequest = try ReconnectionHelpers.rebuildRequest(apiRequest: request, client: MockDropboxTransportClient()) 53 | 54 | // Assert that request was successfully rebuilt 55 | XCTAssertEqual(rebuiltRequest.description, expectedRebuiltDescription) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxUnitTests/Request+Async.test.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2023 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | @testable import SwiftyDropbox 6 | import XCTest 7 | 8 | @available(iOS 13.0, macOS 10.15, *) 9 | final class RequestAsyncTests: XCTestCase { 10 | func testRpcResponseFails() async throws { 11 | let mockTransferClient = MockDropboxTransportClient() 12 | mockTransferClient.mockRequestHandler = MockDropboxTransportClient.alwaysFailMockRequestHandler 13 | let apiClient = DropboxClient(transportClient: mockTransferClient) 14 | 15 | let exp = expectation(description: "should fail") 16 | do { 17 | _ = try await apiClient.check.user().response() 18 | XCTFail("This should fail") 19 | } catch { 20 | exp.fulfill() 21 | } 22 | await fulfillment(of: [exp]) 23 | } 24 | 25 | func testRpcResponseSucceeds() async throws { 26 | let mockTransferClient = MockDropboxTransportClient() 27 | mockTransferClient.mockRequestHandler = { request in 28 | try? request.handleMockInput(.success(json: [:])) 29 | } 30 | let apiClient = DropboxClient(transportClient: mockTransferClient) 31 | 32 | let userCheck = try await apiClient.check.user().response() 33 | XCTAssertNotNil(userCheck) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxUnitTests/TestAsciiEncoding.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2023 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | @testable import SwiftyDropbox 8 | import XCTest 9 | 10 | final class TestAsciiEncoding: XCTestCase { 11 | let stringsToEncodedStrings = [ 12 | "héllø wörld": "h\\u00e9ll\\u00f8 w\\u00f6rld", 13 | "hello": "hello", 14 | "": "", 15 | "こんにちは": "\\u3053\\u3093\\u306b\\u3061\\u306f", 16 | "this has a clustered flag 🇺🇸": "this has a clustered flag \\ud83c\\uddfa\\ud83c\\uddf8", 17 | "this is a big emoji 👩‍👩‍👧‍👦": "this is a big emoji \\ud83d\\udc69\\u200d\\ud83d\\udc69\\u200d\\ud83d\\udc67\\u200d\\ud83d\\udc66", 18 | "🍺": "\\ud83c\\udf7a", 19 | "this\nhas some whitespace": "this\nhas some whitespace", 20 | ] 21 | 22 | func testEncodings() { 23 | for (key, value) in stringsToEncodedStrings { 24 | let lhs = Utilities.asciiEscape(key) 25 | let rhs = value 26 | XCTAssertEqual(lhs, rhs) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxUnitTests/TestNetworkSessionManager+Background.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | @testable import SwiftyDropbox 6 | import XCTest 7 | 8 | extension TestNetworkSessionManager { 9 | func testRecievingADelegateCallbackForAnUnregisteredTaskWrapsAndRegistersIt() throws { 10 | let request = sut.apiRequestData(request: { .example() }, networkTaskTag: "delegate-task") 11 | let mockRequest = try XCTUnwrap(request as? MockApiRequest) 12 | wait(for: taskCreationExpectations, timeout: 1) 13 | 14 | let underlyingTask = try XCTUnwrap(mockNetworkSession.tasks["delegate-task"] as? NetworkDataTask) 15 | 16 | sut.networkSession(mockNetworkSession, dataTask: underlyingTask, didReceive: Data()) 17 | 18 | XCTAssertEqual(sut.requestMap.getAllRequests().count, 1) 19 | XCTAssertEqual(sut.requestMap.getAllRequests().first?.identifier, mockRequest.identifier) 20 | } 21 | 22 | func testMultipleDelegateCallbacksDoNotLeadToMultipleRegistrations() throws { 23 | let request = sut.apiRequestData(request: { .example() }, networkTaskTag: "delegate-task") 24 | let mockRequest = try XCTUnwrap(request as? MockApiRequest) 25 | wait(for: taskCreationExpectations, timeout: 1) 26 | 27 | let underlyingTask = try XCTUnwrap(mockNetworkSession.tasks["delegate-task"] as? NetworkDataTask) 28 | 29 | // First 30 | sut.networkSession(mockNetworkSession, dataTask: underlyingTask, didReceive: Data()) 31 | 32 | // Second 33 | sut.networkSession(mockNetworkSession, task: underlyingTask, didCompleteWithError: nil) 34 | 35 | XCTAssertEqual(createdRequestCount, 1) 36 | XCTAssertEqual(sut.requestMap.getAllRequests().count, 1) 37 | XCTAssertEqual(sut.requestMap.getAllRequests().first?.identifier, mockRequest.identifier) 38 | } 39 | 40 | func testGetAllTasksRewrapsOnlyNewTasksAndReturnsAllUnownedApiRequests() throws { 41 | let e = expectation(description: "completion called") 42 | 43 | // Set a network session id so that the manager knows it's a background session 44 | // In background sessions we treat incoming unknown URLSessionDelegate calls differently 45 | mockNetworkSession.identifier = "bg" 46 | 47 | let existingApiRequest = sut.apiRequestData(request: { .example() }, networkTaskTag: "delegate-task") 48 | (existingApiRequest as? MockApiRequest)?.identifier = 0 49 | wait(for: taskCreationExpectations, timeout: 1) 50 | 51 | XCTAssertEqual(createdRequestCount, 1) 52 | 53 | // Add a pending task via URLSessionDelegate 54 | let pendingViaDelegateTask = MockNetworkTaskDelegate(request: .example()) 55 | pendingViaDelegateTask.taskIdentifier = 1 56 | sut.networkSession(sut.session, task: pendingViaDelegateTask, didSendBodyData: 0, totalBytesSent: 0, totalBytesExpectedToSend: 0) 57 | 58 | // add a pending task to be vended from URLSession.getAllTasks 59 | let pendingViaCompletionTask = MockNetworkTaskDelegate(request: .example()) 60 | pendingViaCompletionTask.taskIdentifier = 2 61 | 62 | mockNetworkSession.tasksPendingReconnection = [pendingViaCompletionTask] 63 | 64 | sut.getAllTasks { requests in 65 | XCTAssertEqual(requests.count, 2) 66 | XCTAssertEqual(self.createdRequestCount, 3) 67 | XCTAssertEqual(requests.idSet, [1, 2]) 68 | e.fulfill() 69 | } 70 | 71 | wait(for: [e], timeout: 1) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Source/SwiftyDropboxUnitTests/TestSecureStorageAccess.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | @testable import SwiftyDropbox 6 | import XCTest 7 | 8 | final class TestSecureStorageAccess: XCTestCase { 9 | private var appBundlePath: String! 10 | private var extensionBundlePath: String! 11 | private var macAppBundlePath: String! 12 | 13 | override func setUpWithError() throws { 14 | appBundlePath = "/private/var/containers/Bundle/Application/some-uuid/TestSwiftyDropbox_iOS.app" 15 | extensionBundlePath = "/private/var/containers/Bundle/Application/some-uuid/TestSwiftyDropbox_iOS.app/PlugIns/TestSwiftyDropbox_ActionExtension.appex" 16 | macAppBundlePath = "/Users/name/Library/Developer/Xcode/DerivedData/TestSwiftyDropbox-uuid/Build/Products/Debug/TestSwiftyDropbox_macOS.app" 17 | } 18 | 19 | func testCanFindAppBundleFromExtension() { 20 | let bundlePath = SecureStorageAccessDefaultImpl.appBundleAbsolutePath(from: extensionBundlePath) 21 | XCTAssertEqual(bundlePath, appBundlePath) 22 | } 23 | 24 | func testCanFindAppBundleFromApp() { 25 | let bundlePath = SecureStorageAccessDefaultImpl.appBundleAbsolutePath(from: appBundlePath) 26 | XCTAssertEqual(bundlePath, appBundlePath) 27 | } 28 | 29 | func testPathIsAbsolute() { 30 | let bundlePath = SecureStorageAccessDefaultImpl.appBundleAbsolutePath(from: macAppBundlePath) 31 | XCTAssertEqual(bundlePath.first, "/") 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SwiftyDropbox.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'SwiftyDropbox' 3 | s.version = '10.2.0' 4 | s.summary = 'Dropbox Swift SDK for API v2' 5 | s.homepage = 'https://dropbox.com/developers/' 6 | s.license = 'MIT' 7 | s.author = { 'Stephen Cobbe' => 'scobbe@dropbox.com' } 8 | s.source = { :git => 'https://github.com/dropbox/SwiftyDropbox.git', :tag => s.version } 9 | 10 | s.source_files = 'Source/SwiftyDropbox/Shared/**/*.{swift,h,m}' 11 | s.osx.source_files = 'Source/SwiftyDropbox/Platform/SwiftyDropbox_macOS/**/*.{swift,h,m}' 12 | s.ios.source_files = 'Source/SwiftyDropbox/Platform/SwiftyDropbox_iOS/**/*.{swift,h,m}' 13 | 14 | s.resource_bundles = { 15 | 'SwiftyDropboxPrivacyInfo' => ['Source/SwiftyDropbox/PrivacyInfo.xcprivacy'], 16 | } 17 | 18 | s.requires_arc = true 19 | s.swift_version = '5.6' 20 | 21 | s.osx.deployment_target = '10.13' 22 | s.ios.deployment_target = '12.0' 23 | 24 | s.osx.frameworks = 'AppKit', 'WebKit', 'SystemConfiguration', 'Foundation' 25 | s.ios.frameworks = 'UIKit', 'WebKit', 'SystemConfiguration', 'Foundation' 26 | end 27 | -------------------------------------------------------------------------------- /SwiftyDropboxObjc.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'SwiftyDropboxObjC' 3 | s.version = '10.2.0' 4 | s.summary = 'Objective-C Wrapper for Dropbox Swift SDK for API v2' 5 | s.homepage = 'https://dropbox.com/developers/' 6 | s.license = 'MIT' 7 | s.author = { 'Stephen Cobbe' => 'scobbe@dropbox.com' } 8 | s.source = { :git => 'https://github.com/dropbox/SwiftyDropbox.git', :tag => s.version } 9 | 10 | s.source_files = 'Source/SwiftyDropboxObjC/Shared/**/*.{swift,h,m}' 11 | s.osx.source_files = 'Source/SwiftyDropboxObjC/Platform/SwiftyDropbox_macOS/**/*.{swift,h,m}' 12 | s.ios.source_files = 'Source/SwiftyDropboxObjC/Platform/SwiftyDropbox_iOS/**/*.{swift,h,m}' 13 | 14 | s.resource_bundles = { 15 | 'SwiftyDropboxObjCPrivacyInfo' => ['Source/SwiftyDropboxObjC/PrivacyInfo.xcprivacy'], 16 | } 17 | 18 | s.requires_arc = true 19 | s.swift_version = '5.6' 20 | 21 | s.osx.deployment_target = '10.13' 22 | s.ios.deployment_target = '12.0' 23 | 24 | s.osx.frameworks = 'AppKit', 'WebKit', 'SystemConfiguration', 'Foundation' 25 | s.ios.frameworks = 'UIKit', 'WebKit', 'SystemConfiguration', 'Foundation' 26 | 27 | s.dependency 'SwiftyDropbox', '~> 10.2.0' 28 | end 29 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/IntegrationTests/BackgroundSessionTestClasses.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | import SwiftyDropbox 7 | 8 | enum BackgroundTestLogger { 9 | static var cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first! 10 | static var logsFileURL = cachesDirectory.appendingPathComponent("app_logs.txt") 11 | 12 | static func log(_ message: String) { 13 | NSLog(message) 14 | appendToFile(fileURL: logsFileURL, content: message) 15 | } 16 | 17 | static func appendToFile(fileURL: URL, content c: String) { 18 | let content = c + "\n" 19 | do { 20 | if FileManager.default.fileExists(atPath: fileURL.path) { 21 | let fileHandle = try FileHandle(forWritingTo: fileURL) 22 | fileHandle.seekToEndOfFile() 23 | if let data = content.data(using: .utf8) { 24 | fileHandle.write(data) 25 | } 26 | fileHandle.closeFile() 27 | } else { 28 | try content.write(to: fileURL, atomically: true, encoding: .utf8) 29 | } 30 | } catch { 31 | print("Error: Unable to append content to the file. \(error.localizedDescription)") 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/IntegrationTests/ObjC/ObjCTestData.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | @objc 8 | open class DBXTestData: NSObject { 9 | @objc static var testId: String { get { TestData.testId } set { TestData.testId = newValue } } 10 | @objc static var baseFolder: String { get { TestData.baseFolder } set { TestData.baseFolder = newValue } } 11 | 12 | @objc static var testFolderName: String { get { TestData.testFolderName } set { TestData.testFolderName = newValue } } 13 | @objc static var testFolderPath: String { get { TestData.testFolderPath } set { TestData.testFolderPath = newValue } } 14 | 15 | @objc static var testShareFolderName: String { get { TestData.testShareFolderName } set { TestData.testShareFolderName = newValue } } 16 | @objc static var testShareFolderPath: String { get { TestData.testShareFolderPath } set { TestData.testShareFolderPath = newValue } } 17 | 18 | @objc static var testFileName: String { get { TestData.testFileName } set { TestData.testFileName = newValue } } 19 | @objc static var testFilePath: String { get { TestData.testFilePath } set { TestData.testFilePath = newValue } } 20 | 21 | @objc static var testData: String { get { TestData.testData } set { TestData.testData = newValue } } 22 | 23 | @objc static var fileData: Data { get { TestData.fileData } set { TestData.fileData = newValue } } 24 | @objc static var fileManager: FileManager { get { TestData.fileManager } set { TestData.fileManager = newValue } } 25 | @objc static var directoryURL: URL { get { TestData.directoryURL } set { TestData.directoryURL = newValue } } 26 | @objc static var destURL: URL { get { TestData.destURL } set { TestData.destURL = newValue } } 27 | 28 | @objc static var accountId: String { get { TestData.accountId } set { TestData.accountId = newValue } } 29 | @objc static var accountId2: String { get { TestData.accountId2 } set { TestData.accountId2 = newValue } } 30 | @objc static var accountId3: String { get { TestData.accountId3 } set { TestData.accountId3 = newValue } } 31 | @objc static var accountId3Email: String { get { TestData.accountId3Email } set { TestData.accountId3Email = newValue } } 32 | 33 | @objc static var testIdTeam: String { get { TestData.testIdTeam } set { TestData.testIdTeam = newValue } } 34 | @objc static var groupName: String { get { TestData.groupName } set { TestData.groupName = newValue } } 35 | @objc static var groupExternalId: String { get { TestData.groupExternalId } set { TestData.groupExternalId = newValue } } 36 | @objc static var groupExternalIdDashObjc: String { TestData.groupExternalId + "-objc" } 37 | 38 | @objc static var teamMemberEmail: String { get { TestData.teamMemberEmail } set { TestData.teamMemberEmail = newValue } } 39 | @objc static var newMemberEmail: String { get { TestData.newMemberEmail } set { TestData.newMemberEmail = newValue } } 40 | 41 | @objc static var fullDropboxAppKey: String { get { TestData.fullDropboxAppKey } set { TestData.fullDropboxAppKey = newValue } } 42 | @objc static var fullDropboxAppSecret: String { get { TestData.fullDropboxAppSecret } set { TestData.fullDropboxAppSecret = newValue } } 43 | } 44 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/IntegrationTests/TestAppType.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | public enum AppPermission { 8 | case fullDropboxScoped 9 | case fullDropboxScopedForTeamTesting 10 | } 11 | 12 | let appPermission = AppPermission.fullDropboxScoped 13 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/IntegrationTests/TestData.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | import SwiftyDropbox 7 | 8 | open class TestData { 9 | // to avoid name collisions in the event of leftover test state from failure 10 | static var testId = String(arc4random_uniform(1_000)) 11 | 12 | static var baseFolder = "/Testing/SwiftyDropboxTests" 13 | 14 | static var testFolderName = "testFolder" 15 | static var testFolderPath = baseFolder + "/" + testFolderName + "_" + testId 16 | 17 | static var testShareFolderName = "testShareFolder" 18 | static var testShareFolderPath = baseFolder + "/" + testShareFolderName + "_" + testId 19 | 20 | static var testFileName = "testFile" 21 | static var testFilePath = testFolderPath + "/" + testFileName 22 | 23 | static var testData = "testing data example" 24 | 25 | static var fileData = testData.data(using: String.Encoding.utf8, allowLossyConversion: false)! 26 | static var fileManager = FileManager.default 27 | static var directoryURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0] 28 | static var destURL = directoryURL.appendingPathComponent(testFileName) 29 | 30 | static var destURLException = directoryURL.appendingPathComponent(testFileName + "_does_not_exist") 31 | 32 | // user-specific information 33 | 34 | // account ID of the user you OAuth linked with in order to test 35 | static var accountId = "" 36 | // any additional valid Dropbox account ID 37 | static var accountId2 = "" 38 | // any additional valid Dropbox account ID 39 | static var accountId3 = "" 40 | // the email address of the account whose account ID is `accoundId3` 41 | static var accountId3Email = "" 42 | 43 | // team-specific data 44 | 45 | // to avoid name collisions in the event of leftover test state from failure 46 | static var testIdTeam = String(arc4random_uniform(1_000)) 47 | 48 | static var groupName = "GroupName" + testIdTeam 49 | static var groupExternalId = "group-" + testIdTeam 50 | 51 | // user-specific information 52 | 53 | // email address of the team user you OAuth link with in order to test 54 | static var teamMemberEmail = "" 55 | static var newMemberEmail = "" 56 | 57 | // App key and secret 58 | static var fullDropboxAppKey = "" 59 | static var fullDropboxAppSecret = "" 60 | 61 | public static let backgroundSessionIdentifier = "" 62 | public static let extensionBackgroundSessionIdentifier = "" 63 | public static let sharedContainerIdentifier = "" 64 | } 65 | 66 | open class TestTeamData {} 67 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.1 2 | /// 3 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 4 | /// 5 | 6 | // This only exists so that Xcode doesn't display TestSwiftyDropbox 7 | 8 | import PackageDescription 9 | 10 | let package = Package( 11 | name: "client", 12 | products: [], 13 | targets: [] 14 | ) 15 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | def shared_iOS_pods 4 | platform :ios, '12.0' 5 | pod 'SwiftyDropbox', :path => '../' 6 | pod 'SwiftyDropboxObjC', :path => '../' 7 | end 8 | 9 | def shared_macOS_pods 10 | platform :osx, '10.13' 11 | pod 'SwiftyDropbox', :path => '../' 12 | pod 'SwiftyDropboxObjC', :path => '../' 13 | end 14 | 15 | target "TestSwiftyDropbox_iOS" do 16 | shared_iOS_pods 17 | 18 | target 'TestSwiftyDropbox_ActionExtension' do 19 | inherit! :search_paths 20 | end 21 | end 22 | 23 | target "TestSwiftyDropbox_iOSTests" do 24 | shared_iOS_pods 25 | end 26 | 27 | target "TestSwiftyDropbox_macOS" do 28 | shared_macOS_pods 29 | end 30 | 31 | target "TestSwiftyDropbox_macOSTests" do 32 | shared_macOS_pods 33 | end 34 | 35 | target "TestSwiftyDropbox_SwiftUI (iOS)" do 36 | shared_iOS_pods 37 | end 38 | 39 | target "TestSwiftyDropbox_SwiftUI (macOS)" do 40 | shared_macOS_pods 41 | end 42 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SwiftyDropbox (10.1.0) 3 | - SwiftyDropboxObjC (10.1.0): 4 | - SwiftyDropbox (~> 10.1.0) 5 | 6 | DEPENDENCIES: 7 | - SwiftyDropbox (from `../`) 8 | - SwiftyDropboxObjC (from `../`) 9 | 10 | EXTERNAL SOURCES: 11 | SwiftyDropbox: 12 | :path: "../" 13 | SwiftyDropboxObjC: 14 | :path: "../" 15 | 16 | SPEC CHECKSUMS: 17 | SwiftyDropbox: a023f55cb1bd8a81bb48c33eea529cd71faf8e29 18 | SwiftyDropboxObjC: c7f2189b65386016ea29942d222863dcd03159ac 19 | 20 | PODFILE CHECKSUM: e0f6bd11b29f3d698a8cf15c435947aa1ac4eee1 21 | 22 | COCOAPODS: 1.16.2 23 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_ActionExtension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionAttributes 8 | 9 | NSExtensionActivationRule 10 | 11 | NSExtensionActivationSupportsWebURLWithMaxCount 12 | 1 13 | 14 | NSExtensionServiceAllowsFinderPreviewItem 15 | 16 | NSExtensionServiceAllowsTouchBarItem 17 | 18 | NSExtensionServiceFinderPreviewIconName 19 | NSActionTemplate 20 | NSExtensionServiceTouchBarBezelColorName 21 | TouchBarBezel 22 | NSExtensionServiceTouchBarIconName 23 | NSActionTemplate 24 | 25 | NSExtensionPointIdentifier 26 | com.apple.services 27 | NSExtensionPrincipalClass 28 | $(PRODUCT_MODULE_NAME).ActionRequestHandler 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_ActionExtension/TestSwiftyDropbox_ActionExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | keychain-access-groups 6 | 7 | $(AppIdentifierPrefix)group.com.getdropbox.TestSwiftyDropbox 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_SwiftUI/Shared/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_SwiftUI/Shared/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | }, 93 | { 94 | "idiom" : "mac", 95 | "scale" : "1x", 96 | "size" : "16x16" 97 | }, 98 | { 99 | "idiom" : "mac", 100 | "scale" : "2x", 101 | "size" : "16x16" 102 | }, 103 | { 104 | "idiom" : "mac", 105 | "scale" : "1x", 106 | "size" : "32x32" 107 | }, 108 | { 109 | "idiom" : "mac", 110 | "scale" : "2x", 111 | "size" : "32x32" 112 | }, 113 | { 114 | "idiom" : "mac", 115 | "scale" : "1x", 116 | "size" : "128x128" 117 | }, 118 | { 119 | "idiom" : "mac", 120 | "scale" : "2x", 121 | "size" : "128x128" 122 | }, 123 | { 124 | "idiom" : "mac", 125 | "scale" : "1x", 126 | "size" : "256x256" 127 | }, 128 | { 129 | "idiom" : "mac", 130 | "scale" : "2x", 131 | "size" : "256x256" 132 | }, 133 | { 134 | "idiom" : "mac", 135 | "scale" : "1x", 136 | "size" : "512x512" 137 | }, 138 | { 139 | "idiom" : "mac", 140 | "scale" : "2x", 141 | "size" : "512x512" 142 | } 143 | ], 144 | "info" : { 145 | "author" : "xcode", 146 | "version" : 1 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_SwiftUI/Shared/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_SwiftUI/iOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | import SwiftyDropbox 7 | 8 | class AppDelegate: UIResponder, UIApplicationDelegate, ObservableObject { 9 | var window: UIWindow? 10 | 11 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 12 | let processInfo = ProcessInfo.processInfo.environment 13 | let inTestScheme = processInfo["FULL_DROPBOX_API_APP_KEY"] != nil 14 | 15 | // Skip setup if launching for unit tests, XCTests set up the clients themselves 16 | if inTestScheme { 17 | return true 18 | } 19 | 20 | if TestData.fullDropboxAppKey.range(of: "<") != nil { 21 | print("\n\n\nMust set test data (in TestData.swift) before launching app.\n\n\nTerminating.....\n\n") 22 | exit(0) 23 | } 24 | switch appPermission { 25 | case .fullDropboxScoped: 26 | DropboxClientsManager.setupWithAppKey(TestData.fullDropboxAppKey) 27 | case .fullDropboxScopedForTeamTesting: 28 | DropboxClientsManager.setupWithTeamAppKey(TestData.fullDropboxAppKey) 29 | } 30 | 31 | return true 32 | } 33 | 34 | func application( 35 | _ application: UIApplication, 36 | configurationForConnecting connectingSceneSession: UISceneSession, 37 | options: UIScene.ConnectionOptions 38 | ) -> UISceneConfiguration { 39 | let sceneConfig = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role) 40 | sceneConfig.delegateClass = SceneDelegate.self 41 | return sceneConfig 42 | } 43 | } 44 | 45 | class SceneDelegate: NSObject, UIWindowSceneDelegate, ObservableObject { 46 | @Published var userAuthed: Bool = false 47 | 48 | func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { 49 | guard let url = URLContexts.first?.url else { return } 50 | let oauthCompletion: DropboxOAuthCompletion = { [weak self] in 51 | if let authResult = $0 { 52 | switch authResult { 53 | case .success: 54 | print("Success! User is logged into DropboxClientsManager.") 55 | self?.userAuthed = true 56 | case .cancel: 57 | print("Authorization flow was manually canceled by user!") 58 | self?.userAuthed = false 59 | case .error(_, let description): 60 | print("Error: \(String(describing: description))") 61 | self?.userAuthed = false 62 | } 63 | } 64 | } 65 | 66 | switch appPermission { 67 | case .fullDropboxScoped: 68 | _ = DropboxClientsManager.handleRedirectURL(url, completion: oauthCompletion) 69 | case .fullDropboxScopedForTeamTesting: 70 | _ = DropboxClientsManager.handleRedirectURLTeam(url, completion: oauthCompletion) 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_SwiftUI/iOS/ContentView.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import SwiftUI 6 | import SwiftyDropbox 7 | 8 | struct ContentView: View { 9 | @EnvironmentObject private var appDelegate: AppDelegate 10 | @EnvironmentObject var sceneDelegate: SceneDelegate 11 | @ObservedObject var viewModel = ViewModel() 12 | 13 | var body: some View { 14 | if viewModel.isLinked || sceneDelegate.userAuthed { 15 | VStack { 16 | Button("Run API Tests", action: runApiTests) 17 | .padding() 18 | Button("Unlink Dropbox Account", action: unlink) 19 | .padding() 20 | } 21 | .padding() 22 | } else { 23 | Button("Link Dropbox (pkce code flow)", action: link) 24 | .padding() 25 | } 26 | } 27 | 28 | func runApiTests() { 29 | let unlink = { 30 | DropboxClientsManager.unlinkClients() 31 | viewModel.checkIsLinked() 32 | sceneDelegate.userAuthed = false 33 | exit(0) 34 | } 35 | 36 | switch appPermission { 37 | case .fullDropboxScoped: 38 | DropboxTester().testAllUserEndpoints(asMember: false, nextTest: unlink) 39 | case .fullDropboxScopedForTeamTesting: 40 | DropboxTeamTester().testTeamMemberFileAcessActions(unlink) 41 | } 42 | } 43 | 44 | func unlink() { 45 | DropboxClientsManager.unlinkClients() 46 | viewModel.checkIsLinked() 47 | sceneDelegate.userAuthed = false 48 | } 49 | 50 | func link() { 51 | let scopeRequest: ScopeRequest 52 | // note if you add new scopes, you need to relogin to update your token 53 | switch appPermission { 54 | case .fullDropboxScoped: 55 | scopeRequest = ScopeRequest(scopeType: .user, scopes: DropboxTester.scopes, includeGrantedScopes: false) 56 | case .fullDropboxScopedForTeamTesting: 57 | scopeRequest = ScopeRequest(scopeType: .team, scopes: DropboxTeamTester.scopes, includeGrantedScopes: false) 58 | } 59 | DropboxClientsManager.authorizeFromControllerV2( 60 | UIApplication.shared, 61 | controller: nil, 62 | loadingStatusDelegate: nil, 63 | openURL: { (url: URL) -> Void in UIApplication.shared.open(url, options: [:], completionHandler: nil) }, 64 | scopeRequest: scopeRequest 65 | ) 66 | } 67 | } 68 | 69 | class ViewModel: ObservableObject { 70 | @Published var isLinked: Bool 71 | 72 | init() { 73 | self.isLinked = ViewModel.sdkIsLinked() 74 | } 75 | 76 | func checkIsLinked() { 77 | isLinked = ViewModel.sdkIsLinked() 78 | } 79 | 80 | private static func sdkIsLinked() -> Bool { 81 | DropboxClientsManager.authorizedClient != nil || DropboxClientsManager.authorizedTeamClient != nil 82 | } 83 | } 84 | 85 | struct ContentView_Previews: PreviewProvider { 86 | static var previews: some View { 87 | ContentView() 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_SwiftUI/iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleURLTypes 6 | 7 | 8 | CFBundleTypeRole 9 | Editor 10 | CFBundleURLSchemes 11 | 12 | db-<APP_KEY> 13 | db-<APP_KEY> 14 | db-<APP_KEY> 15 | 16 | 17 | 18 | LSApplicationQueriesSchemes 19 | 20 | dbapi-2 21 | dbapi-8-emm 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_SwiftUI/iOS/TestSwiftyDropboxApp.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import SwiftUI 6 | 7 | @main 8 | struct TestSwiftyDropboxApp: App { 9 | @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate 10 | 11 | var body: some Scene { 12 | WindowGroup { 13 | ContentView() 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_SwiftUI/macOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | import SwiftyDropbox 7 | 8 | class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject { 9 | @Published var userAuthed: Bool = false 10 | 11 | func applicationDidFinishLaunching(_ aNotification: Notification) { 12 | let processInfo = ProcessInfo.processInfo.environment 13 | let inTestScheme = processInfo["FULL_DROPBOX_API_APP_KEY"] != nil 14 | 15 | // Skip setup if launching for unit tests, XCTests set up the clients themselves 16 | if inTestScheme { 17 | return 18 | } 19 | 20 | if TestData.fullDropboxAppKey.range(of: "<") != nil { 21 | print("\n\n\nMust set test data (in TestData.swift) before launching app.\n\n\nTerminating.....\n\n") 22 | exit(0) 23 | } 24 | switch appPermission { 25 | case .fullDropboxScoped: 26 | DropboxClientsManager.setupWithAppKeyDesktop(TestData.fullDropboxAppKey) 27 | case .fullDropboxScopedForTeamTesting: 28 | DropboxClientsManager.setupWithTeamAppKeyDesktop(TestData.fullDropboxAppKey) 29 | } 30 | NSAppleEventManager.shared() 31 | .setEventHandler( 32 | self, 33 | andSelector: #selector(handleGetURLEvent), 34 | forEventClass: AEEventClass(kInternetEventClass), 35 | andEventID: AEEventID(kAEGetURL) 36 | ) 37 | } 38 | 39 | @objc func handleGetURLEvent(_ event: NSAppleEventDescriptor?, replyEvent: NSAppleEventDescriptor?) { 40 | if let aeEventDescriptor = event?.paramDescriptor(forKeyword: AEKeyword(keyDirectObject)) { 41 | if let urlStr = aeEventDescriptor.stringValue { 42 | guard let url = URL(string: urlStr) else { return } 43 | let oauthCompletion: DropboxOAuthCompletion = { [weak self] in 44 | if let authResult = $0 { 45 | switch authResult { 46 | case .success: 47 | print("Success! User is logged into DropboxClientsManager.") 48 | self?.userAuthed = true 49 | case .cancel: 50 | print("Authorization flow was manually canceled by user!") 51 | self?.userAuthed = false 52 | case .error(_, let description): 53 | print("Error: \(String(describing: description))") 54 | self?.userAuthed = false 55 | } 56 | } 57 | } 58 | 59 | switch appPermission { 60 | case .fullDropboxScoped: 61 | DropboxClientsManager.handleRedirectURL(url, completion: oauthCompletion) 62 | case .fullDropboxScopedForTeamTesting: 63 | DropboxClientsManager.handleRedirectURLTeam(url, completion: oauthCompletion) 64 | } 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_SwiftUI/macOS/ContentView.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import SwiftUI 6 | import SwiftyDropbox 7 | 8 | struct ContentView: View { 9 | @EnvironmentObject var appDelegate: AppDelegate 10 | @ObservedObject var viewModel = ViewModel() 11 | 12 | var body: some View { 13 | if viewModel.isLinked || appDelegate.userAuthed { 14 | VStack { 15 | Button("Run API Tests", action: runApiTests) 16 | .padding() 17 | Button("Unlink Dropbox Account", action: unlink) 18 | .padding() 19 | } 20 | .padding() 21 | } else { 22 | Button("Link Dropbox (pkce code flow)", action: link) 23 | .padding() 24 | } 25 | } 26 | 27 | func runApiTests() { 28 | let unlink = { 29 | DropboxClientsManager.unlinkClients() 30 | viewModel.checkIsLinked() 31 | appDelegate.userAuthed = false 32 | exit(0) 33 | } 34 | 35 | switch appPermission { 36 | case .fullDropboxScoped: 37 | DropboxTester().testAllUserEndpoints(asMember: false, nextTest: unlink) 38 | case .fullDropboxScopedForTeamTesting: 39 | DropboxTeamTester().testTeamMemberFileAcessActions(unlink) 40 | } 41 | } 42 | 43 | func unlink() { 44 | DropboxClientsManager.unlinkClients() 45 | viewModel.checkIsLinked() 46 | appDelegate.userAuthed = false 47 | } 48 | 49 | func link() { 50 | let scopeRequest: ScopeRequest 51 | // note if you add new scopes, you need to relogin to update your token 52 | switch appPermission { 53 | case .fullDropboxScoped: 54 | scopeRequest = ScopeRequest(scopeType: .user, scopes: DropboxTester.scopes, includeGrantedScopes: false) 55 | case .fullDropboxScopedForTeamTesting: 56 | scopeRequest = ScopeRequest(scopeType: .team, scopes: DropboxTeamTester.scopes, includeGrantedScopes: false) 57 | } 58 | 59 | DropboxClientsManager.authorizeFromControllerV2( 60 | sharedApplication: NSApplication.shared, 61 | controller: nil, 62 | loadingStatusDelegate: nil, 63 | openURL: { (url: URL) -> Void in NSWorkspace.shared.open(url) }, 64 | scopeRequest: scopeRequest 65 | ) 66 | } 67 | } 68 | 69 | class ViewModel: ObservableObject { 70 | @Published var isLinked: Bool 71 | 72 | init() { 73 | self.isLinked = ViewModel.sdkIsLinked() 74 | } 75 | 76 | func checkIsLinked() { 77 | isLinked = ViewModel.sdkIsLinked() 78 | } 79 | 80 | private static func sdkIsLinked() -> Bool { 81 | DropboxClientsManager.authorizedClient != nil || DropboxClientsManager.authorizedTeamClient != nil 82 | } 83 | } 84 | 85 | struct ContentView_Previews: PreviewProvider { 86 | static var previews: some View { 87 | ContentView() 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_SwiftUI/macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleURLTypes 6 | 7 | 8 | CFBundleTypeRole 9 | Editor 10 | CFBundleURLSchemes 11 | 12 | db-<APP_KEY> 13 | db-<APP_KEY> 14 | db-<APP_KEY> 15 | 16 | 17 | 18 | LSApplicationQueriesSchemes 19 | 20 | dbapi-2 21 | dbapi-8-emm 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_SwiftUI/macOS/TestSwiftyDropboxApp.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2022 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import SwiftUI 6 | 7 | @main 8 | struct TestSwiftyDropboxApp: App { 9 | @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate 10 | 11 | var body: some Scene { 12 | WindowGroup { 13 | ContentView() 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_SwiftUI/macOS/macOS.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_iOS/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_iOS/FileBrowserView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2023 Dropbox. All rights reserved. 3 | // 4 | 5 | import SwiftUI 6 | 7 | @available(iOS 16.0, *) 8 | func MakeFileBrowserView(localURL: URL?) -> FileBrowserView { 9 | FileBrowserView(viewModel: FileBrowserViewModel(localURL: localURL)) 10 | } 11 | 12 | @available(iOS 16.0, *) 13 | class FileBrowserViewModel: ObservableObject { 14 | let localURL: URL? 15 | @Published var files: [URL] = [] 16 | @Published var showAlert = false 17 | @Published var selectedFileContent: String = "" 18 | 19 | init(localURL: URL?) { 20 | self.localURL = localURL 21 | 22 | let fileManager = FileManager.default 23 | 24 | guard let localURL = localURL else { 25 | return 26 | } 27 | 28 | do { 29 | let fileURLs = try fileManager.contentsOfDirectory(at: localURL, includingPropertiesForKeys: nil) 30 | self.files = fileURLs.sorted(by: { $0.lastPathComponent < $1.lastPathComponent }) 31 | } catch { 32 | print("Error loading files: \(error)") 33 | } 34 | } 35 | 36 | func showFile(fileURL: URL) -> () -> Void { 37 | { 38 | do { 39 | self.selectedFileContent = String(try String(contentsOf: fileURL).prefix(10_000)) 40 | self.showAlert = true 41 | } catch { 42 | print("Error reading file: \(error)") 43 | } 44 | } 45 | } 46 | } 47 | 48 | @available(iOS 16.0, *) 49 | struct FileBrowserView: View { 50 | @Environment(\.dismiss) private var dismiss 51 | @ObservedObject var viewModel: FileBrowserViewModel 52 | 53 | var body: some View { 54 | NavigationView { 55 | VStack { 56 | Text("Files Count: \(viewModel.files.count)") 57 | if viewModel.files.isEmpty { 58 | Text("Folder doesn't exist or is empty") 59 | .foregroundColor(.red) 60 | } else { 61 | List(viewModel.files, id: \.self) { fileURL in 62 | Button(action: viewModel.showFile(fileURL: fileURL)) { 63 | Text(fileURL.lastPathComponent) 64 | } 65 | } 66 | } 67 | } 68 | .alert(isPresented: $viewModel.showAlert) { 69 | Alert(title: Text("File Content"), message: Text(viewModel.selectedFileContent), dismissButton: .default(Text("Close"))) 70 | } 71 | .toolbar { 72 | ToolbarItem(placement: .navigationBarLeading) { 73 | Button("Close") { 74 | dismiss() 75 | } 76 | } 77 | } 78 | } 79 | } 80 | } 81 | 82 | @available(iOS 16.0, *) 83 | struct FileBrowserView_Previews: PreviewProvider { 84 | static var previews: some View { 85 | FileBrowserView(viewModel: FileBrowserViewModel(localURL: nil)) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleURLTypes 22 | 23 | 24 | CFBundleTypeRole 25 | Editor 26 | CFBundleURLSchemes 27 | 28 | db-<APP_KEY> 29 | db-<APP_KEY> 30 | db-<APP_KEY> 31 | 32 | 33 | 34 | CFBundleVersion 35 | 1 36 | LSApplicationQueriesSchemes 37 | 38 | dbapi-2 39 | dbapi-8-emm 40 | 41 | LSRequiresIPhoneOS 42 | 43 | UILaunchStoryboardName 44 | LaunchScreen 45 | UIMainStoryboardFile 46 | Main 47 | UIRequiredDeviceCapabilities 48 | 49 | armv7 50 | 51 | UISupportedInterfaceOrientations 52 | 53 | UIInterfaceOrientationPortrait 54 | UIInterfaceOrientationLandscapeLeft 55 | UIInterfaceOrientationLandscapeRight 56 | 57 | UISupportedInterfaceOrientations~ipad 58 | 59 | UIInterfaceOrientationPortrait 60 | UIInterfaceOrientationPortraitUpsideDown 61 | UIInterfaceOrientationLandscapeLeft 62 | UIInterfaceOrientationLandscapeRight 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_iOS/TestSwiftyDropbox.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | keychain-access-groups 6 | 7 | $(AppIdentifierPrefix)(null) 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_iOS/TestUtilities.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2023 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Foundation 6 | 7 | public enum TestConstants { 8 | public static var sharedContainerDirectory = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: TestData.sharedContainerIdentifier)! 9 | public static var cachesDirectory = sharedContainerDirectory.appendingPathComponent("Caches") 10 | public static var fileToUpload = cachesDirectory.appendingPathComponent("file.txt") 11 | public static var dropboxTestFolder = "/background_session_testing" 12 | public static var localDownloadFolder = cachesDirectory.appendingPathComponent("downloads") 13 | } 14 | 15 | public class TestUtilities { 16 | public static func createFileToUpload(sizeInKBs: Double) { 17 | let sizeInBytes = Int(1_024 * sizeInKBs) 18 | writeFile(ofSize: sizeInBytes, at: TestConstants.fileToUpload) 19 | } 20 | 21 | public static func writeFile(ofSize size: Int, at url: URL) { 22 | let content = "test_content" 23 | let contentData = content.data(using: .utf8)! 24 | let dataSize = contentData.count 25 | 26 | do { 27 | let repeatCount = size / dataSize 28 | let fileContent = String(repeating: content, count: repeatCount) 29 | 30 | try fileContent.write(to: url, atomically: true, encoding: .utf8) 31 | } catch { 32 | print("Error writing file: \(error)") 33 | } 34 | } 35 | 36 | public static func summary(of route: String, from response: CustomStringConvertible?, error: CustomStringConvertible?) -> String { 37 | "\(route) response: \(response?.description ?? "nil") error: \(error?.description ?? "nil")" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_iOSTests/CustomRoutesTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2022 Dropbox Inc. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | import XCTest 8 | #if os(OSX) 9 | @testable import TestSwiftyDropbox_macOS 10 | #elseif os(iOS) 11 | @testable import TestSwiftyDropbox_iOS 12 | #endif 13 | 14 | @testable import SwiftyDropbox 15 | 16 | class CustomRoutesTests: XCTestCase { 17 | private var userClient: UsersRoutes! 18 | private var tester: DropboxTester! 19 | 20 | override func setUp() { 21 | // You need an API app with the "Full Dropbox" permission type and at least the scopes in DropboxTester.scopes 22 | // and no team scopes. 23 | // You can create one for testing here: https://www.dropbox.com/developers/apps/create 24 | // The 'App key' will be on the app's info page. 25 | // Then follow https://dropbox.tech/developers/pkce--what-and-why- to get a refresh token using the PKCE flow 26 | 27 | continueAfterFailure = false 28 | 29 | if DropboxClientsManager.authorizedClient == nil { 30 | setupDropboxClientsManager() 31 | } 32 | 33 | userClient = DropboxClientsManager.authorizedClient!.users! 34 | tester = DropboxTester() 35 | } 36 | 37 | func setupDropboxClientsManager() { 38 | let processInfo = ProcessInfo.processInfo.environment 39 | 40 | guard let apiAppKey = processInfo["FULL_DROPBOX_API_APP_KEY"] else { 41 | return XCTFail("FULL_DROPBOX_API_APP_KEY needs to be set in the test Scheme") 42 | } 43 | guard let refreshToken = processInfo["FULL_DROPBOX_TESTER_USER_REFRESH_TOKEN"] else { 44 | return XCTFail("FULL_DROPBOX_TESTER_USER_REFRESH_TOKEN needs to be set in the test Scheme") 45 | } 46 | 47 | guard let transportClient = TestAuthTokenGenerator.transportClient(with: refreshToken, apiKey: apiAppKey, scopes: DropboxTester.scopes) else { 48 | return XCTFail("Error: Access token creation failed") 49 | } 50 | 51 | #if os(OSX) 52 | DropboxClientsManager.setupWithAppKeyDesktop(apiAppKey, transportClient: transportClient, secureStorageAccess: SecureStorageAccessTestImpl()) 53 | #elseif os(iOS) 54 | DropboxClientsManager.setupWithAppKey(apiAppKey, transportClient: transportClient, secureStorageAccess: SecureStorageAccessTestImpl()) 55 | #endif 56 | } 57 | 58 | override func tearDown() { 59 | print("tearDown: delete folder") 60 | let flag = XCTestExpectation() 61 | 62 | FilesTests(tester: tester).deleteV2 { 63 | flag.fulfill() 64 | } 65 | 66 | _ = XCTWaiter.wait(for: [flag], timeout: 30) // don't need to check result on tear down 67 | } 68 | 69 | func testFileRoutes() { 70 | let flag = XCTestExpectation() 71 | 72 | let nextTest = { 73 | flag.fulfill() 74 | } 75 | 76 | tester.testCustomActions(nextTest) 77 | 78 | let result = XCTWaiter.wait(for: [flag], timeout: 60 * 5) 79 | XCTAssertEqual(result, .completed, "Error: timeout on file routes tests") 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_iOSTests/FilesRoutesTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FilesRoutesTests.swift 3 | // FilesRoutesTests 4 | // 5 | // Created by jlocke on 5/20/21. 6 | // Copyright © 2021 Dropbox. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | #if os(OSX) 11 | @testable import TestSwiftyDropbox_macOS 12 | #elseif os(iOS) 13 | @testable import TestSwiftyDropbox_iOS 14 | #endif 15 | 16 | @testable import SwiftyDropbox 17 | 18 | class FilesRoutesTests: XCTestCase { 19 | private var userClient: UsersRoutes! 20 | private var tester: DropboxTester! 21 | 22 | override func setUp() { 23 | // You need an API app with the "Full Dropbox" permission type and at least the scopes in DropboxTester.scopes 24 | // and no team scopes. 25 | // You can create one for testing here: https://www.dropbox.com/developers/apps/create 26 | // The 'App key' will be on the app's info page. 27 | // Then follow https://dropbox.tech/developers/pkce--what-and-why- to get a refresh token using the PKCE flow 28 | 29 | continueAfterFailure = false 30 | 31 | if DropboxClientsManager.authorizedClient == nil { 32 | setupDropboxClientsManager() 33 | } 34 | 35 | userClient = DropboxClientsManager.authorizedClient!.users! 36 | tester = DropboxTester() 37 | } 38 | 39 | func setupDropboxClientsManager() { 40 | let processInfo = ProcessInfo.processInfo.environment 41 | 42 | guard let apiAppKey = processInfo["FULL_DROPBOX_API_APP_KEY"] else { 43 | return XCTFail("FULL_DROPBOX_API_APP_KEY needs to be set in the test Scheme") 44 | } 45 | guard let refreshToken = processInfo["FULL_DROPBOX_TESTER_USER_REFRESH_TOKEN"] else { 46 | return XCTFail("FULL_DROPBOX_TESTER_USER_REFRESH_TOKEN needs to be set in the test Scheme") 47 | } 48 | 49 | guard let transportClient = TestAuthTokenGenerator.transportClient(with: refreshToken, apiKey: apiAppKey, scopes: DropboxTester.scopes) else { 50 | return XCTFail("Error: Access token creation failed") 51 | } 52 | 53 | #if os(OSX) 54 | DropboxClientsManager.setupWithAppKeyDesktop(apiAppKey, transportClient: transportClient, secureStorageAccess: SecureStorageAccessTestImpl()) 55 | #elseif os(iOS) 56 | DropboxClientsManager.setupWithAppKey(apiAppKey, transportClient: transportClient, secureStorageAccess: SecureStorageAccessTestImpl()) 57 | #endif 58 | } 59 | 60 | override func tearDown() { 61 | print("tearDown: delete folder") 62 | let flag = XCTestExpectation() 63 | 64 | FilesTests(tester: tester).deleteV2 { 65 | flag.fulfill() 66 | } 67 | 68 | _ = XCTWaiter.wait(for: [flag], timeout: 30) // don't need to check result on tear down 69 | } 70 | 71 | func testFileRoutes() { 72 | let flag = XCTestExpectation() 73 | 74 | let nextTest = { 75 | flag.fulfill() 76 | } 77 | 78 | tester.testFilesActions(nextTest, asMember: false) 79 | 80 | let result = XCTWaiter.wait(for: [flag], timeout: 60 * 5) 81 | XCTAssertEqual(result, .completed, "Error: timeout on file routes tests") 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_iOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_iOSTests/ObjCFilesRoutesTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjCUserRoutesTests.h 3 | // TestSwiftyDropbox 4 | // 5 | // Created by Taylor Case on 10/11/22. 6 | // Copyright © 2022 Dropbox. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ObjCFilesRoutesTests : XCTestCase 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_iOSTests/ObjCTeamRoutesTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjCTeamRoutesTests.h 3 | // TestSwiftyDropbox 4 | // 5 | // Created by Taylor Case on 12/16/22. 6 | // Copyright © 2022 Dropbox. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ObjCTeamRoutesTests : XCTestCase 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_iOSTests/SwiftyDropboxTestExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestSecureStorageAccess.swift 3 | // TestSwiftyDropbox 4 | // 5 | // Created by jlocke on 12/13/23. 6 | // Copyright © 2023 Dropbox. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftyDropbox 11 | import SwiftyDropboxObjC 12 | 13 | public extension DBXDropboxOAuthManager { 14 | @objc 15 | static func __test_only_resetForTeamSetup() { 16 | DropboxOAuthManager.sharedOAuthManager = nil 17 | } 18 | } 19 | 20 | @objc 21 | public class DBXSecureStorageAccessTestImpl: DBXSecureStorageAccessImpl { 22 | @objc 23 | public convenience init() { 24 | self.init(swift: SecureStorageAccessTestImpl()) 25 | } 26 | 27 | fileprivate init(swift: SecureStorageAccessTestImpl) { 28 | super.init(swift: swift) 29 | } 30 | } 31 | 32 | public class SecureStorageAccessTestImpl: SecureStorageAccess { 33 | private static var accessTokenData: Data? 34 | 35 | public init() {} 36 | 37 | public func checkAccessibilityMigrationOneTime() {} 38 | 39 | public func setAccessTokenData(for userId: String, data: Data) -> Bool { 40 | Self.accessTokenData = data 41 | return true 42 | } 43 | 44 | public func getAllUserIds() -> [String] { 45 | [TestAuthTokenGenerator.testUid] 46 | } 47 | 48 | public func getDropboxAccessToken(for key: String) -> DropboxAccessToken? { 49 | guard let accessTokenData = Self.accessTokenData else { 50 | return nil 51 | } 52 | 53 | let jsonDecoder = JSONDecoder() 54 | return try? jsonDecoder.decode(DropboxAccessToken.self, from: accessTokenData) 55 | } 56 | 57 | public func deleteInfo(for key: String) -> Bool { 58 | true 59 | } 60 | 61 | public func deleteInfoForAllKeys() -> Bool { 62 | true 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_macOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright (c) 2016 Dropbox, Inc. All rights reserved. 3 | /// 4 | 5 | import Cocoa 6 | import SwiftyDropbox 7 | 8 | @NSApplicationMain 9 | class AppDelegate: NSObject, NSApplicationDelegate { 10 | var viewController: ViewController? 11 | 12 | func applicationDidFinishLaunching(_ aNotification: Notification) { 13 | let processInfo = ProcessInfo.processInfo.environment 14 | let inTestScheme = processInfo["FULL_DROPBOX_API_APP_KEY"] != nil 15 | 16 | // Skip setup if launching for unit tests, XCTests set up the clients themselves 17 | if inTestScheme { 18 | return 19 | } 20 | 21 | if TestData.fullDropboxAppKey.range(of: "<") != nil { 22 | print("\n\n\nMust set test data (in TestData.swift) before launching app.\n\n\nTerminating.....\n\n") 23 | exit(0) 24 | } 25 | switch appPermission { 26 | case .fullDropboxScoped: 27 | DropboxClientsManager.setupWithAppKeyDesktop(TestData.fullDropboxAppKey) 28 | case .fullDropboxScopedForTeamTesting: 29 | DropboxClientsManager.setupWithTeamAppKeyDesktop(TestData.fullDropboxAppKey) 30 | } 31 | NSAppleEventManager.shared() 32 | .setEventHandler( 33 | self, 34 | andSelector: #selector(handleGetURLEvent), 35 | forEventClass: AEEventClass(kInternetEventClass), 36 | andEventID: AEEventID(kAEGetURL) 37 | ) 38 | 39 | viewController = NSApplication.shared.windows[0].contentViewController as? ViewController 40 | checkButtons() 41 | } 42 | 43 | @objc func handleGetURLEvent(_ event: NSAppleEventDescriptor?, replyEvent: NSAppleEventDescriptor?) { 44 | if let aeEventDescriptor = event?.paramDescriptor(forKeyword: AEKeyword(keyDirectObject)) { 45 | if let urlStr = aeEventDescriptor.stringValue { 46 | let url = URL(string: urlStr)! 47 | let oauthCompletion: DropboxOAuthCompletion = { 48 | if let authResult = $0 { 49 | switch authResult { 50 | case .success: 51 | print("Success! User is logged into Dropbox.") 52 | case .cancel: 53 | print("Authorization flow was manually canceled by user!") 54 | case .error(_, let description): 55 | print("Error: \(String(describing: description))") 56 | } 57 | } 58 | self.checkButtons() 59 | } 60 | 61 | switch appPermission { 62 | case .fullDropboxScoped: 63 | DropboxClientsManager.handleRedirectURL(url, includeBackgroundClient: false, completion: oauthCompletion) 64 | case .fullDropboxScopedForTeamTesting: 65 | DropboxClientsManager.handleRedirectURLTeam(url, completion: oauthCompletion) 66 | } 67 | } 68 | } 69 | } 70 | 71 | func applicationWillTerminate(_ aNotification: Notification) { 72 | // Insert code here to tear down your application 73 | } 74 | 75 | func checkButtons() { 76 | viewController?.checkButtons() 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_macOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LSApplicationQueriesSchemes 6 | 7 | dbapi-2 8 | dbapi-8-emm 9 | 10 | CFBundleURLTypes 11 | 12 | 13 | CFBundleTypeRole 14 | Editor 15 | CFBundleURLSchemes 16 | 17 | db-<APP_KEY> 18 | db-<APP_KEY> 19 | db-<APP_KEY> 20 | 21 | 22 | 23 | CFBundleDevelopmentRegion 24 | en 25 | CFBundleExecutable 26 | $(EXECUTABLE_NAME) 27 | CFBundleIconFile 28 | 29 | CFBundleIdentifier 30 | $(PRODUCT_BUNDLE_IDENTIFIER) 31 | CFBundleInfoDictionaryVersion 32 | 6.0 33 | CFBundleName 34 | $(PRODUCT_NAME) 35 | CFBundlePackageType 36 | APPL 37 | CFBundleShortVersionString 38 | 1.0 39 | CFBundleVersion 40 | 1 41 | LSMinimumSystemVersion 42 | $(MACOSX_DEPLOYMENT_TARGET) 43 | NSHumanReadableCopyright 44 | Copyright © 2017 Dropbox. All rights reserved. 45 | NSMainStoryboardFile 46 | Main 47 | NSPrincipalClass 48 | NSApplication 49 | 50 | 51 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestSwiftyDropbox_macOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /TestSwiftyDropbox/TestUtils/TestTokenAuthGenerator.swift: -------------------------------------------------------------------------------- 1 | @testable import SwiftyDropbox 2 | import XCTest 3 | 4 | enum TestAuthTokenGenerator { 5 | static let testUid = "test" // non-empty string needed here as subsequent tokens will share the uid and macOS keychain drops the attribute if empty 6 | 7 | static func transportClient(with refreshToken: String, apiKey: String, scopes: [String]) -> DropboxTransportClient? { 8 | let manager = SwiftyDropbox.DropboxOAuthManager(appKey: apiKey, secureStorageAccess: SecureStorageAccessTestImpl()) 9 | 10 | let defaultToken = DropboxAccessToken( 11 | accessToken: "", 12 | uid: Self.testUid, 13 | refreshToken: refreshToken, 14 | tokenExpirationTimestamp: 0 15 | ) 16 | 17 | let flag = XCTestExpectation() 18 | 19 | var returnAccessToken: DropboxAccessToken? 20 | 21 | manager.refreshAccessToken( 22 | defaultToken, 23 | scopes: scopes, 24 | queue: DispatchQueue.global(qos: .userInitiated) 25 | ) { result in 26 | 27 | switch result { 28 | case .success(let authToken)?: 29 | returnAccessToken = authToken 30 | case .error(_, let description)?: 31 | XCTFail("Error: failed to refresh access token (\(description ?? "no description")") 32 | case .cancel?: 33 | XCTFail("Error: failed to refresh access token (cancelled)") 34 | case .none: 35 | XCTFail("Error: failed to refresh access token (no result)") 36 | } 37 | 38 | flag.fulfill() 39 | } 40 | 41 | let result = XCTWaiter.wait(for: [flag], timeout: 10) 42 | XCTAssertEqual(result, .completed, "Error: timeout refreshing access token") 43 | guard let accessToken = returnAccessToken else { 44 | XCTFail("AccessToken creation failed") 45 | fatalError("AccessToken creation failed") 46 | } 47 | return DropboxTransportClientImpl(accessTokenProvider: manager.accessTokenProviderForToken(accessToken)) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /update_repo_check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Release checklist 4 | # 5 | # 1. Make sure test data is reset 6 | # 2. Run generator 7 | # 3. Check test project, run unit tests 8 | # 4. Check pod spec lint 9 | # 5. Increment version with script 10 | # 6. Update Carthage example project 11 | # 7. Push to CocoaPods 12 | # 13 | 14 | cat TestSwiftyDropbox/IntegrationTests/TestData.swift 15 | 16 | # python generate_base_client.py 17 | 18 | # pod spec lint 19 | -------------------------------------------------------------------------------- /update_version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Script for updating SwiftyDropbox version number 4 | 5 | echo 6 | 7 | if [ "$#" -ne 1 ]; then 8 | echo "Requires 1 parameter. Usage: \`./update_version \`" 9 | exit 1 10 | fi 11 | 12 | arg_version_regex="^[0-9]+\.[0-9]+\.[0-9]+$" 13 | version_regex="[0-9]+\.[0-9]+\.[0-9]+" 14 | 15 | podspec=./SwiftyDropbox.podspec 16 | objc_podspec=./SwiftyDropboxObjC.podspec 17 | readme=./README.md 18 | user_agent=Source/SwiftyDropbox/Shared/Handwritten/SDKConstants.swift 19 | ios_version=Source/SwiftyDropbox/Platform/SwiftyDropbox_iOS/Info.plist 20 | mac_version=Source/SwiftyDropbox/Platform/SwiftyDropbox_macOS/Info.plist 21 | ios_objc_version=Source/SwiftyDropboxObjC/Platform/SwiftyDropbox_iOS/Info.plist 22 | mac_objc_version=Source/SwiftyDropboxObjC/Platform/SwiftyDropbox_macOS/Info.plist 23 | 24 | 25 | if ! [[ $1 =~ $arg_version_regex ]]; then 26 | echo "\"$1\" version string must have format x.x.x" 27 | exit 1 28 | else 29 | echo "Updating SDK text to version \"$1\"" 30 | fi 31 | 32 | echo 33 | echo 34 | 35 | echo "Replacing podspec version number..." 36 | sed -i '' -E "s/s.version = '$version_regex'/s.version = '$1'/" $podspec 37 | echo '--------------------' 38 | cat $podspec | grep $1 39 | echo '--------------------' 40 | echo 41 | 42 | echo "Replacing ObjC podspec version number..." 43 | sed -i '' -E "s/s.version = '$version_regex'/s.version = '$1'/" $objc_podspec 44 | sed -i '' -E "s/s.dependency 'SwiftyDropbox', '~> $version_regex'/s.dependency 'SwiftyDropbox', '~> $1'/" $objc_podspec 45 | echo '--------------------' 46 | cat $objc_podspec | grep $1 47 | echo '--------------------' 48 | echo 49 | 50 | echo "Replacing README version number..." 51 | sed -i '' -E "s/~> $version_regex/~> $1/" $readme 52 | echo '--------------------' 53 | cat $readme | grep $1 54 | echo '--------------------' 55 | echo 56 | 57 | echo "Replacing User Agent version number..." 58 | sed -i '' -E "s/versionSDK = \"$version_regex\"/versionSDK = \"$1\"/" $user_agent 59 | echo '--------------------' 60 | cat $user_agent | grep $1 61 | echo '--------------------' 62 | echo 63 | 64 | echo "Replacing iOS xcodeproj version number..." 65 | sed -i '' -E "s/$version_regex/$1/" $ios_version 66 | echo '--------------------' 67 | cat $ios_version | grep $1 68 | echo '--------------------' 69 | echo 70 | 71 | echo "Replacing macOS xcodeproj version number..." 72 | sed -i '' -E "s/$version_regex/$1/" $mac_version 73 | echo '--------------------' 74 | cat $mac_version | grep $1 75 | echo '--------------------' 76 | echo 77 | 78 | echo "Replacing iOS objc xcodeproj version number..." 79 | sed -i '' -E "s/$version_regex/$1/" $ios_objc_version 80 | echo '--------------------' 81 | cat $ios_objc_version | grep $1 82 | echo '--------------------' 83 | echo 84 | 85 | echo "Replacing macOS objc xcodeproj version number..." 86 | sed -i '' -E "s/$version_regex/$1/" $mac_objc_version 87 | echo '--------------------' 88 | cat $mac_objc_version | grep $1 89 | echo '--------------------' 90 | echo 91 | 92 | echo 93 | echo "Committing changes and tagging commit." 94 | git commit -am "$1 release." 95 | git tag "$1" 96 | echo 97 | echo "Changes ready for review and push" 98 | echo 99 | --------------------------------------------------------------------------------