COVIDSafe code from version 2.6 (#51)

This commit is contained in:
COVIDSafe Support 2021-05-12 17:39:38 -07:00 committed by GitHub
parent 195798ddd5
commit 4d98b6c5e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
43 changed files with 910 additions and 144 deletions

49
.circleci/README.md Normal file
View file

@ -0,0 +1,49 @@
## Introduction
CircleCI has a workflow configured to build and upload UAT builds once a merge is done to the dev branch. In the same way, there is a workflow for production and it runs when a merge is done to the master branch.
Fastlane is used to build and distribute the app.
## Fastlane Configuration
The approach taken for the app build and distribution was to provide the `provisioning profile` and the `certificate` manually rather than retrieving it automatically from appstore connect. For this, environment variables are set with the required values for both UAT and PROD.
This aliviates the requirements for authentication and interaction with the appstore leaving upload as the only outstanding task in the lanes. With fastlane's `pilot` we upload the app to TestFlight using application specific password, this action **requires** both `apple_id` and `skip_waiting_for_build_processing`. For more information see https://docs.fastlane.tools/actions/upload_to_testflight/#use-an-application-specific-password-to-upload
Note: Build numbers need to be set correctly on merge otherwise the upload will fail. In order to automate the build number update it is recomended to use an api_key.
### Lanes
There are 2 lanes defined per app build (UAT and PROD):
- import_uat_distribution_certificate: This lane will decode and install the needed provisioning profile and signing certificate for the UAT build.
- import_distribution_certificate: This lane will decode and install the needed provisioning profile and signing certificate for the PROD build.
- beta: This lane will build and upload the UAT build to testflight
- release: This lane will build and upload the PROD build to testflight
## CircleCI Project Configuration
The following environment variables need to be set in the CircleCI web console project configuration.
- APP_STORE_UAT_PROFILE_B64: Base64 encoded provisioning profile to use with UAT builds
- DISTRIBUTION_UAT_P12_B64: Base64 encoded distribution certificate to use with UAT builds
- DISTRIBUTION_UAT_P12_PASSWORD: Password for the UAT certificate above.
- APPLE_ID_UAT: This is the apps apple id. Can be found in appstore connect under App information -> General information.
- APP_STORE_PROFILE_B64: Base64 encoded provisioning profile to use with UAT builds
- DISTRIBUTION_P12_B64: Base64 encoded distribution certificate to use with UAT builds
- DISTRIBUTION_P12_PASSWORD: Password for the UAT certificate above.
- APPLE_ID: This is the apps apple id. Can be found in appstore connect under App information -> General information.
- FASTLANE_USER: App store connect user
- FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: Application specific password generated for Fastlane. This is account specific rather than app specific, share the same for UAT and PROD. For more information on how to generate the password see https://docs.fastlane.tools/best-practices/continuous-integration/#method-3-application-specific-passwords
To get a base64 encoded string of the desired secret run
```
openssl base64 -A -in "filename.extension"
```

69
.circleci/config.yml Normal file
View file

@ -0,0 +1,69 @@
# Circle CI Build config for COVIDSafe
version: 2.1
commands:
prepare-uat:
steps:
- checkout
- run: bundle install
- run: mkdir -pv ~/Library/MobileDevice/Provisioning\ Profiles/
- run: echo ${APP_STORE_UAT_PROFILE_B64} | base64 --decode > ~/Library/MobileDevice/Provisioning\ Profiles/AppStore_UAT.mobileprovision
- run: echo ${DISTRIBUTION_UAT_P12_B64} | base64 --decode > Distribution_UAT.p12
- run: bundle exec fastlane import_uat_distribution_certificate
prepare-release:
steps:
- checkout
- run: bundle install
- run: mkdir -pv ~/Library/MobileDevice/Provisioning\ Profiles/
- run: echo ${APP_STORE_PROFILE_B64} | base64 --decode > ~/Library/MobileDevice/Provisioning\ Profiles/AppStore.mobileprovision
- run: echo ${DISTRIBUTION_P12_B64} | base64 --decode > Distribution.p12
- run: bundle exec fastlane import_distribution_certificate
jobs:
build-uat:
macos:
xcode: 12.4.0 # Specify the Xcode version to use
environment:
FL_OUTPUT_DIR: output
steps:
- prepare-uat
- checkout
- run: bundle exec pod install
- run: bundle exec fastlane beta
- store_artifacts:
path: output
build-release:
macos:
xcode: 12.4.0 # Specify the Xcode version to use
environment:
FL_OUTPUT_DIR: output
steps:
- prepare-release
- checkout
- run: bundle exec pod install
- run: bundle exec fastlane release
- store_artifacts:
path: output
workflows:
build-uat:
jobs:
- build-uat:
filters:
branches:
only: dev
build-release:
jobs:
- build-release:
filters:
branches:
only: master

View file

@ -316,6 +316,8 @@
5BA3624225E463B6002CFF41 /* WebContentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BA3624025E463B5002CFF41 /* WebContentView.xib */; }; 5BA3624225E463B6002CFF41 /* WebContentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BA3624025E463B5002CFF41 /* WebContentView.xib */; };
5BA3624625E4654F002CFF41 /* WebContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA3624525E4654E002CFF41 /* WebContentView.swift */; }; 5BA3624625E4654F002CFF41 /* WebContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA3624525E4654E002CFF41 /* WebContentView.swift */; };
5BA3624725E4654F002CFF41 /* WebContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA3624525E4654E002CFF41 /* WebContentView.swift */; }; 5BA3624725E4654F002CFF41 /* WebContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA3624525E4654E002CFF41 /* WebContentView.swift */; };
5BB9B8A0262FE0870056C47E /* KeychainSwift+Singleton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB9B89F262FE0870056C47E /* KeychainSwift+Singleton.swift */; };
5BB9B8A1262FE0870056C47E /* KeychainSwift+Singleton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB9B89F262FE0870056C47E /* KeychainSwift+Singleton.swift */; };
5BBC571D25526F99005E90AA /* staging-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BBC571C25526F99005E90AA /* staging-Info.plist */; }; 5BBC571D25526F99005E90AA /* staging-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BBC571C25526F99005E90AA /* staging-Info.plist */; };
5BBE61B125633B6D00B8C983 /* CSGenericContentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BBE61B025633B6D00B8C983 /* CSGenericContentView.xib */; }; 5BBE61B125633B6D00B8C983 /* CSGenericContentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BBE61B025633B6D00B8C983 /* CSGenericContentView.xib */; };
5BBE61B225633B6D00B8C983 /* CSGenericContentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BBE61B025633B6D00B8C983 /* CSGenericContentView.xib */; }; 5BBE61B225633B6D00B8C983 /* CSGenericContentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BBE61B025633B6D00B8C983 /* CSGenericContentView.xib */; };
@ -564,6 +566,7 @@
5BA3623325DE133D002CFF41 /* CSGenericErrorController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSGenericErrorController.swift; sourceTree = "<group>"; }; 5BA3623325DE133D002CFF41 /* CSGenericErrorController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSGenericErrorController.swift; sourceTree = "<group>"; };
5BA3624025E463B5002CFF41 /* WebContentView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = WebContentView.xib; sourceTree = "<group>"; }; 5BA3624025E463B5002CFF41 /* WebContentView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = WebContentView.xib; sourceTree = "<group>"; };
5BA3624525E4654E002CFF41 /* WebContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebContentView.swift; sourceTree = "<group>"; }; 5BA3624525E4654E002CFF41 /* WebContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebContentView.swift; sourceTree = "<group>"; };
5BB9B89F262FE0870056C47E /* KeychainSwift+Singleton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KeychainSwift+Singleton.swift"; sourceTree = "<group>"; };
5BBC571C25526F99005E90AA /* staging-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "staging-Info.plist"; sourceTree = "<group>"; }; 5BBC571C25526F99005E90AA /* staging-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "staging-Info.plist"; sourceTree = "<group>"; };
5BBE61B025633B6D00B8C983 /* CSGenericContentView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CSGenericContentView.xib; sourceTree = "<group>"; }; 5BBE61B025633B6D00B8C983 /* CSGenericContentView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CSGenericContentView.xib; sourceTree = "<group>"; };
5BBE61B625633E8D00B8C983 /* CSGenericViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CSGenericViewController.swift; sourceTree = "<group>"; }; 5BBE61B625633E8D00B8C983 /* CSGenericViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CSGenericViewController.swift; sourceTree = "<group>"; };
@ -800,6 +803,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
B605A7B02427429D008BA819 /* PlistHelper.swift */, B605A7B02427429D008BA819 /* PlistHelper.swift */,
5BB9B89F262FE0870056C47E /* KeychainSwift+Singleton.swift */,
5B900FC02485C4EE00CAA419 /* String+Localization.swift */, 5B900FC02485C4EE00CAA419 /* String+Localization.swift */,
5B69C06525D382AF00DF536D /* String+HtmlAttributed.swift */, 5B69C06525D382AF00DF536D /* String+HtmlAttributed.swift */,
0B1810112431EE610005D11F /* PhoneNumberParser.swift */, 0B1810112431EE610005D11F /* PhoneNumberParser.swift */,
@ -1240,7 +1244,7 @@
5B92D66A243018040049877B /* Sources */, 5B92D66A243018040049877B /* Sources */,
5B92D6B7243018040049877B /* Frameworks */, 5B92D6B7243018040049877B /* Frameworks */,
5B92D6B9243018040049877B /* Resources */, 5B92D6B9243018040049877B /* Resources */,
67401E6C50CE0E543E47346A /* [CP] Embed Pods Frameworks */, 34C60B5DD40F4458AB9E6FD0 /* [CP] Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
@ -1259,7 +1263,7 @@
5DD41D3323DCB03B00FD4AB0 /* Sources */, 5DD41D3323DCB03B00FD4AB0 /* Sources */,
5DD41D3423DCB03B00FD4AB0 /* Frameworks */, 5DD41D3423DCB03B00FD4AB0 /* Frameworks */,
5DD41D3523DCB03B00FD4AB0 /* Resources */, 5DD41D3523DCB03B00FD4AB0 /* Resources */,
2D8EF319C5D6408D45C0B585 /* [CP] Embed Pods Frameworks */, DB7F6C492EEEEFCD9ACA09F9 /* [CP] Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
@ -1432,24 +1436,7 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
2D8EF319C5D6408D45C0B585 /* [CP] Embed Pods Frameworks */ = { 34C60B5DD40F4458AB9E6FD0 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-CovidSafe/Pods-CovidSafe-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-CovidSafe/Pods-CovidSafe-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CovidSafe/Pods-CovidSafe-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
67401E6C50CE0E543E47346A /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
@ -1488,6 +1475,23 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
DB7F6C492EEEEFCD9ACA09F9 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-CovidSafe/Pods-CovidSafe-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-CovidSafe/Pods-CovidSafe-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CovidSafe/Pods-CovidSafe-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
DC4D19AF69C7C819FCC35F09 /* [CP] Check Pods Manifest.lock */ = { DC4D19AF69C7C819FCC35F09 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@ -1576,6 +1580,7 @@
5B92D68A243018040049877B /* Outcome.swift in Sources */, 5B92D68A243018040049877B /* Outcome.swift in Sources */,
5B92D68B243018040049877B /* Encounter+EncounterRecord.swift in Sources */, 5B92D68B243018040049877B /* Encounter+EncounterRecord.swift in Sources */,
0B42D0DE2432B39E00E4F44C /* Question2ErrorViewController.swift in Sources */, 0B42D0DE2432B39E00E4F44C /* Question2ErrorViewController.swift in Sources */,
5BB9B8A1262FE0870056C47E /* KeychainSwift+Singleton.swift in Sources */,
594E77C024736B77009B8B34 /* EncounterDB.swift in Sources */, 594E77C024736B77009B8B34 /* EncounterDB.swift in Sources */,
5B728B4724B5667000654ABC /* BLELogViewController.swift in Sources */, 5B728B4724B5667000654ABC /* BLELogViewController.swift in Sources */,
590888B42431B9F5008C9B9F /* UploadDataNavigationController.swift in Sources */, 590888B42431B9F5008C9B9F /* UploadDataNavigationController.swift in Sources */,
@ -1796,6 +1801,7 @@
A767D32F242DF1B100DC9E2A /* Errors.swift in Sources */, A767D32F242DF1B100DC9E2A /* Errors.swift in Sources */,
5905462A2543E0F6009B82AD /* PayloadDataSupplier.swift in Sources */, 5905462A2543E0F6009B82AD /* PayloadDataSupplier.swift in Sources */,
0B22A56B242F286900D1FE60 /* UINavigationBar+Style.swift in Sources */, 0B22A56B242F286900D1FE60 /* UINavigationBar+Style.swift in Sources */,
5BB9B8A0262FE0870056C47E /* KeychainSwift+Singleton.swift in Sources */,
0B1810122431EE610005D11F /* PhoneNumberParser.swift in Sources */, 0B1810122431EE610005D11F /* PhoneNumberParser.swift in Sources */,
1B86119B24303FA200EA4B6B /* Question3ErrorViewController.swift in Sources */, 1B86119B24303FA200EA4B6B /* Question3ErrorViewController.swift in Sources */,
5BEDEF5425CBC4A900AEEC20 /* RestrictionsViewController.swift in Sources */, 5BEDEF5425CBC4A900AEEC20 /* RestrictionsViewController.swift in Sources */,
@ -1971,9 +1977,9 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements"; CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 121; CURRENT_PROJECT_VERSION = 127;
DEVELOPMENT_TEAM = 45792XH5L8; DEVELOPMENT_TEAM = 45792XH5L8;
INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/Info.plist"; INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.0; IPHONEOS_DEPLOYMENT_TARGET = 10.0;
@ -1981,11 +1987,11 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 2.5; MARKETING_VERSION = 2.6;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe; PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe;
PRODUCT_NAME = COVIDSafe; PRODUCT_NAME = COVIDSafe;
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = COVIDSafe;
SERVICE_UUID = "17E033D3-490E-4BC9-9FE8-2F567643F4D3"; SERVICE_UUID = "17E033D3-490E-4BC9-9FE8-2F567643F4D3";
SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@ -2055,9 +2061,9 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements"; CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 121; CURRENT_PROJECT_VERSION = 127;
DEVELOPMENT_TEAM = 45792XH5L8; DEVELOPMENT_TEAM = 45792XH5L8;
INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/Info.plist"; INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.0; IPHONEOS_DEPLOYMENT_TARGET = 10.0;
@ -2065,10 +2071,10 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 2.5; MARKETING_VERSION = 2.6;
PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe; PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe;
PRODUCT_NAME = COVIDSafe; PRODUCT_NAME = COVIDSafe;
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = COVIDSafe;
SERVICE_UUID = "B82AB3FC-1595-4F6A-80F0-FE094CC218F9"; SERVICE_UUID = "B82AB3FC-1595-4F6A-80F0-FE094CC218F9";
SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h";
SWIFT_REFLECTION_METADATA_LEVEL = none; SWIFT_REFLECTION_METADATA_LEVEL = none;
@ -2083,9 +2089,9 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements"; CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 120; CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = 45792XH5L8; DEVELOPMENT_TEAM = 45792XH5L8;
INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/staging-Info.plist"; INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/staging-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.0; IPHONEOS_DEPLOYMENT_TARGET = 10.0;
@ -2093,13 +2099,13 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 2.5; MARKETING_VERSION = 2.6;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -D DEBUG"; OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -D DEBUG";
PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe.uat; PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe.uat;
PRODUCT_MODULE_NAME = COVIDSafe; PRODUCT_MODULE_NAME = COVIDSafe;
PRODUCT_NAME = "COVIDSafe-staging"; PRODUCT_NAME = "COVIDSafe-staging";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "CovidSafe UAT";
SERVICE_UUID = "CC0AC8B7-03B5-4252-8D84-44D199E16065"; SERVICE_UUID = "CC0AC8B7-03B5-4252-8D84-44D199E16065";
SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@ -2113,9 +2119,9 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements"; CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 120; CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = 45792XH5L8; DEVELOPMENT_TEAM = 45792XH5L8;
INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/staging-Info.plist"; INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/staging-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.0; IPHONEOS_DEPLOYMENT_TARGET = 10.0;
@ -2123,13 +2129,13 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 2.5; MARKETING_VERSION = 2.6;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -D DEBUG"; OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -D DEBUG";
PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe.uat; PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe.uat;
PRODUCT_MODULE_NAME = COVIDSafe; PRODUCT_MODULE_NAME = COVIDSafe;
PRODUCT_NAME = "COVIDSafe-staging"; PRODUCT_NAME = "COVIDSafe-staging";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "CovidSafe UAT";
SERVICE_UUID = "CC0AC8B7-03B5-4252-8D84-44D199E16065"; SERVICE_UUID = "CC0AC8B7-03B5-4252-8D84-44D199E16065";
SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@ -2143,9 +2149,9 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements"; CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 120; CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = 45792XH5L8; DEVELOPMENT_TEAM = 45792XH5L8;
INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/staging-Info.plist"; INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/staging-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.0; IPHONEOS_DEPLOYMENT_TARGET = 10.0;
@ -2153,12 +2159,12 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 2.5; MARKETING_VERSION = 2.6;
OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -D DEBUG"; OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -D DEBUG";
PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe.uat; PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe.uat;
PRODUCT_MODULE_NAME = COVIDSafe; PRODUCT_MODULE_NAME = COVIDSafe;
PRODUCT_NAME = "COVIDSafe-staging"; PRODUCT_NAME = "COVIDSafe-staging";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "CovidSafe UAT";
SERVICE_UUID = "CC0AC8B7-03B5-4252-8D84-44D199E16065"; SERVICE_UUID = "CC0AC8B7-03B5-4252-8D84-44D199E16065";
SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h";
SWIFT_REFLECTION_METADATA_LEVEL = none; SWIFT_REFLECTION_METADATA_LEVEL = none;
@ -2173,9 +2179,9 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements"; CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 120; CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = 45792XH5L8; DEVELOPMENT_TEAM = 45792XH5L8;
INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/staging-Info.plist"; INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/staging-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.0; IPHONEOS_DEPLOYMENT_TARGET = 10.0;
@ -2183,12 +2189,12 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 2.5; MARKETING_VERSION = 2.6;
OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -D DEBUG"; OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -D DEBUG";
PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe.uat; PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe.uat;
PRODUCT_MODULE_NAME = COVIDSafe; PRODUCT_MODULE_NAME = COVIDSafe;
PRODUCT_NAME = "COVIDSafe-staging"; PRODUCT_NAME = "COVIDSafe-staging";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "CovidSafe UAT";
SERVICE_UUID = "CC0AC8B7-03B5-4252-8D84-44D199E16065"; SERVICE_UUID = "CC0AC8B7-03B5-4252-8D84-44D199E16065";
SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h";
SWIFT_REFLECTION_METADATA_LEVEL = none; SWIFT_REFLECTION_METADATA_LEVEL = none;
@ -2321,9 +2327,9 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements"; CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 121; CURRENT_PROJECT_VERSION = 127;
DEVELOPMENT_TEAM = 45792XH5L8; DEVELOPMENT_TEAM = 45792XH5L8;
INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/Info.plist"; INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.0; IPHONEOS_DEPLOYMENT_TARGET = 10.0;
@ -2331,11 +2337,11 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 2.5; MARKETING_VERSION = 2.6;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe; PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe;
PRODUCT_NAME = COVIDSafe; PRODUCT_NAME = COVIDSafe;
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = COVIDSafe;
SERVICE_UUID = "CC0AC8B7-03B5-4252-8D84-44D199E16065"; SERVICE_UUID = "CC0AC8B7-03B5-4252-8D84-44D199E16065";
SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@ -2349,9 +2355,9 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements"; CODE_SIGN_ENTITLEMENTS = "CovidSafe/Project Bluetrace.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 121; CURRENT_PROJECT_VERSION = 127;
DEVELOPMENT_TEAM = 45792XH5L8; DEVELOPMENT_TEAM = 45792XH5L8;
INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/Info.plist"; INFOPLIST_FILE = "$(SRCROOT)/CovidSafe/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.0; IPHONEOS_DEPLOYMENT_TARGET = 10.0;
@ -2359,10 +2365,10 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 2.5; MARKETING_VERSION = 2.6;
PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe; PRODUCT_BUNDLE_IDENTIFIER = au.gov.health.covidsafe;
PRODUCT_NAME = COVIDSafe; PRODUCT_NAME = COVIDSafe;
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = COVIDSafe;
SERVICE_UUID = "B82AB3FC-1595-4F6A-80F0-FE094CC218F9"; SERVICE_UUID = "B82AB3FC-1595-4F6A-80F0-FE094CC218F9";
SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "CovidSafe/covid-Bridging-Header.h";
SWIFT_REFLECTION_METADATA_LEVEL = none; SWIFT_REFLECTION_METADATA_LEVEL = none;

View file

@ -31,7 +31,7 @@
</Testables> </Testables>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Release" buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"

View file

@ -16,10 +16,15 @@ class AuthenticationAPI: CovidSafeAuthenticatedAPI {
return return
} }
guard let authHeaders = try? authenticatedHeaders() else {
completion(nil, .RequestError)
return
}
CovidNetworking.shared.session.request("\(apiHost)/issueInitialRefreshToken", CovidNetworking.shared.session.request("\(apiHost)/issueInitialRefreshToken",
method: .post, method: .post,
encoding: JSONEncoding.default, encoding: JSONEncoding.default,
headers: authenticatedHeaders headers: authHeaders
).validate().responseDecodable(of: ChallengeResponse.self) { (response) in ).validate().responseDecodable(of: ChallengeResponse.self) { (response) in
switch response.result { switch response.result {
case .success: case .success:
@ -55,7 +60,7 @@ class AuthenticationAPI: CovidSafeAuthenticatedAPI {
return return
} }
let keychain = KeychainSwift() let keychain = KeychainSwift.shared
guard let token = keychain.get("JWT_TOKEN"), guard let token = keychain.get("JWT_TOKEN"),
let refreshToken = keychain.get("REFRESH_TOKEN"), let refreshToken = keychain.get("REFRESH_TOKEN"),
@ -105,7 +110,7 @@ class AuthenticationAPI: CovidSafeAuthenticatedAPI {
} }
static func issueTokensAPI(completion: @escaping (ChallengeResponse?, CovidSafeAPIError?) -> Void) { static func issueTokensAPI(completion: @escaping (ChallengeResponse?, CovidSafeAPIError?) -> Void) {
let keychain = KeychainSwift() let keychain = KeychainSwift.shared
// block api call only if refresh token exists, if it doesn't it means the app should get it for the first time // block api call only if refresh token exists, if it doesn't it means the app should get it for the first time
if UserDefaults.standard.bool(forKey: "ReauthenticationNeededKey") && keychain.get("REFRESH_TOKEN") != nil { if UserDefaults.standard.bool(forKey: "ReauthenticationNeededKey") && keychain.get("REFRESH_TOKEN") != nil {
@ -132,13 +137,20 @@ class AuthenticationAPI: CovidSafeAuthenticatedAPI {
completion(response, nil) completion(response, nil)
} }
} else { } else {
let refreshTokenBeforeRefresh = keychain.get("REFRESH_TOKEN")
AuthenticationAPI.issueJWTTokenAPI { (response, error) in AuthenticationAPI.issueJWTTokenAPI { (response, error) in
guard let jwt = response?.token, guard let jwt = response?.token,
let refresh = response?.refreshToken, let refresh = response?.refreshToken,
error == nil else { error == nil else {
// set corrupted // if the token in the system before the call is different than the one in keychain, this is a concurrency issue, the token was refresh already and that is why this failed. We should not start re-authentication
guard refreshTokenBeforeRefresh == keychain.get("REFRESH_TOKEN") else {
completion(response, .TokenAlreadyRefreshedError)
return
}
// set corrupted only when it has not been changed
UserDefaults.standard.set(true, forKey: "ReauthenticationNeededKey") UserDefaults.standard.set(true, forKey: "ReauthenticationNeededKey")
completion(response, .TokenExpiredError) completion(response, .TokenExpiredError)
return return

View file

@ -20,11 +20,17 @@ class ChangePostcodeAPI: CovidSafeAuthenticatedAPI {
let params = [ let params = [
"postcode": newPostcode, "postcode": newPostcode,
] ]
guard let authHeaders = try? authenticatedHeaders() else {
completion(.RequestError)
return
}
CovidNetworking.shared.session.request("\(apiHost)/device", CovidNetworking.shared.session.request("\(apiHost)/device",
method: .post, method: .post,
parameters: params, parameters: params,
encoding: JSONEncoding.default, encoding: JSONEncoding.default,
headers: authenticatedHeaders, headers: authHeaders,
interceptor: CovidRequestRetrier(retries:3)).validate().responseDecodable(of: DeviceResponse.self) { (response) in interceptor: CovidRequestRetrier(retries:3)).validate().responseDecodable(of: DeviceResponse.self) { (response) in
switch response.result { switch response.result {
case .success: case .success:

View file

@ -56,6 +56,8 @@ enum CovidSafeAPIError: Error {
case ResponseError case ResponseError
case ServerError case ServerError
case TokenExpiredError case TokenExpiredError
case TokenAlreadyRefreshedError
case MaxRegistrationError
case UnknownError case UnknownError
} }
@ -63,18 +65,16 @@ class CovidSafeAuthenticatedAPI {
static var isBusy = false static var isBusy = false
static var authenticatedHeaders: HTTPHeaders { static func authenticatedHeaders() throws -> HTTPHeaders {
get { let keychain = KeychainSwift.shared
let keychain = KeychainSwift()
guard let token = keychain.get("JWT_TOKEN") else { guard let token = keychain.get("JWT_TOKEN") else {
return [] throw CovidSafeAPIError.RequestError
}
let headers: HTTPHeaders = [
"Authorization": "Bearer \(token)"
]
return headers
} }
let headers: HTTPHeaders = [
"Authorization": "Bearer \(token)"
]
return headers
} }
static func processUnauthorizedError(_ data: Data) -> CovidSafeAPIError { static func processUnauthorizedError(_ data: Data) -> CovidSafeAPIError {

View file

@ -20,8 +20,12 @@ final class CovidRequestRetrier: Alamofire.RequestInterceptor {
func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) { func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
var urlRequest = urlRequest var urlRequest = urlRequest
let keychain = KeychainSwift() let keychain = KeychainSwift.shared
let refreshExists = keychain.get("REFRESH_TOKEN") != nil let refreshExists = keychain.get("REFRESH_TOKEN") != nil
// turn off geolock error
UserDefaults.standard.setValue(false, forKey: showGeolockErrorKey)
// prevent authenticated api calls if the re-registration flow has been started // prevent authenticated api calls if the re-registration flow has been started
if UserDefaults.standard.bool(forKey: "ReauthenticationNeededKey") && if UserDefaults.standard.bool(forKey: "ReauthenticationNeededKey") &&
refreshExists { refreshExists {
@ -81,13 +85,19 @@ final class CovidRequestRetrier: Alamofire.RequestInterceptor {
return completion(.retryWithDelay(1.0)) return completion(.retryWithDelay(1.0))
} }
if let serverHeader = response.headers.first(where: { $0.name == "Server" }),
response.statusCode == 403 && serverHeader.value == "CloudFront" {
UserDefaults.standard.setValue(true, forKey: showGeolockErrorKey)
return completion(.doNotRetryWithError(error))
}
if !triedRefresh && if !triedRefresh &&
(response.statusCode == 403 || response.statusCode == 401) { (response.statusCode == 401 || response.statusCode == 403) {
triedRefresh = true triedRefresh = true
retriesExecuted += 1 retriesExecuted += 1
AuthenticationAPI.issueTokensAPI { (response, authError) in AuthenticationAPI.issueTokensAPI { (response, authError) in
// this will update the tokens automatically // this will update the tokens automatically
guard let respError = authError, respError == .TokenExpiredError else { if let respError = authError, respError == .TokenExpiredError {
completion(.doNotRetryWithError(error)) completion(.doNotRetryWithError(error))
return return
} }

View file

@ -26,7 +26,7 @@ class GetTempIdAPI: CovidSafeAuthenticatedAPI {
"version" : apiVersion "version" : apiVersion
] ]
guard authenticatedHeaders.count > 0 else { guard let authHeaders = try? authenticatedHeaders(), authHeaders.count > 0 else {
completion(nil, nil, nil, .TokenExpiredError) completion(nil, nil, nil, .TokenExpiredError)
return return
} }
@ -34,7 +34,7 @@ class GetTempIdAPI: CovidSafeAuthenticatedAPI {
CovidNetworking.shared.session.request("\(apiHost)/getTempId", CovidNetworking.shared.session.request("\(apiHost)/getTempId",
method: .get, method: .get,
parameters: params, parameters: params,
headers: authenticatedHeaders, headers: authHeaders,
interceptor: CovidRequestRetrier(retries: 3)).validate().responseDecodable(of: TempIdResponse.self) { (response) in interceptor: CovidRequestRetrier(retries: 3)).validate().responseDecodable(of: TempIdResponse.self) { (response) in
switch response.result { switch response.result {
case .success: case .success:

View file

@ -65,7 +65,7 @@ class MessageAPI: CovidSafeAuthenticatedAPI {
var shouldGetMessages = true var shouldGetMessages = true
let calendar = NSCalendar.current let calendar = NSCalendar.current
let currentDate = calendar.startOfDay(for: Date()) let currentDate = Date()
// if the current version is newer than the last version checked, allow messages call // if the current version is newer than the last version checked, allow messages call
if let currVersionStr = Bundle.main.version, let currVersion = Int(currVersionStr), currVersion > versionChecked { if let currVersionStr = Bundle.main.version, let currVersion = Int(currVersionStr), currVersion > versionChecked {
@ -77,7 +77,7 @@ class MessageAPI: CovidSafeAuthenticatedAPI {
let components = calendar.dateComponents([.hour], from: lastCheckedDate, to: currentDate) let components = calendar.dateComponents([.hour], from: lastCheckedDate, to: currentDate)
if let numHours = components.hour { if let numHours = components.hour {
shouldGetMessages = numHours > 4 shouldGetMessages = numHours >= 4
} }
} }
@ -109,10 +109,15 @@ class MessageAPI: CovidSafeAuthenticatedAPI {
isBusy = true isBusy = true
guard let authHeaders = try? authenticatedHeaders() else {
completion(nil, .RequestError)
return
}
CovidNetworking.shared.session.request("\(apiHost)/messages", CovidNetworking.shared.session.request("\(apiHost)/messages",
method: .get, method: .get,
parameters: params, parameters: params,
headers: authenticatedHeaders, headers: authHeaders,
interceptor: CovidRequestRetrier(retries: 3) interceptor: CovidRequestRetrier(retries: 3)
).validate().responseDecodable(of: MessageResponse.self) { (response) in ).validate().responseDecodable(of: MessageResponse.self) { (response) in
switch response.result { switch response.result {
@ -120,7 +125,7 @@ class MessageAPI: CovidSafeAuthenticatedAPI {
guard let messageResponse = response.value else { return } guard let messageResponse = response.value else { return }
// save successful timestamp // save successful timestamp
let minutesToDefer = Int.random(in: 0..<10) let minutesToDefer = Int.random(in: 0..<30)
let calendar = NSCalendar.current let calendar = NSCalendar.current
let currentDate = Date() let currentDate = Date()
if let deferredDate = calendar.date(byAdding: .minute, value: minutesToDefer, to: currentDate) { if let deferredDate = calendar.date(byAdding: .minute, value: minutesToDefer, to: currentDate) {

View file

@ -11,7 +11,7 @@ import Alamofire
class PhoneValidationAPI { class PhoneValidationAPI {
static func verifyPhoneNumber(regInfo: RegistrationRequest, static func verifyPhoneNumber(regInfo: RegistrationRequest,
completion: @escaping (String?, Swift.Error?) -> Void) { completion: @escaping (String?, CovidSafeAPIError?) -> Void) {
guard let apiHost = PlistHelper.getvalueFromInfoPlist(withKey: "API_Host", plistName: "CovidSafe-config") else { guard let apiHost = PlistHelper.getvalueFromInfoPlist(withKey: "API_Host", plistName: "CovidSafe-config") else {
return return
@ -33,8 +33,22 @@ class PhoneValidationAPI {
case .success: case .success:
guard let authResponse = response.value else { return } guard let authResponse = response.value else { return }
completion(authResponse.session, nil) completion(authResponse.session, nil)
case let .failure(error): case .failure(_):
completion(nil, error) var apiError = CovidSafeAPIError.RequestError
if let respData = response.data {
do {
let errorResponse = try JSONDecoder().decode(CovidSafeErrorResponse.self, from: respData)
if errorResponse.message == "MaxRegistrationsReached" {
apiError = .MaxRegistrationError
}
} catch {
// unable to parse response
apiError = .ResponseError
}
}
completion(nil, apiError)
} }
} }
} }

View file

@ -24,10 +24,15 @@ class RestrictionsAPI: CovidSafeAuthenticatedAPI {
let params = ["state": "\(forState.rawValue.lowercased())"] let params = ["state": "\(forState.rawValue.lowercased())"]
guard let authHeaders = try? authenticatedHeaders() else {
completion(nil, .RequestError)
return
}
CovidNetworking.shared.session.request("\(apiHost)/restrictions", CovidNetworking.shared.session.request("\(apiHost)/restrictions",
method: .get, method: .get,
parameters: params, parameters: params,
headers: authenticatedHeaders, headers: authHeaders,
interceptor: CovidRequestRetrier(retries: 3) interceptor: CovidRequestRetrier(retries: 3)
).validate().responseDecodable(of: StateRestriction.self) { (response) in ).validate().responseDecodable(of: StateRestriction.self) { (response) in
switch response.result { switch response.result {

View file

@ -20,10 +20,15 @@ class StatisticsAPI: CovidSafeAuthenticatedAPI {
let parameters = ["state" : "\(forState.rawValue)"] let parameters = ["state" : "\(forState.rawValue)"]
guard let authHeaders = try? authenticatedHeaders() else {
completion(nil, .RequestError)
return
}
CovidNetworking.shared.session.request("\(apiHost)/v2/statistics", CovidNetworking.shared.session.request("\(apiHost)/v2/statistics",
method: .get, method: .get,
parameters: parameters, parameters: parameters,
headers: authenticatedHeaders, headers: authHeaders,
interceptor: CovidRequestRetrier(retries: 3) interceptor: CovidRequestRetrier(retries: 3)
).validate().responseDecodable(of: StatisticsResponse.self) { (response) in ).validate().responseDecodable(of: StatisticsResponse.self) { (response) in
switch response.result { switch response.result {

View file

@ -21,7 +21,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
setupCoredataDir() setupCoredataDir()
let firstRun = UserDefaults.standard.bool(forKey: "HasBeenLaunched") let firstRun = UserDefaults.standard.bool(forKey: "HasBeenLaunched")
if( !firstRun ) { if( !firstRun ) {
let keychain = KeychainSwift() let keychain = KeychainSwift.shared
keychain.clear() keychain.clear()
UserDefaults.standard.set(true, forKey: "HasBeenLaunched") UserDefaults.standard.set(true, forKey: "HasBeenLaunched")
} }

View file

@ -21,6 +21,7 @@
<outlet property="covidStatisticsContainer" destination="eZl-C5-gSv" id="37c-CV-VgS"/> <outlet property="covidStatisticsContainer" destination="eZl-C5-gSv" id="37c-CV-VgS"/>
<outlet property="covidStatisticsSection" destination="Aop-Ae-hRv" id="Qpd-Hv-uA8"/> <outlet property="covidStatisticsSection" destination="Aop-Ae-hRv" id="Qpd-Hv-uA8"/>
<outlet property="inactiveAppSectionView" destination="784-Jf-kOX" id="J3m-Pu-697"/> <outlet property="inactiveAppSectionView" destination="784-Jf-kOX" id="J3m-Pu-697"/>
<outlet property="inactiveGenericError" destination="5Pd-c8-CYx" id="Fez-q4-Oc5"/>
<outlet property="inactiveSettingsContent" destination="AUW-C2-ven" id="NNP-o9-zkK"/> <outlet property="inactiveSettingsContent" destination="AUW-C2-ven" id="NNP-o9-zkK"/>
<outlet property="inactiveTokenExpiredView" destination="nxM-ji-ttb" id="vVC-KW-yek"/> <outlet property="inactiveTokenExpiredView" destination="nxM-ji-ttb" id="vVC-KW-yek"/>
<outlet property="locationPermissionsView" destination="u4f-uR-ri3" id="70q-Jr-1cc"/> <outlet property="locationPermissionsView" destination="u4f-uR-ri3" id="70q-Jr-1cc"/>
@ -127,19 +128,19 @@
</constraints> </constraints>
</view> </view>
<stackView opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="h36-8c-K2n"> <stackView opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="h36-8c-K2n">
<rect key="frame" x="0.0" y="120" width="414" height="1940.5"/> <rect key="frame" x="0.0" y="120" width="414" height="2105"/>
<subviews> <subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bRs-XW-qzv" userLabel="StatusView"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bRs-XW-qzv" userLabel="StatusView">
<rect key="frame" x="0.0" y="0.0" width="414" height="1136"/> <rect key="frame" x="0.0" y="0.0" width="414" height="1300.5"/>
<subviews> <subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="rcS-nL-IAO"> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="rcS-nL-IAO">
<rect key="frame" x="0.0" y="0.0" width="414" height="1124"/> <rect key="frame" x="0.0" y="0.0" width="414" height="1288.5"/>
<subviews> <subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="784-Jf-kOX" userLabel="InactiveView"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="784-Jf-kOX" userLabel="InactiveView">
<rect key="frame" x="0.0" y="0.0" width="414" height="696.5"/> <rect key="frame" x="0.0" y="0.0" width="414" height="861"/>
<subviews> <subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="1" translatesAutoresizingMaskIntoConstraints="NO" id="xti-6W-zko" userLabel="Inactive Stack View"> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="1" translatesAutoresizingMaskIntoConstraints="NO" id="xti-6W-zko" userLabel="Inactive Stack View">
<rect key="frame" x="0.0" y="0.0" width="414" height="696.5"/> <rect key="frame" x="0.0" y="0.0" width="414" height="861"/>
<subviews> <subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4fe-SU-8Q6" userLabel="InActiveHeader"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4fe-SU-8Q6" userLabel="InActiveHeader">
<rect key="frame" x="0.0" y="0.0" width="414" height="81"/> <rect key="frame" x="0.0" y="0.0" width="414" height="81"/>
@ -246,7 +247,7 @@
</subviews> </subviews>
<accessibility key="accessibilityConfiguration" label="Bluetooth permissions off"> <accessibility key="accessibilityConfiguration" label="Bluetooth permissions off">
<accessibilityTraits key="traits" button="YES"/> <accessibilityTraits key="traits" button="YES"/>
<bool key="isElement" value="YES"/> <bool key="isElement" value="NO"/>
</accessibility> </accessibility>
<constraints> <constraints>
<constraint firstItem="reL-DQ-aFx" firstAttribute="leading" secondItem="nxM-ji-ttb" secondAttribute="leading" id="DNN-Va-LUA"/> <constraint firstItem="reL-DQ-aFx" firstAttribute="leading" secondItem="nxM-ji-ttb" secondAttribute="leading" id="DNN-Va-LUA"/>
@ -255,8 +256,69 @@
<constraint firstAttribute="bottom" secondItem="reL-DQ-aFx" secondAttribute="bottom" id="qeE-Hu-OAb"/> <constraint firstAttribute="bottom" secondItem="reL-DQ-aFx" secondAttribute="bottom" id="qeE-Hu-OAb"/>
</constraints> </constraints>
</view> </view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5Pd-c8-CYx" userLabel="Generic Error View">
<rect key="frame" x="0.0" y="369" width="414" height="163.5"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8Nu-a1-6fd" userLabel="Generic Error Bar">
<rect key="frame" x="0.0" y="0.0" width="414" height="163.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Error connectiong to server" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yw4-mY-Pvb">
<rect key="frame" x="16" y="16" width="238.5" height="0.0"/>
<constraints>
<constraint firstAttribute="height" id="K73-MG-bAA"/>
</constraints>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle3"/>
<color key="textColor" red="0.63921568630000003" green="0.098039215690000001" blue="0.098039215690000001" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Iw2-bN-Bjb">
<rect key="frame" x="16" y="16" width="350" height="131.5"/>
<accessibility key="accessibilityConfiguration">
<bool key="isElement" value="NO"/>
</accessibility>
<string key="text">It looks like you may be accessing the internet from outside Australia. This sometimes happens when roaming on an international simcard. Please connect to an Australian network to continue.</string>
<fontDescription key="fontDescription" style="UICTFontTextStyleCallout"/>
<color key="textColor" red="0.63921568630000003" green="0.098039215690000001" blue="0.098039215690000001" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="localizationKey" value="geoblock_error_message"/>
</userDefinedRuntimeAttributes>
</label>
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="chevron-right-red" highlightedImage="redcross" translatesAutoresizingMaskIntoConstraints="NO" id="JZ8-95-6mR">
<rect key="frame" x="374" y="16" width="24" height="24"/>
<constraints>
<constraint firstAttribute="width" constant="24" id="5Dg-TP-jeV"/>
<constraint firstAttribute="height" constant="24" id="QDY-8b-rGB"/>
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="yw4-mY-Pvb" firstAttribute="top" secondItem="8Nu-a1-6fd" secondAttribute="top" constant="16" id="8lj-Mp-QPd"/>
<constraint firstItem="Iw2-bN-Bjb" firstAttribute="top" secondItem="yw4-mY-Pvb" secondAttribute="bottom" id="BG1-vf-8aa"/>
<constraint firstItem="yw4-mY-Pvb" firstAttribute="leading" secondItem="8Nu-a1-6fd" secondAttribute="leading" constant="16" id="FB0-Gh-26E"/>
<constraint firstItem="Iw2-bN-Bjb" firstAttribute="leading" secondItem="8Nu-a1-6fd" secondAttribute="leading" constant="16" id="MsQ-XB-0Cp"/>
<constraint firstItem="JZ8-95-6mR" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="yw4-mY-Pvb" secondAttribute="trailing" constant="8" id="N9H-1e-dzZ"/>
<constraint firstAttribute="bottom" secondItem="Iw2-bN-Bjb" secondAttribute="bottom" constant="16" id="SmG-4M-0Ir"/>
<constraint firstAttribute="trailing" secondItem="Iw2-bN-Bjb" secondAttribute="trailing" constant="48" id="YQ6-nh-9k7"/>
<constraint firstAttribute="trailing" secondItem="JZ8-95-6mR" secondAttribute="trailing" constant="16" id="jSl-T3-bbB"/>
<constraint firstItem="JZ8-95-6mR" firstAttribute="top" secondItem="8Nu-a1-6fd" secondAttribute="top" constant="16" id="toG-5o-Kri"/>
</constraints>
</view>
</subviews>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" button="YES"/>
<bool key="isElement" value="NO"/>
</accessibility>
<constraints>
<constraint firstItem="8Nu-a1-6fd" firstAttribute="leading" secondItem="5Pd-c8-CYx" secondAttribute="leading" id="GvM-yl-CrV"/>
<constraint firstAttribute="bottom" secondItem="8Nu-a1-6fd" secondAttribute="bottom" id="gZR-KX-tky"/>
<constraint firstItem="8Nu-a1-6fd" firstAttribute="top" secondItem="5Pd-c8-CYx" secondAttribute="top" id="gl7-zv-NsS"/>
<constraint firstAttribute="trailing" secondItem="8Nu-a1-6fd" secondAttribute="trailing" id="tnp-QS-aoM"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="a5D-xk-n0n" userLabel="Bluetooth Permission Off Section"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="a5D-xk-n0n" userLabel="Bluetooth Permission Off Section">
<rect key="frame" x="0.0" y="369" width="414" height="80.5"/> <rect key="frame" x="0.0" y="533.5" width="414" height="80.5"/>
<subviews> <subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ZoL-pC-0bR" userLabel="Bluetooth Permission Off Bar"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ZoL-pC-0bR" userLabel="Bluetooth Permission Off Bar">
<rect key="frame" x="0.0" y="0.0" width="414" height="80.5"/> <rect key="frame" x="0.0" y="0.0" width="414" height="80.5"/>
@ -327,7 +389,7 @@
</connections> </connections>
</view> </view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ers-f9-BFH" userLabel="Bluetooth Status Off Section"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ers-f9-BFH" userLabel="Bluetooth Status Off Section">
<rect key="frame" x="0.0" y="450.5" width="414" height="101.5"/> <rect key="frame" x="0.0" y="615" width="414" height="101.5"/>
<subviews> <subviews>
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="p5d-dk-foR" userLabel="Bluetooth Status Bar Off"> <view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="p5d-dk-foR" userLabel="Bluetooth Status Bar Off">
<rect key="frame" x="0.0" y="0.0" width="414" height="101.5"/> <rect key="frame" x="0.0" y="0.0" width="414" height="101.5"/>
@ -394,7 +456,7 @@
</connections> </connections>
</view> </view>
<view contentMode="scaleToFill" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="u4f-uR-ri3" userLabel="Location Settings"> <view contentMode="scaleToFill" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="u4f-uR-ri3" userLabel="Location Settings">
<rect key="frame" x="0.0" y="553" width="414" height="143.5"/> <rect key="frame" x="0.0" y="717.5" width="414" height="143.5"/>
<subviews> <subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aGh-Fm-LNa" userLabel="Location Off bar"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aGh-Fm-LNa" userLabel="Location Off bar">
<rect key="frame" x="0.0" y="0.0" width="414" height="142.5"/> <rect key="frame" x="0.0" y="0.0" width="414" height="142.5"/>
@ -473,7 +535,7 @@
</constraints> </constraints>
</view> </view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="m1D-93-7sF" userLabel="ActiveView"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="m1D-93-7sF" userLabel="ActiveView">
<rect key="frame" x="0.0" y="696.5" width="414" height="427.5"/> <rect key="frame" x="0.0" y="861" width="414" height="427.5"/>
<subviews> <subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="1" translatesAutoresizingMaskIntoConstraints="NO" id="981-Cd-Xm3" userLabel="Active Stack View"> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="1" translatesAutoresizingMaskIntoConstraints="NO" id="981-Cd-Xm3" userLabel="Active Stack View">
<rect key="frame" x="0.0" y="0.0" width="414" height="427.5"/> <rect key="frame" x="0.0" y="0.0" width="414" height="427.5"/>
@ -592,7 +654,7 @@
</constraints> </constraints>
</view> </view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Aop-Ae-hRv" userLabel="StatisticsViewSection"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Aop-Ae-hRv" userLabel="StatisticsViewSection">
<rect key="frame" x="0.0" y="1136" width="414" height="124"/> <rect key="frame" x="0.0" y="1300.5" width="414" height="124"/>
<subviews> <subviews>
<view clipsSubviews="YES" contentMode="scaleToFill" verticalHuggingPriority="1" translatesAutoresizingMaskIntoConstraints="NO" id="eZl-C5-gSv" userLabel="StatisticsView"> <view clipsSubviews="YES" contentMode="scaleToFill" verticalHuggingPriority="1" translatesAutoresizingMaskIntoConstraints="NO" id="eZl-C5-gSv" userLabel="StatisticsView">
<rect key="frame" x="0.0" y="12" width="414" height="100"/> <rect key="frame" x="0.0" y="12" width="414" height="100"/>
@ -610,7 +672,7 @@
</constraints> </constraints>
</view> </view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9cE-NC-A20" userLabel="Help"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9cE-NC-A20" userLabel="Help">
<rect key="frame" x="0.0" y="1260" width="414" height="153"/> <rect key="frame" x="0.0" y="1424.5" width="414" height="153"/>
<subviews> <subviews>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="co1-dK-1WU"> <view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="co1-dK-1WU">
<rect key="frame" x="0.0" y="12" width="414" height="129"/> <rect key="frame" x="0.0" y="12" width="414" height="129"/>
@ -743,7 +805,7 @@
</constraints> </constraints>
</view> </view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7cN-DY-lc3" userLabel="Change language"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7cN-DY-lc3" userLabel="Change language">
<rect key="frame" x="0.0" y="1413" width="414" height="153"/> <rect key="frame" x="0.0" y="1577.5" width="414" height="153"/>
<subviews> <subviews>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bE9-gT-Hba"> <view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bE9-gT-Hba">
<rect key="frame" x="0.0" y="12" width="414" height="129"/> <rect key="frame" x="0.0" y="12" width="414" height="129"/>
@ -876,7 +938,7 @@
</constraints> </constraints>
</view> </view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="CGS-rw-uZS" userLabel="PrivacyPolicy"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="CGS-rw-uZS" userLabel="PrivacyPolicy">
<rect key="frame" x="0.0" y="1566" width="414" height="153"/> <rect key="frame" x="0.0" y="1730.5" width="414" height="153"/>
<subviews> <subviews>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="BBB-zD-Non"> <view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="BBB-zD-Non">
<rect key="frame" x="0.0" y="12" width="414" height="129"/> <rect key="frame" x="0.0" y="12" width="414" height="129"/>
@ -885,7 +947,7 @@
<rect key="frame" x="0.0" y="0.0" width="414" height="129"/> <rect key="frame" x="0.0" y="0.0" width="414" height="129"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Privacy Policy" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mFo-iF-cX3"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Privacy Policy" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mFo-iF-cX3">
<rect key="frame" x="72" y="16" width="302" height="24"/> <rect key="frame" x="72" y="16" width="302" height="77.5"/>
<accessibility key="accessibilityConfiguration"> <accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" none="YES"/> <accessibilityTraits key="traits" none="YES"/>
<bool key="isElement" value="NO"/> <bool key="isElement" value="NO"/>
@ -908,7 +970,7 @@
</constraints> </constraints>
</imageView> </imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Privacy Policy for COVIDSafe Application" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gF9-eh-ER2"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Privacy Policy for COVIDSafe Application" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gF9-eh-ER2">
<rect key="frame" x="72" y="40" width="302" height="73"/> <rect key="frame" x="72" y="93.5" width="302" height="19.5"/>
<accessibility key="accessibilityConfiguration"> <accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" none="YES"/> <accessibilityTraits key="traits" none="YES"/>
<bool key="isElement" value="NO"/> <bool key="isElement" value="NO"/>
@ -1009,7 +1071,7 @@
</constraints> </constraints>
</view> </view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vs9-rS-UOM" userLabel="Share CovidSafe"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vs9-rS-UOM" userLabel="Share CovidSafe">
<rect key="frame" x="0.0" y="1719" width="414" height="56"/> <rect key="frame" x="0.0" y="1883.5" width="414" height="56"/>
<subviews> <subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="RCa-zU-3Vo"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="RCa-zU-3Vo">
<rect key="frame" x="0.0" y="12" width="414" height="32"/> <rect key="frame" x="0.0" y="12" width="414" height="32"/>
@ -1120,7 +1182,7 @@
</constraints> </constraints>
</view> </view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="JSe-D6-hyV" userLabel="Upload Data"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="JSe-D6-hyV" userLabel="Upload Data">
<rect key="frame" x="0.0" y="1719" width="414" height="165.5"/> <rect key="frame" x="0.0" y="1883.5" width="414" height="165.5"/>
<subviews> <subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8pS-Df-p0U"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8pS-Df-p0U">
<rect key="frame" x="0.0" y="12" width="414" height="141.5"/> <rect key="frame" x="0.0" y="12" width="414" height="141.5"/>
@ -1240,7 +1302,7 @@
</constraints> </constraints>
</view> </view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="eZ2-CQ-dtQ" userLabel="Version View"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="eZ2-CQ-dtQ" userLabel="Version View">
<rect key="frame" x="0.0" y="1884.5" width="414" height="56"/> <rect key="frame" x="0.0" y="2049" width="414" height="56"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Version number:" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="O1w-Sl-OIH" userLabel="Version"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Version number:" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="O1w-Sl-OIH" userLabel="Version">
<rect key="frame" x="16" y="12" width="382" height="20"/> <rect key="frame" x="16" y="12" width="382" height="20"/>

View file

@ -4,15 +4,18 @@ import KeychainSwift
import SafariServices import SafariServices
import Reachability import Reachability
let reauthenticationNeededKey = "ReauthenticationNeededKey"
let showGeolockErrorKey = "showGeolockErrorKey"
class HomeViewController: UIViewController, HomeDelegate { class HomeViewController: UIViewController, HomeDelegate {
private var observer: NSObjectProtocol? private var observer: NSObjectProtocol?
private let reauthenticationNeededKey = "ReauthenticationNeededKey"
@IBOutlet weak var bluetoothStatusOffView: UIView! @IBOutlet weak var bluetoothStatusOffView: UIView!
@IBOutlet weak var bluetoothPermissionOffView: UIView! @IBOutlet weak var bluetoothPermissionOffView: UIView!
@IBOutlet weak var locationPermissionsView: UIView! @IBOutlet weak var locationPermissionsView: UIView!
@IBOutlet weak var inactiveSettingsContent: UIView! @IBOutlet weak var inactiveSettingsContent: UIView!
@IBOutlet weak var inactiveTokenExpiredView: UIView! @IBOutlet weak var inactiveTokenExpiredView: UIView!
@IBOutlet weak var inactiveGenericError: UIView!
@IBOutlet weak var shareView: UIView! @IBOutlet weak var shareView: UIView!
@IBOutlet weak var inactiveAppSectionView: UIView! @IBOutlet weak var inactiveAppSectionView: UIView!
@IBOutlet weak var activeAppSectionView: UIView! @IBOutlet weak var activeAppSectionView: UIView!
@ -42,8 +45,17 @@ class HomeViewController: UIViewController, HomeDelegate {
var allPermissionOn = true var allPermissionOn = true
var registrationNeeded: Bool { var showErrorToUser: Bool {
return UserDefaults.standard.bool(forKey: reauthenticationNeededKey) return showRegistrationError ||
showGenericError
}
var showGenericError: Bool {
return UserDefaults.standard.bool(forKey: showGeolockErrorKey)
}
var showRegistrationError: Bool {
return UserDefaults.standard.bool(forKey: reauthenticationNeededKey)
} }
var bluetoothStatusOn = true var bluetoothStatusOn = true
@ -222,7 +234,7 @@ class HomeViewController: UIViewController, HomeDelegate {
func updateJWTKeychainAccess() { func updateJWTKeychainAccess() {
let hasUpdatedKeychainAccess = UserDefaults.standard.bool(forKey: "HasUpdatedKeychainAccess") let hasUpdatedKeychainAccess = UserDefaults.standard.bool(forKey: "HasUpdatedKeychainAccess")
let keychain = KeychainSwift() let keychain = KeychainSwift.shared
if (!hasUpdatedKeychainAccess) { if (!hasUpdatedKeychainAccess) {
if let jwt = keychain.get("JWT_TOKEN") { if let jwt = keychain.get("JWT_TOKEN") {
if (keychain.set(jwt, forKey: "JWT_TOKEN", withAccess: .accessibleAfterFirstUnlock)) { if (keychain.set(jwt, forKey: "JWT_TOKEN", withAccess: .accessibleAfterFirstUnlock)) {
@ -272,6 +284,7 @@ class HomeViewController: UIViewController, HomeDelegate {
self?.toggleShareView() self?.toggleShareView()
self?.toggleStatisticsView() self?.toggleStatisticsView()
self?.toggleRegistrationNeededView() self?.toggleRegistrationNeededView()
self?.toggleGenericErrorView()
} }
}) })
} }
@ -349,37 +362,41 @@ class HomeViewController: UIViewController, HomeDelegate {
} }
fileprivate func toggleUploadView() { fileprivate func toggleUploadView() {
toggleViewVisibility(view: self.uploadView, isVisible: !self.didUploadData && !self.registrationNeeded) toggleViewVisibility(view: self.uploadView, isVisible: !self.didUploadData && !self.showErrorToUser)
} }
fileprivate func toggleShareView() { fileprivate func toggleShareView() {
toggleViewVisibility(view: shareView, isVisible: !registrationNeeded) toggleViewVisibility(view: shareView, isVisible: !showErrorToUser)
} }
fileprivate func toggleStatisticsView() { fileprivate func toggleStatisticsView() {
toggleViewVisibility(view: covidStatisticsSection, isVisible: !registrationNeeded) toggleViewVisibility(view: covidStatisticsSection, isVisible: !showErrorToUser)
} }
fileprivate func toggleHeaderView() { fileprivate func toggleHeaderView() {
toggleViewVisibility(view: inactiveAppSectionView, isVisible: !self.allPermissionOn || registrationNeeded) toggleViewVisibility(view: inactiveAppSectionView, isVisible: !self.allPermissionOn || showErrorToUser)
toggleViewVisibility(view: inactiveSettingsContent, isVisible: !self.allPermissionOn && !registrationNeeded) toggleViewVisibility(view: inactiveSettingsContent, isVisible: !self.allPermissionOn && !showErrorToUser)
toggleViewVisibility(view: activeAppSectionView, isVisible: self.allPermissionOn) toggleViewVisibility(view: activeAppSectionView, isVisible: self.allPermissionOn && !showErrorToUser)
} }
fileprivate func toggleBluetoothStatusView() { fileprivate func toggleBluetoothStatusView() {
toggleViewVisibility(view: bluetoothStatusOffView, isVisible: self.bluetoothPermissionOn && !self.bluetoothStatusOn && !registrationNeeded) toggleViewVisibility(view: bluetoothStatusOffView, isVisible: self.bluetoothPermissionOn && !self.bluetoothStatusOn && !showErrorToUser)
} }
fileprivate func toggleBluetoothPermissionStatusView() { fileprivate func toggleBluetoothPermissionStatusView() {
toggleViewVisibility(view: bluetoothPermissionOffView, isVisible: !self.allPermissionOn && !self.bluetoothPermissionOn && !registrationNeeded) toggleViewVisibility(view: bluetoothPermissionOffView, isVisible: !self.allPermissionOn && !self.bluetoothPermissionOn && !showErrorToUser)
} }
fileprivate func toggleLocationPermissionStatusView() { fileprivate func toggleLocationPermissionStatusView() {
toggleViewVisibility(view: locationPermissionsView, isVisible: !allPermissionOn && !locationPermissionOn && (bluetoothPermissionOn && bluetoothStatusOn) && !registrationNeeded) toggleViewVisibility(view: locationPermissionsView, isVisible: !allPermissionOn && !locationPermissionOn && (bluetoothPermissionOn && bluetoothStatusOn) && !showErrorToUser)
} }
fileprivate func toggleRegistrationNeededView() { fileprivate func toggleRegistrationNeededView() {
toggleViewVisibility(view: inactiveTokenExpiredView, isVisible: registrationNeeded) toggleViewVisibility(view: inactiveTokenExpiredView, isVisible: showRegistrationError)
}
fileprivate func toggleGenericErrorView() {
toggleViewVisibility(view: inactiveGenericError, isVisible: showGenericError)
} }
func attemptTurnOnBluetooth() { func attemptTurnOnBluetooth() {

View file

@ -53,7 +53,7 @@ final class InfoViewController: UIViewController {
silentNotificationsCountLabel.text = "\(UserDefaults.standard.integer(forKey: "debugSilentNotificationCount"))" silentNotificationsCountLabel.text = "\(UserDefaults.standard.integer(forKey: "debugSilentNotificationCount"))"
apnTokenLabel.text = UserDefaults.standard.string(forKey: "deviceTokenForAPN") apnTokenLabel.text = UserDefaults.standard.string(forKey: "deviceTokenForAPN")
let keychain = KeychainSwift() let keychain = KeychainSwift.shared
let dateFormatter = DateFormatter() let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .medium dateFormatter.timeStyle = .medium
@ -92,7 +92,7 @@ final class InfoViewController: UIViewController {
} }
@IBAction func requestUploadOTP(_ sender: UIButton) { @IBAction func requestUploadOTP(_ sender: UIButton) {
let keychain = KeychainSwift() let keychain = KeychainSwift.shared
guard let jwt = keychain.get("JWT_TOKEN") else { guard let jwt = keychain.get("JWT_TOKEN") else {
DLog("Error trying to upload when not logged in") DLog("Error trying to upload when not logged in")
return return
@ -199,7 +199,7 @@ final class InfoViewController: UIViewController {
} }
@IBAction func setReauthenticationNeeded(_ sender: Any) { @IBAction func setReauthenticationNeeded(_ sender: Any) {
let keychain = KeychainSwift() let keychain = KeychainSwift.shared
keychain.set("corruptedjwt", forKey: "JWT_TOKEN", withAccess: .accessibleAfterFirstUnlock) keychain.set("corruptedjwt", forKey: "JWT_TOKEN", withAccess: .accessibleAfterFirstUnlock)
} }

View file

@ -15,7 +15,7 @@ class InitialScreenViewController: UIViewController, EncounterDBMigrationProgres
var migrationStart: Date? var migrationStart: Date?
var isKeychainAvailable = false var isKeychainAvailable = false
var isDisplayTimeElapsed = false var isDisplayTimeElapsed = false
let keychain = KeychainSwift() let keychain = KeychainSwift.shared
var giveupTimer: Timer? var giveupTimer: Timer?
var initialDelayTimer: Timer? var initialDelayTimer: Timer?
var migrationViewController: UIViewController? var migrationViewController: UIViewController?

View file

@ -0,0 +1,13 @@
//
// KeychainSwift+Singleton.swift
// CovidSafe
//
// Copyright © 2021 Australian Government. All rights reserved.
//
import Foundation
import KeychainSwift
extension KeychainSwift {
static var shared = KeychainSwift()
}

View file

@ -240,7 +240,7 @@ class OTPViewController: UIViewController, RegistrationHandler {
result(.WrongOTP) result(.WrongOTP)
return return
} }
let keychain = KeychainSwift() let keychain = KeychainSwift.shared
keychain.set(tokenToStore, forKey: "JWT_TOKEN", withAccess: .accessibleAfterFirstUnlock) keychain.set(tokenToStore, forKey: "JWT_TOKEN", withAccess: .accessibleAfterFirstUnlock)
keychain.set(refreshToken, forKey: "REFRESH_TOKEN", withAccess: .accessibleAfterFirstUnlock) keychain.set(refreshToken, forKey: "REFRESH_TOKEN", withAccess: .accessibleAfterFirstUnlock)
UserDefaults.standard.set(true, forKey: "HasUpdatedKeychainAccess") UserDefaults.standard.set(true, forKey: "HasUpdatedKeychainAccess")

View file

@ -135,12 +135,34 @@ class PhoneNumberViewController: UIViewController, UITextFieldDelegate, Registra
self?.activityIndicator.stopAnimating() self?.activityIndicator.stopAnimating()
self?.getOTPButton.isEnabled = true self?.getOTPButton.isEnabled = true
if let error = error { if let error = error {
let alertMessage = error == .MaxRegistrationError ? "max_registrations".localizedString() : "PhoneVerificationErrorMessage".localizedString()
let errorAlert = UIAlertController(title: "PhoneVerificationErrorTitle".localizedString(), let errorAlert = UIAlertController(title: "PhoneVerificationErrorTitle".localizedString(),
message: "PhoneVerificationErrorMessage".localizedString(), message: alertMessage,
preferredStyle: .alert) preferredStyle: .alert)
errorAlert.addAction(UIAlertAction(title: "global_OK".localizedString(), style: .default, handler: { _ in if error == .MaxRegistrationError {
DLog("Unable to verify phone number") errorAlert.addAction(UIAlertAction(title: "max_registrations_button1".localizedString(), style: .default, handler: { _ in
})) DLog("Max registrations error, request deletion tapped")
let deleteUrl = URLHelper.getDataDeletionURL()
guard let url = URL(string: deleteUrl) else {
DLog("Unable to create url")
return
}
let safariVC = SFSafariViewController(url: url)
self?.present(safariVC, animated: true, completion: nil)
}))
errorAlert.addAction(UIAlertAction(title: "max_registration_button2".localizedString(), style: .default, handler: { _ in
DLog("Max registrations error, close alert")
}))
} else {
errorAlert.addAction(UIAlertAction(title: "global_OK".localizedString(), style: .default, handler: { _ in
DLog("Unable to verify phone number")
}))
}
self?.present(errorAlert, animated: true) self?.present(errorAlert, animated: true)
DLog("Phone number verification error: \(error.localizedDescription)") DLog("Phone number verification error: \(error.localizedDescription)")
return return

View file

@ -21,7 +21,7 @@ class QuestionUploadDataViewController: UIViewController {
// MARK: - // MARK: -
private func showUploadDataFlow() { private func showUploadDataFlow() {
let keychain = KeychainSwift() let keychain = KeychainSwift.shared
setIsLoading(true) setIsLoading(true)
guard let jwt = keychain.get("JWT_TOKEN") else { guard let jwt = keychain.get("JWT_TOKEN") else {
DLog("Error trying to upload when not logged in") DLog("Error trying to upload when not logged in")

View file

@ -11,7 +11,7 @@ import KeychainSwift
class RegistrationIntroViewController: UIViewController { class RegistrationIntroViewController: UIViewController {
let keychain = KeychainSwift() let keychain = KeychainSwift.shared
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)

View file

@ -64,7 +64,6 @@ class RegistrationSuccessViewController: UIViewController {
if reauthenticating { if reauthenticating {
dismiss(animated: true, completion: nil) dismiss(animated: true, completion: nil)
} else { } else {
let homeVC = HomeViewController(nibName: "HomeView", bundle: nil)
let tabVC = MainTabBarViewController() let tabVC = MainTabBarViewController()
self.navigationController?.setViewControllers([tabVC], animated: true) self.navigationController?.setViewControllers([tabVC], animated: true)
} }

View file

@ -62,4 +62,8 @@ struct URLHelper {
return "\(getHelpURL())#location-permissions" return "\(getHelpURL())#location-permissions"
} }
static func getDataDeletionURL() -> String {
return "https://covidsafe-form.service.gov.au"
}
} }

View file

@ -12,7 +12,7 @@ import KeychainSwift
final class UploadHelper { final class UploadHelper {
public static func uploadEncounterData(pin: String?, _ result: @escaping (UploadResult, String?) -> Void) { public static func uploadEncounterData(pin: String?, _ result: @escaping (UploadResult, String?) -> Void) {
let keychain = KeychainSwift() let keychain = KeychainSwift.shared
guard let managedContext = EncounterDB.shared.persistentContainer?.viewContext else { guard let managedContext = EncounterDB.shared.persistentContainer?.viewContext else {
result(.Failed, "[001]") result(.Failed, "[001]")

View file

@ -1,3 +1,4 @@
"[test]decommission_message" = "";
"action_continue" = "تابع"; "action_continue" = "تابع";
"action_report_an_issue" = "بلِّغ عن مشكلة"; "action_report_an_issue" = "بلِّغ عن مشكلة";
"action_upload_done" = "تمّ"; "action_upload_done" = "تمّ";
@ -286,6 +287,8 @@
"factors_intro_2" = "كما يمكن أن تتأثر المصافحات بالعوامل البيئية، بما في ذلك:"; "factors_intro_2" = "كما يمكن أن تتأثر المصافحات بالعوامل البيئية، بما في ذلك:";
/* Example: "From 22 to 28 January 2021" */ /* Example: "From 22 to 28 January 2021" */
"from" = ""; "from" = "";
/* Error message for when a user tries to signup outside of Australia. */
"geoblock_error_message" = "";
"global_back" = "رجوع"; "global_back" = "رجوع";
"global_close" = "إغلاق"; "global_close" = "إغلاق";
"global_double_tap" = "أنقر مرتين للتصحيح"; "global_double_tap" = "أنقر مرتين للتصحيح";
@ -367,6 +370,9 @@
"location_off" = "الموقع الجغرافي: معطّل"; "location_off" = "الموقع الجغرافي: معطّل";
"location_off_description" = "يتطلب جهاز iphone الخاص بك تشغيل الموقع الجغرافي ليتمكن تطبيق COVIDSafe من العمل. لا يقوم تطبيق COVIDSafe بتتبّع بيانات الموقع الجغرافي أو تخزينها."; "location_off_description" = "يتطلب جهاز iphone الخاص بك تشغيل الموقع الجغرافي ليتمكن تطبيق COVIDSafe من العمل. لا يقوم تطبيق COVIDSafe بتتبّع بيانات الموقع الجغرافي أو تخزينها.";
"main_restrictions" = "القيود الرئيسية"; "main_restrictions" = "القيود الرئيسية";
"max_registration_button2" = "";
"max_registrations" = "";
"max_registrations_button1" = "";
/* Splash Screen */ /* Splash Screen */
"migration_in_progress" = "تحديث تطبيق COVIDSafe قيد الإنجاز. \n\nيُرجى التأكد من عدم إغلاق هاتفك إلى أن يتم اكتمال التحديث."; "migration_in_progress" = "تحديث تطبيق COVIDSafe قيد الإنجاز. \n\nيُرجى التأكد من عدم إغلاق هاتفك إلى أن يتم اكتمال التحديث.";
"minute" = "دقيقة"; "minute" = "دقيقة";

View file

@ -1,3 +1,4 @@
"[test]decommission_message" = "";
"action_continue" = "Συνεχίστε"; "action_continue" = "Συνεχίστε";
"action_report_an_issue" = "Αναφέρετε το πρόβλημα"; "action_report_an_issue" = "Αναφέρετε το πρόβλημα";
"action_upload_done" = "Συνεχίστε"; "action_upload_done" = "Συνεχίστε";
@ -286,6 +287,8 @@
"factors_intro_2" = "Οι χειραψίες μπορούν επίσης να επηρεαστούν από περιβαλλοντικούς παράγοντες, όπως:"; "factors_intro_2" = "Οι χειραψίες μπορούν επίσης να επηρεαστούν από περιβαλλοντικούς παράγοντες, όπως:";
/* Example: "From 22 to 28 January 2021" */ /* Example: "From 22 to 28 January 2021" */
"from" = ""; "from" = "";
/* Error message for when a user tries to signup outside of Australia. */
"geoblock_error_message" = "";
"global_back" = "Πίσω"; "global_back" = "Πίσω";
"global_close" = "Κλείστε"; "global_close" = "Κλείστε";
"global_double_tap" = "πατήστε δύο φορές για επεξεργασία"; "global_double_tap" = "πατήστε δύο φορές για επεξεργασία";
@ -367,6 +370,9 @@
"location_off" = "Τοποθεσία: ΑΠΕΝΕΡΓΟΠΟΙΗΜΕΝΗ"; "location_off" = "Τοποθεσία: ΑΠΕΝΕΡΓΟΠΟΙΗΜΕΝΗ";
"location_off_description" = "Το iPhone σας απαιτεί άδεια τοποθεσίας για να λειτουργήσει την COVIDSafe. Η COVIDSafe ΔΕΝ παρακολουθεί ούτε αποθηκεύει τα δεδομένα τοποθεσίας σας."; "location_off_description" = "Το iPhone σας απαιτεί άδεια τοποθεσίας για να λειτουργήσει την COVIDSafe. Η COVIDSafe ΔΕΝ παρακολουθεί ούτε αποθηκεύει τα δεδομένα τοποθεσίας σας.";
"main_restrictions" = "Κύριοι περιορισμοί"; "main_restrictions" = "Κύριοι περιορισμοί";
"max_registration_button2" = "";
"max_registrations" = "";
"max_registrations_button1" = "";
/* Splash Screen */ /* Splash Screen */
"migration_in_progress" = "Η ενημέρωση της COVIDSafe συνεχίζεται. \n\nΒεβαιωθείτε ότι το τηλέφωνό σας δεν είναι απενεργοποιημένο έως ότου ολοκληρωθεί η ενημέρωση."; "migration_in_progress" = "Η ενημέρωση της COVIDSafe συνεχίζεται. \n\nΒεβαιωθείτε ότι το τηλέφωνό σας δεν είναι απενεργοποιημένο έως ότου ολοκληρωθεί η ενημέρωση.";
"minute" = "Λεπτό"; "minute" = "Λεπτό";

View file

@ -1,3 +1,4 @@
"[test]decommission_message" = "Delete this app now";
"action_continue" = "Continue"; "action_continue" = "Continue";
"action_report_an_issue" = "Report an issue"; "action_report_an_issue" = "Report an issue";
"action_upload_done" = "Done"; "action_upload_done" = "Done";
@ -286,6 +287,8 @@
"factors_intro_2" = "Handshakes can also be affected by environmental factors, including:"; "factors_intro_2" = "Handshakes can also be affected by environmental factors, including:";
/* Example: "From 22 to 28 January 2021" */ /* Example: "From 22 to 28 January 2021" */
"from" = "From"; "from" = "From";
/* Error message for when a user tries to signup outside of Australia. */
"geoblock_error_message" = "You may be connected using an internet provider from outside Australia. This could happen when using international data roaming on a non-Australian SIM card.\n\nPlease connect to an Australian network or use a local Wi-Fi internet connection to continue.";
"global_back" = "Back"; "global_back" = "Back";
"global_close" = "Close"; "global_close" = "Close";
"global_double_tap" = "double tap to edit"; "global_double_tap" = "double tap to edit";
@ -367,6 +370,9 @@
"location_off" = "Location: OFF"; "location_off" = "Location: OFF";
"location_off_description" = "Your iPhone requires Location permission for COVIDSafe to work. COVIDSafe does NOT track or store your location data."; "location_off_description" = "Your iPhone requires Location permission for COVIDSafe to work. COVIDSafe does NOT track or store your location data.";
"main_restrictions" = "Main restrictions"; "main_restrictions" = "Main restrictions";
"max_registration_button2" = "Cancel";
"max_registrations" = "You've reached the limit to register using the same mobile number.\n\nTo use the same mobile number to register again, you must request to delete your current registration information.";
"max_registrations_button1" = "Request deletion";
/* Splash Screen */ /* Splash Screen */
"migration_in_progress" = " COVIDSafe update in progress. \n\n Please make sure you phone is not switched off until the update is complete."; "migration_in_progress" = " COVIDSafe update in progress. \n\n Please make sure you phone is not switched off until the update is complete.";
"minute" = "Minute"; "minute" = "Minute";

View file

@ -1,3 +1,4 @@
"[test]decommission_message" = "";
"action_continue" = "Continua"; "action_continue" = "Continua";
"action_report_an_issue" = "Segnala un problema"; "action_report_an_issue" = "Segnala un problema";
"action_upload_done" = "Eseguito"; "action_upload_done" = "Eseguito";
@ -286,6 +287,8 @@
"factors_intro_2" = "Anche le strette di mano possono essere influenzate da fattori ambientali:"; "factors_intro_2" = "Anche le strette di mano possono essere influenzate da fattori ambientali:";
/* Example: "From 22 to 28 January 2021" */ /* Example: "From 22 to 28 January 2021" */
"from" = ""; "from" = "";
/* Error message for when a user tries to signup outside of Australia. */
"geoblock_error_message" = "";
"global_back" = "Indietro"; "global_back" = "Indietro";
"global_close" = "Chiudi"; "global_close" = "Chiudi";
"global_double_tap" = "Fai un doppio click per modificare"; "global_double_tap" = "Fai un doppio click per modificare";
@ -367,6 +370,9 @@
"location_off" = "Posizione: OFF"; "location_off" = "Posizione: OFF";
"location_off_description" = "Il tuo iPhone richiede l'autorizzazione alla localizzazione affinché COVIDSafe funzioni. COVIDSafe NON memorizza né utilizza i dati relativi alla tua posizione."; "location_off_description" = "Il tuo iPhone richiede l'autorizzazione alla localizzazione affinché COVIDSafe funzioni. COVIDSafe NON memorizza né utilizza i dati relativi alla tua posizione.";
"main_restrictions" = "Restrizioni principali"; "main_restrictions" = "Restrizioni principali";
"max_registration_button2" = "";
"max_registrations" = "";
"max_registrations_button1" = "";
/* Splash Screen */ /* Splash Screen */
"migration_in_progress" = "Aggiornamento COVIDSafe in corso. \n\nAssicurati che il cellulare non sia spento fino al completamento dell'aggiornamento."; "migration_in_progress" = "Aggiornamento COVIDSafe in corso. \n\nAssicurati che il cellulare non sia spento fino al completamento dell'aggiornamento.";
"minute" = "Minuto"; "minute" = "Minuto";

View file

@ -1,3 +1,4 @@
"[test]decommission_message" = "";
"action_continue" = "계속"; "action_continue" = "계속";
"action_report_an_issue" = "문제 신고하기"; "action_report_an_issue" = "문제 신고하기";
"action_upload_done" = "완료"; "action_upload_done" = "완료";
@ -286,6 +287,8 @@
"factors_intro_2" = "다음과 같은 환경 요인 역시 블루투스 악수에 영향을 미칠 수 있습니다."; "factors_intro_2" = "다음과 같은 환경 요인 역시 블루투스 악수에 영향을 미칠 수 있습니다.";
/* Example: "From 22 to 28 January 2021" */ /* Example: "From 22 to 28 January 2021" */
"from" = "부터"; "from" = "부터";
/* Error message for when a user tries to signup outside of Australia. */
"geoblock_error_message" = "";
"global_back" = "뒤로"; "global_back" = "뒤로";
"global_close" = "닫기"; "global_close" = "닫기";
"global_double_tap" = "두 번 탭해서 수정하세요"; "global_double_tap" = "두 번 탭해서 수정하세요";
@ -367,6 +370,9 @@
"location_off" = "위치 서비스: 꺼짐"; "location_off" = "위치 서비스: 꺼짐";
"location_off_description" = "COVIDSafe가 제대로 실행되기 위해서는 여러분의 아이폰에서 위치 서비스 기능을 허용해야 합니다. COVIDSafe는 여러분의 위치 정보를 추적하거나 저장하지 않습니다."; "location_off_description" = "COVIDSafe가 제대로 실행되기 위해서는 여러분의 아이폰에서 위치 서비스 기능을 허용해야 합니다. COVIDSafe는 여러분의 위치 정보를 추적하거나 저장하지 않습니다.";
"main_restrictions" = "주요 규제 조치"; "main_restrictions" = "주요 규제 조치";
"max_registration_button2" = "";
"max_registrations" = "";
"max_registrations_button1" = "";
/* Splash Screen */ /* Splash Screen */
"migration_in_progress" = "COVIDSafe 업데이트 진행 중. \n\n업데이트가 완료될 때까지 휴대폰이 꺼지지 않도록 해주세요."; "migration_in_progress" = "COVIDSafe 업데이트 진행 중. \n\n업데이트가 완료될 때까지 휴대폰이 꺼지지 않도록 해주세요.";
"minute" = "분"; "minute" = "분";

View file

@ -1,3 +1,4 @@
"[test]decommission_message" = "";
"action_continue" = "ਜਾਰੀ ਰੱਖੋ"; "action_continue" = "ਜਾਰੀ ਰੱਖੋ";
"action_report_an_issue" = "ਮੁੱਦੇ/ਮਸਲੇ ਬਾਰੇ ਰਿਪੋਰਟ ਕਰੋ|"; "action_report_an_issue" = "ਮੁੱਦੇ/ਮਸਲੇ ਬਾਰੇ ਰਿਪੋਰਟ ਕਰੋ|";
"action_upload_done" = "ਕਰ ਦਿੱਤਾ"; "action_upload_done" = "ਕਰ ਦਿੱਤਾ";
@ -286,6 +287,8 @@
"factors_intro_2" = "ਹੱਥ ਮਿਲਾਉਣੇ, ਵਾਤਾਵਰਣਕ ਕਾਰਕਾਂ ਦੁਆਰਾ ਵੀ ਪ੍ਰਭਾਵਤ ਹੋ ਸਕਦੇ ਹਨ, ਜਿੰਨ੍ਹਾਂ ਵਿੱਚ ਸ਼ਾਮਲ ਹਨ :"; "factors_intro_2" = "ਹੱਥ ਮਿਲਾਉਣੇ, ਵਾਤਾਵਰਣਕ ਕਾਰਕਾਂ ਦੁਆਰਾ ਵੀ ਪ੍ਰਭਾਵਤ ਹੋ ਸਕਦੇ ਹਨ, ਜਿੰਨ੍ਹਾਂ ਵਿੱਚ ਸ਼ਾਮਲ ਹਨ :";
/* Example: "From 22 to 28 January 2021" */ /* Example: "From 22 to 28 January 2021" */
"from" = "ਵੱਲੋਂ"; "from" = "ਵੱਲੋਂ";
/* Error message for when a user tries to signup outside of Australia. */
"geoblock_error_message" = "";
"global_back" = "ਪਿੱਛੇ"; "global_back" = "ਪਿੱਛੇ";
"global_close" = "ਬੰਦ ਕਰੋ"; "global_close" = "ਬੰਦ ਕਰੋ";
"global_double_tap" = "ਸੋਧਣ ਲਈ ਡਬਲ ਟੈਪ ਕਰੋ"; "global_double_tap" = "ਸੋਧਣ ਲਈ ਡਬਲ ਟੈਪ ਕਰੋ";
@ -367,6 +370,9 @@
"location_off" = "ਲੋਕੇਸ਼ਨ: ਔਫ"; "location_off" = "ਲੋਕੇਸ਼ਨ: ਔਫ";
"location_off_description" = "COVIDSafe ਕੰਮ ਕਰ ਸਕੇ, ਇਸ ਦੇ ਲਈ ਤੁਹਾਡੇ iPhone ਨੂੰ ਲੋਕੇਸ਼ਨ ਆਗਿਆ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ। *COVIDSafe ਤੁਹਾਡੇ ਸਥਾਨਕ ਅੰਕੜਿਆਂ ਨੂੰ ਨਹੀਂ ਢੂੰਡਦਾ ਜਾਂ ਸੰਭਾਲਦਾ।*"; "location_off_description" = "COVIDSafe ਕੰਮ ਕਰ ਸਕੇ, ਇਸ ਦੇ ਲਈ ਤੁਹਾਡੇ iPhone ਨੂੰ ਲੋਕੇਸ਼ਨ ਆਗਿਆ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ। *COVIDSafe ਤੁਹਾਡੇ ਸਥਾਨਕ ਅੰਕੜਿਆਂ ਨੂੰ ਨਹੀਂ ਢੂੰਡਦਾ ਜਾਂ ਸੰਭਾਲਦਾ।*";
"main_restrictions" = "ਮੁੱਖ ਪਾਬੰਦੀਆਂ"; "main_restrictions" = "ਮੁੱਖ ਪਾਬੰਦੀਆਂ";
"max_registration_button2" = "";
"max_registrations" = "";
"max_registrations_button1" = "";
/* Splash Screen */ /* Splash Screen */
"migration_in_progress" = "COVIDSafe ਅੱਪਡੇਟ ਚੱਲ ਰਿਹਾ ਹੈ। \n\nਕਿਰਪਾ ਕਰਕੇ ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਤੁਹਾਡਾ ਫ਼ੋਨ ਤਦ ਤੱਕ ਬੰਦ ਨਹੀਂ ਹੋਣਾ ਚਾਹੀਦਾ ਜਦ ਤੱਕ ਅੱਪਡੇਟ ਪੂਰਾ ਨਹੀਂ ਹੋ ਜਾਂਦਾ।"; "migration_in_progress" = "COVIDSafe ਅੱਪਡੇਟ ਚੱਲ ਰਿਹਾ ਹੈ। \n\nਕਿਰਪਾ ਕਰਕੇ ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਤੁਹਾਡਾ ਫ਼ੋਨ ਤਦ ਤੱਕ ਬੰਦ ਨਹੀਂ ਹੋਣਾ ਚਾਹੀਦਾ ਜਦ ਤੱਕ ਅੱਪਡੇਟ ਪੂਰਾ ਨਹੀਂ ਹੋ ਜਾਂਦਾ।";
"minute" = "ਮਿੰਟ"; "minute" = "ਮਿੰਟ";

View file

@ -1,3 +1,4 @@
"[test]decommission_message" = "";
"action_continue" = "Devam"; "action_continue" = "Devam";
"action_report_an_issue" = "Sorun bildir"; "action_report_an_issue" = "Sorun bildir";
"action_upload_done" = "Bitti"; "action_upload_done" = "Bitti";
@ -286,6 +287,8 @@
"factors_intro_2" = "El sıkışmalar çevresel faktörlerden de etkilenebilir, örneğin:"; "factors_intro_2" = "El sıkışmalar çevresel faktörlerden de etkilenebilir, örneğin:";
/* Example: "From 22 to 28 January 2021" */ /* Example: "From 22 to 28 January 2021" */
"from" = ""; "from" = "";
/* Error message for when a user tries to signup outside of Australia. */
"geoblock_error_message" = "";
"global_back" = "Geri"; "global_back" = "Geri";
"global_close" = "Kapat"; "global_close" = "Kapat";
"global_double_tap" = "düzeltme yapmak için iki defa tıklayınız"; "global_double_tap" = "düzeltme yapmak için iki defa tıklayınız";
@ -367,6 +370,9 @@
"location_off" = "Konum: KAPALI"; "location_off" = "Konum: KAPALI";
"location_off_description" = "iPhoneunuz, COVIDSafein çalışması için Konum iznine ihtiyaç duyar. COVIDSafe konum verilerinizi İZLEMEZ veya SAKLAMAZ."; "location_off_description" = "iPhoneunuz, COVIDSafein çalışması için Konum iznine ihtiyaç duyar. COVIDSafe konum verilerinizi İZLEMEZ veya SAKLAMAZ.";
"main_restrictions" = "Ana kısıtlamalar"; "main_restrictions" = "Ana kısıtlamalar";
"max_registration_button2" = "";
"max_registrations" = "";
"max_registrations_button1" = "";
/* Splash Screen */ /* Splash Screen */
"migration_in_progress" = " COVIDSafe güncellemesi devam ediyor. \n\n Lütfen güncelleme tamamlanana kadar telefonunuzu kapatmayın."; "migration_in_progress" = " COVIDSafe güncellemesi devam ediyor. \n\n Lütfen güncelleme tamamlanana kadar telefonunuzu kapatmayın.";
"minute" = "Dakika"; "minute" = "Dakika";

View file

@ -1,3 +1,4 @@
"[test]decommission_message" = "";
"action_continue" = "Tiếp tục"; "action_continue" = "Tiếp tục";
"action_report_an_issue" = "Báo cáo sự cố"; "action_report_an_issue" = "Báo cáo sự cố";
"action_upload_done" = "Hoàn tất"; "action_upload_done" = "Hoàn tất";
@ -286,6 +287,8 @@
"factors_intro_2" = "Chức năng bắt tay cũng có thể bị ảnh hưởng bởi các yếu tố môi trường, bao gồm:"; "factors_intro_2" = "Chức năng bắt tay cũng có thể bị ảnh hưởng bởi các yếu tố môi trường, bao gồm:";
/* Example: "From 22 to 28 January 2021" */ /* Example: "From 22 to 28 January 2021" */
"from" = ""; "from" = "";
/* Error message for when a user tries to signup outside of Australia. */
"geoblock_error_message" = "";
"global_back" = "Trở lại"; "global_back" = "Trở lại";
"global_close" = "Đóng"; "global_close" = "Đóng";
"global_double_tap" = "nhấn đúp để chỉnh sửa"; "global_double_tap" = "nhấn đúp để chỉnh sửa";
@ -367,6 +370,9 @@
"location_off" = "Vị trí: TẮT"; "location_off" = "Vị trí: TẮT";
"location_off_description" = "iPhone của bạn yêu cầu quyền truy cập Vị trí để COVIDSafe hoạt động. COVIDSafe KHÔNG theo dõi hoặc lưu trữ dữ liệu vị trí của bạn."; "location_off_description" = "iPhone của bạn yêu cầu quyền truy cập Vị trí để COVIDSafe hoạt động. COVIDSafe KHÔNG theo dõi hoặc lưu trữ dữ liệu vị trí của bạn.";
"main_restrictions" = "Những hạn chế chính"; "main_restrictions" = "Những hạn chế chính";
"max_registration_button2" = "";
"max_registrations" = "";
"max_registrations_button1" = "";
/* Splash Screen */ /* Splash Screen */
"migration_in_progress" = "COVIDSafe trong tiến trình cập nhật. \n\nVui lòng đảm bảo điện thoại của bạn không bị tắt cho đến khi cập nhật hoàn tất."; "migration_in_progress" = "COVIDSafe trong tiến trình cập nhật. \n\nVui lòng đảm bảo điện thoại của bạn không bị tắt cho đến khi cập nhật hoàn tất.";
"minute" = "Phút"; "minute" = "Phút";

View file

@ -1,3 +1,4 @@
"[test]decommission_message" = "";
"action_continue" = "继续"; "action_continue" = "继续";
"action_report_an_issue" = "报告问题"; "action_report_an_issue" = "报告问题";
"action_upload_done" = "完成"; "action_upload_done" = "完成";
@ -286,6 +287,8 @@
"factors_intro_2" = "蓝牙握手也会受到环境因素的影响,这些因素包括:"; "factors_intro_2" = "蓝牙握手也会受到环境因素的影响,这些因素包括:";
/* Example: "From 22 to 28 January 2021" */ /* Example: "From 22 to 28 January 2021" */
"from" = ""; "from" = "";
/* Error message for when a user tries to signup outside of Australia. */
"geoblock_error_message" = "";
"global_back" = "返回"; "global_back" = "返回";
"global_close" = "关闭"; "global_close" = "关闭";
"global_double_tap" = "双击进行编辑"; "global_double_tap" = "双击进行编辑";
@ -367,6 +370,9 @@
"location_off" = "位置:关闭"; "location_off" = "位置:关闭";
"location_off_description" = "您的 iPhone 要求COVIDSafe 获得位置权限才能运行。COVIDSafe 不会跟踪或存储您的位置数据。"; "location_off_description" = "您的 iPhone 要求COVIDSafe 获得位置权限才能运行。COVIDSafe 不会跟踪或存储您的位置数据。";
"main_restrictions" = "主要限制措施"; "main_restrictions" = "主要限制措施";
"max_registration_button2" = "";
"max_registrations" = "";
"max_registrations_button1" = "";
/* Splash Screen */ /* Splash Screen */
"migration_in_progress" = "COVIDSafe正在更新。 \n\n请保持开机状态直至更新完成。"; "migration_in_progress" = "COVIDSafe正在更新。 \n\n请保持开机状态直至更新完成。";
"minute" = "分钟"; "minute" = "分钟";

View file

@ -1,3 +1,4 @@
"[test]decommission_message" = "";
"action_continue" = "繼續"; "action_continue" = "繼續";
"action_report_an_issue" = "報告問題"; "action_report_an_issue" = "報告問題";
"action_upload_done" = "完成"; "action_upload_done" = "完成";
@ -286,6 +287,8 @@
"factors_intro_2" = "藍牙握手也可以受到環境因素影響,包括:"; "factors_intro_2" = "藍牙握手也可以受到環境因素影響,包括:";
/* Example: "From 22 to 28 January 2021" */ /* Example: "From 22 to 28 January 2021" */
"from" = ""; "from" = "";
/* Error message for when a user tries to signup outside of Australia. */
"geoblock_error_message" = "";
"global_back" = "返回"; "global_back" = "返回";
"global_close" = "關閉"; "global_close" = "關閉";
"global_double_tap" = "點觸兩次來編輯"; "global_double_tap" = "點觸兩次來編輯";
@ -367,6 +370,9 @@
"location_off" = "位置:關閉"; "location_off" = "位置:關閉";
"location_off_description" = "你的iPhone要求COVIDSafe獲得位置許可權才能正常運作。COVIDSafe不會跟蹤或者存儲你的位置資料。"; "location_off_description" = "你的iPhone要求COVIDSafe獲得位置許可權才能正常運作。COVIDSafe不會跟蹤或者存儲你的位置資料。";
"main_restrictions" = "主要限制措施"; "main_restrictions" = "主要限制措施";
"max_registration_button2" = "";
"max_registrations" = "";
"max_registrations_button1" = "";
/* Splash Screen */ /* Splash Screen */
"migration_in_progress" = "正在更新 COVIDSafe。\n\n請保持開機狀態直至更新完成為止。"; "migration_in_progress" = "正在更新 COVIDSafe。\n\n請保持開機狀態直至更新完成為止。";
"minute" = "分鐘 "; "minute" = "分鐘 ";

5
Gemfile Normal file
View file

@ -0,0 +1,5 @@
source "https://rubygems.org"
gem "fastlane"
gem 'cocoapods'
gem 'shellwords'

269
Gemfile.lock Normal file
View file

@ -0,0 +1,269 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.3)
activesupport (5.2.5)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
artifactory (3.0.15)
atomos (0.1.3)
aws-eventstream (1.1.1)
aws-partitions (1.443.0)
aws-sdk-core (3.113.1)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-kms (1.43.0)
aws-sdk-core (~> 3, >= 3.112.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.93.0)
aws-sdk-core (~> 3, >= 3.112.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1)
aws-sigv4 (1.2.3)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
claide (1.0.3)
cocoapods (1.10.1)
addressable (~> 2.6)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.10.1)
cocoapods-deintegrate (>= 1.0.3, < 2.0)
cocoapods-downloader (>= 1.4.0, < 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.4.0, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored2 (~> 3.1)
escape (~> 0.0.4)
fourflusher (>= 2.3.0, < 3.0)
gh_inspector (~> 1.0)
molinillo (~> 0.6.6)
nap (~> 1.0)
ruby-macho (~> 1.4)
xcodeproj (>= 1.19.0, < 2.0)
cocoapods-core (1.10.1)
activesupport (> 5.0, < 6)
addressable (~> 2.6)
algoliasearch (~> 1.0)
concurrent-ruby (~> 1.1)
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
netrc (~> 0.11)
public_suffix
typhoeus (~> 1.0)
cocoapods-deintegrate (1.0.4)
cocoapods-downloader (1.4.0)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.0)
cocoapods-trunk (1.5.0)
nap (>= 0.8, < 2.0)
netrc (~> 0.11)
cocoapods-try (1.2.0)
colored (1.2)
colored2 (3.1.2)
commander-fastlane (4.4.6)
highline (~> 1.7.2)
concurrent-ruby (1.1.8)
declarative (0.0.20)
declarative-option (0.1.0)
digest-crc (0.6.3)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.6)
emoji_regex (3.2.2)
escape (0.0.4)
ethon (0.12.0)
ffi (>= 1.3.0)
excon (0.79.0)
faraday (1.3.0)
faraday-net_http (~> 1.0)
multipart-post (>= 1.2, < 3)
ruby2_keywords
faraday-cookie_jar (0.0.7)
faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
faraday-net_http (1.0.1)
faraday_middleware (1.0.0)
faraday (~> 1.0)
fastimage (2.2.3)
fastlane (2.180.1)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0)
artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0)
colored
commander-fastlane (>= 4.4.6, < 5.0.0)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
faraday (~> 1.0)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-api-client (>= 0.37.0, < 0.39.0)
google-cloud-storage (>= 1.15.0, < 2.0.0)
highline (>= 1.7.2, < 2.0.0)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (~> 2.0.0)
naturally (~> 2.2)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.3)
simctl (~> 1.6.3)
slack-notifier (>= 2.0.0, < 3.0.0)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
ffi (1.15.0)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
google-api-client (0.38.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (~> 0.9)
httpclient (>= 2.8.1, < 3.0)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.12)
google-apis-core (0.3.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (~> 0.14)
httpclient (>= 2.8.1, < 3.0)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
rexml
signet (~> 0.14)
webrick
google-apis-iamcredentials_v1 (0.3.0)
google-apis-core (~> 0.1)
google-apis-storage_v1 (0.3.0)
google-apis-core (~> 0.1)
google-cloud-core (1.6.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.5.0)
faraday (>= 0.17.3, < 2.0)
google-cloud-errors (1.1.0)
google-cloud-storage (1.31.0)
addressable (~> 2.5)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.1)
google-cloud-core (~> 1.2)
googleauth (~> 0.9)
mini_mime (~> 1.0)
googleauth (0.16.1)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.14)
highline (1.7.10)
http-cookie (1.0.3)
domain_name (~> 0.5)
httpclient (2.8.3)
i18n (1.8.10)
concurrent-ruby (~> 1.0)
jmespath (1.4.0)
json (2.5.1)
jwt (2.2.2)
memoist (0.16.2)
mini_magick (4.11.0)
mini_mime (1.1.0)
minitest (5.14.4)
molinillo (0.6.6)
multi_json (1.15.0)
multipart-post (2.0.0)
nanaimo (0.3.0)
nap (1.1.0)
naturally (2.2.1)
netrc (0.11.0)
os (1.1.1)
plist (3.6.0)
public_suffix (4.0.6)
rake (13.0.3)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.2.5)
rouge (2.0.7)
ruby-macho (1.4.0)
ruby2_keywords (0.0.4)
rubyzip (2.3.0)
security (0.1.3)
shellwords (0.1.0)
signet (0.15.0)
addressable (~> 2.3)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.8)
CFPropertyList
naturally
slack-notifier (2.3.2)
terminal-notifier (2.0.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
tty-cursor (0.7.1)
tty-screen (0.8.1)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (1.2.9)
thread_safe (~> 0.1)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
webrick (1.7.0)
word_wrap (1.0.0)
xcodeproj (1.19.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
ruby
DEPENDENCIES
cocoapods
fastlane
shellwords
BUNDLED WITH
2.1.4

View file

@ -31,3 +31,11 @@ target 'CovidSafe-staging' do
pod 'FlagKit' pod 'FlagKit'
pod 'ReachabilitySwift' pod 'ReachabilitySwift'
end end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '10.0'
end
end
end

View file

@ -1,8 +1,8 @@
PODS: PODS:
- Alamofire (5.0.5) - Alamofire (5.4.0)
- FlagKit (2.2) - FlagKit (2.2)
- KeychainSwift (19.0.0) - KeychainSwift (19.0.0)
- lottie-ios (3.1.6) - lottie-ios (3.1.9)
- ReachabilitySwift (5.0.0) - ReachabilitySwift (5.0.0)
DEPENDENCIES: DEPENDENCIES:
@ -21,12 +21,12 @@ SPEC REPOS:
- ReachabilitySwift - ReachabilitySwift
SPEC CHECKSUMS: SPEC CHECKSUMS:
Alamofire: df2f8f826963b08b9a870791ad48e07a10090b2e Alamofire: 3b6a534a3df22db367e4dedeeca73d1ddfcf0e2f
FlagKit: eca7dc89064b0c986302ba9acefad1bf80a435b1 FlagKit: eca7dc89064b0c986302ba9acefad1bf80a435b1
KeychainSwift: a06190cf933ad46b1e0abc3d77d29c06331715c7 KeychainSwift: a06190cf933ad46b1e0abc3d77d29c06331715c7
lottie-ios: 85ce835dd8c53e02509f20729fc7d6a4e6645a0a lottie-ios: 3a3758ef5a008e762faec9c9d50a39842f26d124
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
PODFILE CHECKSUM: 5c536190b2facfc3f56594f2313066237ffac6ab PODFILE CHECKSUM: 3075a84136d3a2d8fde2aeecdc0d0c5147e0306f
COCOAPODS: 1.10.1 COCOAPODS: 1.9.1

6
fastlane/Appfile Normal file
View file

@ -0,0 +1,6 @@
itc_team_id(<idhere>) # App Store Connect Team ID
team_id(<portalTeamId>) # Developer Portal Team ID
# For more information about the Appfile, see:
# https://docs.fastlane.tools/advanced/#appfile

96
fastlane/Fastfile Normal file
View file

@ -0,0 +1,96 @@
# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
# https://docs.fastlane.tools/actions
#
# For a list of all available plugins, check out
#
# https://docs.fastlane.tools/plugins/available-plugins
#
# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane
default_platform(:ios)
platform :ios do
before_all do
setup_circle_ci
end
desc "Install UAT certificate (in CI)"
lane :import_uat_distribution_certificate do
import_certificate(
certificate_path: "Distribution_UAT.p12",
certificate_password: ENV["DISTRIBUTION_UAT_P12_PASSWORD"] || "default",
keychain_name: ENV["MATCH_KEYCHAIN_NAME"],
keychain_password: ENV["MATCH_KEYCHAIN_PASSWORD"],
)
install_provisioning_profile(path: "~/Library/MobileDevice/Provisioning\ Profiles/AppStore_UAT.mobileprovision")
end
desc "Install PROD certificate (in CI)"
lane :import_distribution_certificate do
import_certificate(
certificate_path: "Distribution.p12",
certificate_password: ENV["DISTRIBUTION_P12_PASSWORD"] || "default",
keychain_name: ENV["MATCH_KEYCHAIN_NAME"],
keychain_password: ENV["MATCH_KEYCHAIN_PASSWORD"],
)
install_provisioning_profile(path: "~/Library/MobileDevice/Provisioning\ Profiles/AppStore.mobileprovision")
end
desc "Push a new UAT build to TestFlight"
lane :beta do
# To increment build number is recommended to use api_key
# increment_build_number(
# build_number: app_store_build_number + 1,
# xcodeproj: "CovidSafe.xcodeproj"
# )
gym(workspace: "CovidSafe.xcworkspace",
scheme: "covid-staging",
export_options: {
method: "app-store",
provisioningProfiles: {
"au.gov.health.covidsafe.uat" => "CovidSafe UAT"
}
},
configuration: "Release")
upload_to_testflight(apple_id: ENV["APPLE_ID_UAT"],
skip_submission: true,
skip_waiting_for_build_processing: true)
end
desc "Push a new PROD build to TestFlight"
lane :release do
# To increment build number is recommended to use api_key
# increment_build_number(
# build_number: app_store_build_number + 1,
# xcodeproj: "CovidSafe.xcodeproj"
# )
gym(workspace: "CovidSafe.xcworkspace",
scheme: "covid-production",
export_options: {
method: "app-store",
provisioningProfiles: {
"au.gov.health.covidsafe" => "COVIDSafe"
}
},
configuration: "Release")
upload_to_testflight(apple_id: ENV["APPLE_ID"],
skip_submission: true,
skip_waiting_for_build_processing: true)
end
end

24
fastlane/README.md Normal file
View file

@ -0,0 +1,24 @@
fastlane documentation
================
# Installation
Make sure you have the latest version of the Xcode command line tools installed:
```
xcode-select --install
```
Install _fastlane_ using
```
[sudo] gem install fastlane -NV
```
or alternatively using `brew install fastlane`
# Available Actions
## iOS
- import_uat_distribution_certificate: This lane will decode and install the needed provisioning profile and signing certificate for the UAT build.
- import_distribution_certificate: This lane will decode and install the needed provisioning profile and signing certificate for the PROD build.
- beta: This lane will build and upload the UAT build to testflight
- release: This lane will build and upload the PROD build to testflight