├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── AWSCognito.podspec ├── AWSCognito.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── AWSCognito.xcscheme ├── AWSCognito.xcworkspace └── contents.xcworkspacedata ├── AWSCognitoSync.podspec ├── AWSCognitoSyncTests ├── AWSCognitoClientTest.m ├── AWSCognitoSyncServiceTests.m ├── AWSCognitoTests-Prefix.pch ├── AWSGeneralCognitoSyncTests.m ├── AmazonCognitoSqliteManagerTests.m ├── CognitoTestUtils.h ├── CognitoTestUtils.m └── Info.plist ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Cognito ├── AWSCognito.h ├── AWSCognitoConflict.h ├── AWSCognitoConflict.m ├── AWSCognitoDataset.h ├── AWSCognitoDataset.m ├── AWSCognitoHandlers.h ├── AWSCognitoRecord.h ├── AWSCognitoRecord.m ├── AWSCognitoService.h ├── AWSCognitoService.m ├── Fabric │ ├── FABAttributes.h │ ├── FABKitProtocol.h │ ├── Fabric+FABKits.h │ └── Fabric.h ├── Internal │ ├── AWSCognitoConflict_Internal.h │ ├── AWSCognitoConstants.h │ ├── AWSCognitoConstants.m │ ├── AWSCognitoDataset_Internal.h │ ├── AWSCognitoRecord_Internal.h │ ├── AWSCognitoSQLiteManager.h │ ├── AWSCognitoSQLiteManager.m │ ├── AWSCognitoUtil.h │ └── AWSCognitoUtil.m └── module.modulemap ├── CognitoSync ├── AWSCognitoSync.h ├── AWSCognitoSyncModel.h ├── AWSCognitoSyncModel.m ├── AWSCognitoSyncResources.h ├── AWSCognitoSyncResources.m ├── AWSCognitoSyncService.h └── AWSCognitoSyncService.m ├── LICENSE ├── NOTICE ├── README.md └── Rakefile /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # This repo is deprecated. Please use https://github.com/aws/aws-sdk-ios/ 2 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Description of changes:* 4 | 5 | 6 | By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS generated files # 2 | ###################### 3 | .DS_Store 4 | .DS_Store? 5 | ._* 6 | .Spotlight-V100 7 | .Trashes 8 | Icon? 9 | ehthumbs.db 10 | Thumbs.db 11 | src/Documentation/* 12 | src/docs/docset/* 13 | src/docs/docset-installed.txt 14 | src/aws-ios-sdk-*.zip 15 | 16 | # Xcode generated files # 17 | ###################### 18 | xcuserdata 19 | *.xccheckout 20 | 21 | # Patched code # 22 | ###################### 23 | *.bak 24 | 25 | # Built assets # 26 | ###################### 27 | build 28 | AWS*.framework 29 | 30 | # Stuff that can't be committed # 31 | ###################### 32 | credentials.json 33 | Pods 34 | Podfile.lock 35 | -------------------------------------------------------------------------------- /AWSCognito.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = 'AWSCognito' 4 | s.version = '2.3.6' 5 | s.summary = 'Amazon Cognito SDK for iOS' 6 | 7 | s.description = 'Amazon Cognito offers multi device data synchronization with offline access' 8 | 9 | s.homepage = 'http://aws.amazon.com/cognito' 10 | s.license = 'Amazon Software License' 11 | s.author = { 'Amazon Web Services' => 'amazonwebservices' } 12 | s.platform = :ios, '7.0' 13 | s.source = { :git => 'https://github.com/aws/amazon-cognito-ios.git', 14 | :tag => s.version} 15 | s.requires_arc = true 16 | s.library = 'sqlite3' 17 | s.dependency 'AWSCore', '2.3.6' 18 | 19 | s.source_files = 'CognitoSync/*.{h,m}', 'Cognito/*.{h,m}', 'Cognito/**/*.{h,m}' 20 | s.public_header_files = 'Cognito/*.h', 'CognitoSync/*.h' 21 | s.private_header_files = 'Cognito/Fabric/*.h', 'Cognito/Internal/*.h' 22 | end 23 | -------------------------------------------------------------------------------- /AWSCognito.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AWSCognito.xcodeproj/xcshareddata/xcschemes/AWSCognito.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 93 | 99 | 100 | 101 | 102 | 103 | 104 | 110 | 111 | 117 | 118 | 119 | 120 | 122 | 123 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /AWSCognito.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /AWSCognitoSync.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = 'AWSCognitoSync' 4 | s.version = '2.3.6' 5 | s.summary = 'Amazon Cognito SDK for iOS' 6 | 7 | s.description = 'Amazon Cognito offers multi device data synchronization with offline access' 8 | 9 | s.homepage = 'http://aws.amazon.com/cognito' 10 | s.license = 'Amazon Software License' 11 | s.author = { 'Amazon Web Services' => 'amazonwebservices' } 12 | s.platform = :ios, '7.0' 13 | s.source = { :git => 'https://github.com/aws/amazon-cognito-ios.git', 14 | :tag => s.version} 15 | s.requires_arc = true 16 | s.library = 'sqlite3' 17 | s.dependency 'AWSCognito', '2.3.6' 18 | 19 | s.deprecated = true 20 | s.deprecated_in_favor_of = 'AWSCognito' 21 | end 22 | -------------------------------------------------------------------------------- /AWSCognitoSyncTests/AWSCognitoSyncServiceTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #if AWS_TEST_COGNITO_SYNC_SERVICE 17 | 18 | #import 19 | #import 20 | #import 21 | #import "AWSCognito.h" 22 | #import "CognitoTestUtils.h" 23 | 24 | @interface AWSCognitoSyncTests : XCTestCase 25 | 26 | @end 27 | 28 | NSString *_identityId; 29 | 30 | @implementation AWSCognitoSyncTests 31 | 32 | + (void)setUp { 33 | [CognitoTestUtils createIdentityPool]; 34 | 35 | AWSCognitoCredentialsProvider *provider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 36 | identityId:nil 37 | accountId:[CognitoTestUtils accountId] 38 | identityPoolId:[CognitoTestUtils identityPoolId] 39 | unauthRoleArn:[CognitoTestUtils unauthRoleArn] 40 | authRoleArn:[CognitoTestUtils authRoleArn] 41 | logins:nil]; 42 | [[provider refresh] waitUntilFinished]; 43 | _identityId = provider.identityId; 44 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:provider]; 45 | 46 | [AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration; 47 | // Can't use default because default config was probably written earlier 48 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:@"AWSCognitoSyncTests"]; 49 | } 50 | 51 | + (void)tearDown { 52 | [CognitoTestUtils deleteIdentityPool]; 53 | } 54 | 55 | - (void)testExample { 56 | 57 | AWSCognitoSyncListRecordsRequest *request = [AWSCognitoSyncListRecordsRequest new]; 58 | request.datasetName = @"mydataset"; 59 | request.identityPoolId = [CognitoTestUtils identityPoolId]; 60 | request.identityId = _identityId; 61 | 62 | [[[[AWSCognitoSync CognitoSyncForKey:@"AWSCognitoSyncTests"] listRecords:request] continueWithBlock:^id(AWSTask *task) { 63 | AWSCognitoSyncListRecordsResponse *response = task.result; 64 | XCTAssertNotNil(response, @"response should not be nil"); 65 | return nil; 66 | }] waitUntilFinished]; 67 | } 68 | 69 | - (void)testExampleFailed { 70 | AWSStaticCredentialsProvider *provider = [[AWSStaticCredentialsProvider alloc] initWithCredentialsFilename:@"credentials"]; 71 | AWSServiceConfiguration * configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:provider]; 72 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:@"testExampleFailed"]; 73 | AWSCognitoSync *client = [AWSCognitoSync CognitoSyncForKey:@"testExampleFailed"]; 74 | 75 | AWSCognitoSyncDescribeDatasetRequest *request = [AWSCognitoSyncDescribeDatasetRequest new]; 76 | request.datasetName = @"wrongname"; //Wrong DatasetName 77 | request.identityPoolId = [CognitoTestUtils identityPoolId]; 78 | request.identityId = _identityId; 79 | 80 | [[[client describeDataset:request] continueWithBlock:^id(AWSTask *task) { 81 | XCTAssertNotNil(task.error,@"expected error but got nil"); 82 | XCTAssertEqual(AWSCognitoSyncErrorResourceNotFound, task.error.code, @"expected AWSCognitoSyncErrorResourceNotFound Error but got: %ld",(long)task.error.code); 83 | 84 | return nil; 85 | }] waitUntilFinished]; 86 | 87 | [AWSCognitoSync removeCognitoSyncForKey:@"testExampleFailed"]; 88 | } 89 | 90 | - (void)testSyncSessionToken { 91 | // Do any initial list to get a token 92 | AWSCognitoSyncListRecordsRequest *listRequest = [AWSCognitoSyncListRecordsRequest new]; 93 | listRequest.datasetName = @"tokentest"; 94 | listRequest.identityPoolId = [CognitoTestUtils identityPoolId]; 95 | listRequest.identityId = _identityId; 96 | listRequest.lastSyncCount = @0; 97 | 98 | __block NSString *_sessionToken = nil; 99 | [[[[AWSCognitoSync CognitoSyncForKey:@"AWSCognitoSyncTests"] listRecords:listRequest] continueWithBlock:^id(AWSTask *task) { 100 | XCTAssertNil(task.error, @"Error: [%@].", task.error); 101 | AWSCognitoSyncListRecordsResponse *result = task.result; 102 | _sessionToken = result.syncSessionToken; 103 | return nil; 104 | }] waitUntilFinished]; 105 | 106 | XCTAssertNotNil(_sessionToken, @"Couldn't get a session token"); 107 | 108 | // Retry the list with the token 109 | listRequest.syncSessionToken = _sessionToken; 110 | 111 | [[[[AWSCognitoSync CognitoSyncForKey:@"AWSCognitoSyncTests"] listRecords:listRequest] continueWithBlock:^id(AWSTask *task) { 112 | XCTAssertNil(task.error, @"Error from list w/session token: %@", task.error); 113 | return nil; 114 | }] waitUntilFinished]; 115 | 116 | // Create an update request, use the token 117 | AWSCognitoSyncRecordPatch *patch = [AWSCognitoSyncRecordPatch new]; 118 | patch.key = @"tokenkey"; 119 | patch.syncCount = [NSNumber numberWithInt:0]; 120 | patch.value = @"forced"; 121 | patch.op = AWSCognitoSyncOperationReplace; 122 | 123 | AWSCognitoSyncUpdateRecordsRequest *updateRequest = [AWSCognitoSyncUpdateRecordsRequest new]; 124 | updateRequest.datasetName = @"tokentest"; 125 | updateRequest.identityPoolId = [CognitoTestUtils identityPoolId]; 126 | updateRequest.identityId = _identityId; 127 | updateRequest.syncSessionToken = _sessionToken; 128 | updateRequest.recordPatches = [NSArray arrayWithObject:patch]; 129 | 130 | [[[[AWSCognitoSync CognitoSyncForKey:@"AWSCognitoSyncTests"] updateRecords:updateRequest] continueWithBlock:^id(AWSTask *task) { 131 | XCTAssertNil(task.error, @"Error from update w/session token: %@", task.error); 132 | return nil; 133 | }] waitUntilFinished]; 134 | 135 | // Now that the token was used to push, listing again should fail 136 | [[[[AWSCognitoSync CognitoSyncForKey:@"AWSCognitoSyncTests"] listRecords:listRequest] continueWithBlock:^id(AWSTask *task) { 137 | XCTAssertNotNil(task.error, @"Should have gotten error"); 138 | return nil; 139 | }] waitUntilFinished]; 140 | } 141 | 142 | @end 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /AWSCognitoSyncTests/AWSCognitoTests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #ifndef AWSiOSSDKCognitoSync_AWSiOSSDKCognitoSyncTests_Prefix_pch 17 | #define AWSiOSSDKCognitoSync_AWSiOSSDKCognitoSyncTests_Prefix_pch 18 | 19 | #ifdef __OBJC__ 20 | #import 21 | #endif 22 | 23 | #define AWS_TEST_COGNITO_SQLITE_MANAGER 1 24 | #define AWS_TEST_COGNITO_CLIENT 1 25 | #define AWS_TEST_COGNITO_SYNC_SERVICE 1 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /AWSCognitoSyncTests/AWSGeneralCognitoSyncTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import 17 | #import 18 | #import 19 | #import "AWSTestUtility.h" 20 | #import "AWSCognitoSync.h" 21 | 22 | static id mockNetworking = nil; 23 | 24 | @interface AWSGeneralCognitoSyncTests : XCTestCase 25 | 26 | @end 27 | 28 | @implementation AWSGeneralCognitoSyncTests 29 | 30 | - (void)setUp { 31 | [super setUp]; 32 | [AWSTestUtility setupFakeCognitoCredentialsProvider]; 33 | 34 | mockNetworking = OCMClassMock([AWSNetworking class]); 35 | AWSTask *errorTask = [AWSTask taskWithError:[NSError errorWithDomain:@"OCMockExpectedNetworkingError" code:8848 userInfo:nil]]; 36 | OCMStub([mockNetworking sendRequest:[OCMArg isKindOfClass:[AWSNetworkingRequest class]]]).andReturn(errorTask); 37 | } 38 | 39 | - (void)tearDown { 40 | [super tearDown]; 41 | } 42 | 43 | - (void)testConstructors { 44 | NSString *key = @"testCognitoSyncConstructors"; 45 | XCTAssertNotNil([AWSCognitoSync defaultCognitoSync]); 46 | XCTAssertEqual([[AWSCognitoSync defaultCognitoSync] class], [AWSCognitoSync class]); 47 | XCTAssertNil([AWSCognitoSync CognitoSyncForKey:key]); 48 | 49 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionSAEast1 credentialsProvider:[AWSServiceManager defaultServiceManager].defaultServiceConfiguration.credentialsProvider]; 50 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 51 | XCTAssertNotNil([AWSCognitoSync CognitoSyncForKey:key]); 52 | XCTAssertEqual([[AWSCognitoSync CognitoSyncForKey:key] class], [AWSCognitoSync class]); 53 | XCTAssertEqual([AWSCognitoSync CognitoSyncForKey:key].configuration.regionType, AWSRegionSAEast1); 54 | 55 | [AWSCognitoSync removeCognitoSyncForKey:key]; 56 | XCTAssertNil([AWSCognitoSync CognitoSyncForKey:key]); 57 | 58 | } 59 | 60 | - (void)testBulkPublish { 61 | NSString *key = @"testBulkPublish"; 62 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 63 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 64 | 65 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 66 | XCTAssertNotNil(awsClient); 67 | XCTAssertNotNil(mockNetworking); 68 | [awsClient setValue:mockNetworking forKey:@"networking"]; 69 | [[[[AWSCognitoSync CognitoSyncForKey:key] bulkPublish:[AWSCognitoSyncBulkPublishRequest new]] continueWithBlock:^id(AWSTask *task) { 70 | XCTAssertNotNil(task.error); 71 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 72 | XCTAssertEqual(8848, task.error.code); 73 | XCTAssertNil(task.exception); 74 | XCTAssertNil(task.result); 75 | return nil; 76 | }] waitUntilFinished]; 77 | 78 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 79 | 80 | [AWSCognitoSync removeCognitoSyncForKey:key]; 81 | } 82 | 83 | - (void)testDeleteDataset { 84 | NSString *key = @"testDeleteDataset"; 85 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 86 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 87 | 88 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 89 | XCTAssertNotNil(awsClient); 90 | XCTAssertNotNil(mockNetworking); 91 | [awsClient setValue:mockNetworking forKey:@"networking"]; 92 | [[[[AWSCognitoSync CognitoSyncForKey:key] deleteDataset:[AWSCognitoSyncDeleteDatasetRequest new]] continueWithBlock:^id(AWSTask *task) { 93 | XCTAssertNotNil(task.error); 94 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 95 | XCTAssertEqual(8848, task.error.code); 96 | XCTAssertNil(task.exception); 97 | XCTAssertNil(task.result); 98 | return nil; 99 | }] waitUntilFinished]; 100 | 101 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 102 | 103 | [AWSCognitoSync removeCognitoSyncForKey:key]; 104 | } 105 | 106 | - (void)testDescribeDataset { 107 | NSString *key = @"testDescribeDataset"; 108 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 109 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 110 | 111 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 112 | XCTAssertNotNil(awsClient); 113 | XCTAssertNotNil(mockNetworking); 114 | [awsClient setValue:mockNetworking forKey:@"networking"]; 115 | [[[[AWSCognitoSync CognitoSyncForKey:key] describeDataset:[AWSCognitoSyncDescribeDatasetRequest new]] continueWithBlock:^id(AWSTask *task) { 116 | XCTAssertNotNil(task.error); 117 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 118 | XCTAssertEqual(8848, task.error.code); 119 | XCTAssertNil(task.exception); 120 | XCTAssertNil(task.result); 121 | return nil; 122 | }] waitUntilFinished]; 123 | 124 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 125 | 126 | [AWSCognitoSync removeCognitoSyncForKey:key]; 127 | } 128 | 129 | - (void)testDescribeIdentityPoolUsage { 130 | NSString *key = @"testDescribeIdentityPoolUsage"; 131 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 132 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 133 | 134 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 135 | XCTAssertNotNil(awsClient); 136 | XCTAssertNotNil(mockNetworking); 137 | [awsClient setValue:mockNetworking forKey:@"networking"]; 138 | [[[[AWSCognitoSync CognitoSyncForKey:key] describeIdentityPoolUsage:[AWSCognitoSyncDescribeIdentityPoolUsageRequest new]] continueWithBlock:^id(AWSTask *task) { 139 | XCTAssertNotNil(task.error); 140 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 141 | XCTAssertEqual(8848, task.error.code); 142 | XCTAssertNil(task.exception); 143 | XCTAssertNil(task.result); 144 | return nil; 145 | }] waitUntilFinished]; 146 | 147 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 148 | 149 | [AWSCognitoSync removeCognitoSyncForKey:key]; 150 | } 151 | 152 | - (void)testDescribeIdentityUsage { 153 | NSString *key = @"testDescribeIdentityUsage"; 154 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 155 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 156 | 157 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 158 | XCTAssertNotNil(awsClient); 159 | XCTAssertNotNil(mockNetworking); 160 | [awsClient setValue:mockNetworking forKey:@"networking"]; 161 | [[[[AWSCognitoSync CognitoSyncForKey:key] describeIdentityUsage:[AWSCognitoSyncDescribeIdentityUsageRequest new]] continueWithBlock:^id(AWSTask *task) { 162 | XCTAssertNotNil(task.error); 163 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 164 | XCTAssertEqual(8848, task.error.code); 165 | XCTAssertNil(task.exception); 166 | XCTAssertNil(task.result); 167 | return nil; 168 | }] waitUntilFinished]; 169 | 170 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 171 | 172 | [AWSCognitoSync removeCognitoSyncForKey:key]; 173 | } 174 | 175 | - (void)testGetBulkPublishDetails { 176 | NSString *key = @"testGetBulkPublishDetails"; 177 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 178 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 179 | 180 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 181 | XCTAssertNotNil(awsClient); 182 | XCTAssertNotNil(mockNetworking); 183 | [awsClient setValue:mockNetworking forKey:@"networking"]; 184 | [[[[AWSCognitoSync CognitoSyncForKey:key] getBulkPublishDetails:[AWSCognitoSyncGetBulkPublishDetailsRequest new]] continueWithBlock:^id(AWSTask *task) { 185 | XCTAssertNotNil(task.error); 186 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 187 | XCTAssertEqual(8848, task.error.code); 188 | XCTAssertNil(task.exception); 189 | XCTAssertNil(task.result); 190 | return nil; 191 | }] waitUntilFinished]; 192 | 193 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 194 | 195 | [AWSCognitoSync removeCognitoSyncForKey:key]; 196 | } 197 | 198 | - (void)testGetCognitoEvents { 199 | NSString *key = @"testGetCognitoEvents"; 200 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 201 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 202 | 203 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 204 | XCTAssertNotNil(awsClient); 205 | XCTAssertNotNil(mockNetworking); 206 | [awsClient setValue:mockNetworking forKey:@"networking"]; 207 | [[[[AWSCognitoSync CognitoSyncForKey:key] getCognitoEvents:[AWSCognitoSyncGetCognitoEventsRequest new]] continueWithBlock:^id(AWSTask *task) { 208 | XCTAssertNotNil(task.error); 209 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 210 | XCTAssertEqual(8848, task.error.code); 211 | XCTAssertNil(task.exception); 212 | XCTAssertNil(task.result); 213 | return nil; 214 | }] waitUntilFinished]; 215 | 216 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 217 | 218 | [AWSCognitoSync removeCognitoSyncForKey:key]; 219 | } 220 | 221 | - (void)testGetIdentityPoolConfiguration { 222 | NSString *key = @"testGetIdentityPoolConfiguration"; 223 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 224 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 225 | 226 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 227 | XCTAssertNotNil(awsClient); 228 | XCTAssertNotNil(mockNetworking); 229 | [awsClient setValue:mockNetworking forKey:@"networking"]; 230 | [[[[AWSCognitoSync CognitoSyncForKey:key] getIdentityPoolConfiguration:[AWSCognitoSyncGetIdentityPoolConfigurationRequest new]] continueWithBlock:^id(AWSTask *task) { 231 | XCTAssertNotNil(task.error); 232 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 233 | XCTAssertEqual(8848, task.error.code); 234 | XCTAssertNil(task.exception); 235 | XCTAssertNil(task.result); 236 | return nil; 237 | }] waitUntilFinished]; 238 | 239 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 240 | 241 | [AWSCognitoSync removeCognitoSyncForKey:key]; 242 | } 243 | 244 | - (void)testListDatasets { 245 | NSString *key = @"testListDatasets"; 246 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 247 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 248 | 249 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 250 | XCTAssertNotNil(awsClient); 251 | XCTAssertNotNil(mockNetworking); 252 | [awsClient setValue:mockNetworking forKey:@"networking"]; 253 | [[[[AWSCognitoSync CognitoSyncForKey:key] listDatasets:[AWSCognitoSyncListDatasetsRequest new]] continueWithBlock:^id(AWSTask *task) { 254 | XCTAssertNotNil(task.error); 255 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 256 | XCTAssertEqual(8848, task.error.code); 257 | XCTAssertNil(task.exception); 258 | XCTAssertNil(task.result); 259 | return nil; 260 | }] waitUntilFinished]; 261 | 262 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 263 | 264 | [AWSCognitoSync removeCognitoSyncForKey:key]; 265 | } 266 | 267 | - (void)testListIdentityPoolUsage { 268 | NSString *key = @"testListIdentityPoolUsage"; 269 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 270 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 271 | 272 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 273 | XCTAssertNotNil(awsClient); 274 | XCTAssertNotNil(mockNetworking); 275 | [awsClient setValue:mockNetworking forKey:@"networking"]; 276 | [[[[AWSCognitoSync CognitoSyncForKey:key] listIdentityPoolUsage:[AWSCognitoSyncListIdentityPoolUsageRequest new]] continueWithBlock:^id(AWSTask *task) { 277 | XCTAssertNotNil(task.error); 278 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 279 | XCTAssertEqual(8848, task.error.code); 280 | XCTAssertNil(task.exception); 281 | XCTAssertNil(task.result); 282 | return nil; 283 | }] waitUntilFinished]; 284 | 285 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 286 | 287 | [AWSCognitoSync removeCognitoSyncForKey:key]; 288 | } 289 | 290 | - (void)testListRecords { 291 | NSString *key = @"testListRecords"; 292 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 293 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 294 | 295 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 296 | XCTAssertNotNil(awsClient); 297 | XCTAssertNotNil(mockNetworking); 298 | [awsClient setValue:mockNetworking forKey:@"networking"]; 299 | [[[[AWSCognitoSync CognitoSyncForKey:key] listRecords:[AWSCognitoSyncListRecordsRequest new]] continueWithBlock:^id(AWSTask *task) { 300 | XCTAssertNotNil(task.error); 301 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 302 | XCTAssertEqual(8848, task.error.code); 303 | XCTAssertNil(task.exception); 304 | XCTAssertNil(task.result); 305 | return nil; 306 | }] waitUntilFinished]; 307 | 308 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 309 | 310 | [AWSCognitoSync removeCognitoSyncForKey:key]; 311 | } 312 | 313 | - (void)testRegisterDevice { 314 | NSString *key = @"testRegisterDevice"; 315 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 316 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 317 | 318 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 319 | XCTAssertNotNil(awsClient); 320 | XCTAssertNotNil(mockNetworking); 321 | [awsClient setValue:mockNetworking forKey:@"networking"]; 322 | [[[[AWSCognitoSync CognitoSyncForKey:key] registerDevice:[AWSCognitoSyncRegisterDeviceRequest new]] continueWithBlock:^id(AWSTask *task) { 323 | XCTAssertNotNil(task.error); 324 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 325 | XCTAssertEqual(8848, task.error.code); 326 | XCTAssertNil(task.exception); 327 | XCTAssertNil(task.result); 328 | return nil; 329 | }] waitUntilFinished]; 330 | 331 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 332 | 333 | [AWSCognitoSync removeCognitoSyncForKey:key]; 334 | } 335 | 336 | - (void)testSetCognitoEvents { 337 | NSString *key = @"testSetCognitoEvents"; 338 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 339 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 340 | 341 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 342 | XCTAssertNotNil(awsClient); 343 | XCTAssertNotNil(mockNetworking); 344 | [awsClient setValue:mockNetworking forKey:@"networking"]; 345 | [[[[AWSCognitoSync CognitoSyncForKey:key] setCognitoEvents:[AWSCognitoSyncSetCognitoEventsRequest new]] continueWithBlock:^id(AWSTask *task) { 346 | XCTAssertNotNil(task.error); 347 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 348 | XCTAssertEqual(8848, task.error.code); 349 | XCTAssertNil(task.exception); 350 | XCTAssertNil(task.result); 351 | return nil; 352 | }] waitUntilFinished]; 353 | 354 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 355 | 356 | [AWSCognitoSync removeCognitoSyncForKey:key]; 357 | } 358 | 359 | - (void)testSetIdentityPoolConfiguration { 360 | NSString *key = @"testSetIdentityPoolConfiguration"; 361 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 362 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 363 | 364 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 365 | XCTAssertNotNil(awsClient); 366 | XCTAssertNotNil(mockNetworking); 367 | [awsClient setValue:mockNetworking forKey:@"networking"]; 368 | [[[[AWSCognitoSync CognitoSyncForKey:key] setIdentityPoolConfiguration:[AWSCognitoSyncSetIdentityPoolConfigurationRequest new]] continueWithBlock:^id(AWSTask *task) { 369 | XCTAssertNotNil(task.error); 370 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 371 | XCTAssertEqual(8848, task.error.code); 372 | XCTAssertNil(task.exception); 373 | XCTAssertNil(task.result); 374 | return nil; 375 | }] waitUntilFinished]; 376 | 377 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 378 | 379 | [AWSCognitoSync removeCognitoSyncForKey:key]; 380 | } 381 | 382 | - (void)testSubscribeToDataset { 383 | NSString *key = @"testSubscribeToDataset"; 384 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 385 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 386 | 387 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 388 | XCTAssertNotNil(awsClient); 389 | XCTAssertNotNil(mockNetworking); 390 | [awsClient setValue:mockNetworking forKey:@"networking"]; 391 | [[[[AWSCognitoSync CognitoSyncForKey:key] subscribeToDataset:[AWSCognitoSyncSubscribeToDatasetRequest new]] continueWithBlock:^id(AWSTask *task) { 392 | XCTAssertNotNil(task.error); 393 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 394 | XCTAssertEqual(8848, task.error.code); 395 | XCTAssertNil(task.exception); 396 | XCTAssertNil(task.result); 397 | return nil; 398 | }] waitUntilFinished]; 399 | 400 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 401 | 402 | [AWSCognitoSync removeCognitoSyncForKey:key]; 403 | } 404 | 405 | - (void)testUnsubscribeFromDataset { 406 | NSString *key = @"testUnsubscribeFromDataset"; 407 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 408 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 409 | 410 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 411 | XCTAssertNotNil(awsClient); 412 | XCTAssertNotNil(mockNetworking); 413 | [awsClient setValue:mockNetworking forKey:@"networking"]; 414 | [[[[AWSCognitoSync CognitoSyncForKey:key] unsubscribeFromDataset:[AWSCognitoSyncUnsubscribeFromDatasetRequest new]] continueWithBlock:^id(AWSTask *task) { 415 | XCTAssertNotNil(task.error); 416 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 417 | XCTAssertEqual(8848, task.error.code); 418 | XCTAssertNil(task.exception); 419 | XCTAssertNil(task.result); 420 | return nil; 421 | }] waitUntilFinished]; 422 | 423 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 424 | 425 | [AWSCognitoSync removeCognitoSyncForKey:key]; 426 | } 427 | 428 | - (void)testUpdateRecords { 429 | NSString *key = @"testUpdateRecords"; 430 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; 431 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:key]; 432 | 433 | AWSCognitoSync *awsClient = [AWSCognitoSync CognitoSyncForKey:key]; 434 | XCTAssertNotNil(awsClient); 435 | XCTAssertNotNil(mockNetworking); 436 | [awsClient setValue:mockNetworking forKey:@"networking"]; 437 | [[[[AWSCognitoSync CognitoSyncForKey:key] updateRecords:[AWSCognitoSyncUpdateRecordsRequest new]] continueWithBlock:^id(AWSTask *task) { 438 | XCTAssertNotNil(task.error); 439 | XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); 440 | XCTAssertEqual(8848, task.error.code); 441 | XCTAssertNil(task.exception); 442 | XCTAssertNil(task.result); 443 | return nil; 444 | }] waitUntilFinished]; 445 | 446 | OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); 447 | 448 | [AWSCognitoSync removeCognitoSyncForKey:key]; 449 | } 450 | 451 | @end 452 | -------------------------------------------------------------------------------- /AWSCognitoSyncTests/AmazonCognitoSqliteManagerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #if AWS_TEST_COGNITO_SQLITE_MANAGER 17 | 18 | #import 19 | #import "AWSCognitoSQLiteManager.h" 20 | #import 21 | #import 22 | #import "AWSCognito.h" 23 | #import "AWSCognitoConflict_Internal.h" 24 | 25 | @interface AmazonCognitoSqliteManagerTests : XCTestCase 26 | 27 | @property (nonatomic, strong) AWSCognito *client; 28 | @property (nonatomic, strong) AWSCognitoSQLiteManager *manager; 29 | 30 | @end 31 | 32 | NSString *const TestId1 = @"originalId"; 33 | NSString *const TestId2 = @"newId"; 34 | NSString *const DeviceId = @"tester"; 35 | NSString *const DatasetName = @"testDataset"; 36 | 37 | @implementation AmazonCognitoSqliteManagerTests 38 | 39 | #pragma mark - Test Setups 40 | 41 | - (void)setUp { 42 | [super setUp]; 43 | self.manager = [[AWSCognitoSQLiteManager alloc] initWithIdentityId:TestId1 deviceId:DeviceId]; 44 | [self.manager initializeDatasetTables:DatasetName]; 45 | } 46 | 47 | - (void)tearDown { 48 | [super tearDown]; 49 | [self.manager deleteSQLiteDatabase]; 50 | } 51 | 52 | - (void)testLastSyncCount { 53 | NSNumber *syncCount = [self.manager lastSyncCount:DatasetName]; 54 | XCTAssertTrue([syncCount intValue] == 0, @"Last sync count didn't match"); 55 | [self.manager updateLastSyncCount:DatasetName syncCount:[NSNumber numberWithInt:2] lastModifiedBy:nil]; 56 | syncCount = [self.manager lastSyncCount:DatasetName]; 57 | XCTAssertTrue([syncCount intValue] == 2, @"Last sync count didn't match"); 58 | } 59 | 60 | - (void)testPutAndGet { 61 | NSError * error; 62 | XCTAssertEqualObjects([NSNumber numberWithInt:0],[self.manager numRecords:DatasetName]); 63 | AWSCognitoRecordValue* on = [[AWSCognitoRecordValue alloc] initWithString:@"on"]; 64 | AWSCognitoRecord* record = [[AWSCognitoRecord alloc] initWithId:@"wifi" data:on]; 65 | [self.manager putRecord:record datasetName:DatasetName error:&error]; 66 | XCTAssertNil(error, @"Error on put [%@]", error); 67 | XCTAssertEqualObjects([NSNumber numberWithInt:1],[self.manager numRecords:DatasetName]); 68 | AWSCognitoRecord* result = [self.manager getRecordById:record.recordId datasetName:DatasetName error:&error]; 69 | XCTAssertNil(error, @"Error on get [%@]", error); 70 | XCTAssertEqualObjects(@"on", result.data.string); 71 | AWSCognitoRecordValue* off = [[AWSCognitoRecordValue alloc] initWithString:@"off"]; 72 | record.data = off; 73 | [self.manager putRecord:record datasetName:DatasetName error:&error]; 74 | XCTAssertNil(error, @"Error on put [%@]", error); 75 | result = [self.manager getRecordById:record.recordId datasetName:DatasetName error:&error]; 76 | XCTAssertNil(error, @"Error on get [%@]", error); 77 | XCTAssertEqualObjects(@"off", result.data.string); 78 | } 79 | 80 | - (void)testGetDirty { 81 | NSError * error; 82 | AWSCognitoRecordValue* on = [[AWSCognitoRecordValue alloc] initWithString:@"on"]; 83 | AWSCognitoRecord* record = [[AWSCognitoRecord alloc] initWithId:@"wifi" data:on]; 84 | [self.manager putRecord:record datasetName:DatasetName error:&error]; 85 | AWSCognitoRecord* result = [self.manager getRecordById:record.recordId datasetName:DatasetName error:&error]; 86 | XCTAssertEqualObjects(@"on", result.data.string); 87 | AWSCognitoRecordValue* off = [[AWSCognitoRecordValue alloc] initWithString:@"off"]; 88 | record.data = off; 89 | [self.manager putRecord:record datasetName:DatasetName error:&error]; 90 | result = [self.manager getRecordById:record.recordId datasetName:DatasetName error:&error]; 91 | XCTAssertEqualObjects(@"off", result.data.string); 92 | NSArray * records = [self.manager allRecords:DatasetName]; 93 | XCTAssertEqual(1,[records count]); 94 | } 95 | 96 | - (void)testDeleteAll { 97 | NSError * error; 98 | 99 | // populate some data 100 | AWSCognitoRecordValue* on = [[AWSCognitoRecordValue alloc] initWithString:@"on"]; 101 | AWSCognitoRecord* record = [[AWSCognitoRecord alloc] initWithId:@"wifi" data:on]; 102 | [self.manager putRecord:record datasetName:DatasetName error:&error]; 103 | [self.manager updateLastSyncCount:DatasetName syncCount:[NSNumber numberWithInt:1] lastModifiedBy:@"me"]; 104 | 105 | // check data 106 | NSArray *datasets = [self.manager getDatasets:&error]; 107 | XCTAssertTrue([datasets count] != 0, @"No datasets found"); 108 | NSArray *records = [self.manager allRecords:DatasetName]; 109 | XCTAssertTrue([records count] != 0, @"No records found"); 110 | 111 | [self.manager deleteAllData]; 112 | 113 | // check that data is gone 114 | datasets = [self.manager getDatasets:&error]; 115 | XCTAssertTrue([datasets count] == 0, @"Datasets left behind"); 116 | records = [self.manager allRecords:DatasetName]; 117 | XCTAssertTrue([records count] == 0, @"Records left behind"); 118 | } 119 | 120 | - (void)testDelete { 121 | NSError * error; 122 | 123 | // populate some data 124 | AWSCognitoRecordValue* on = [[AWSCognitoRecordValue alloc] initWithString:@"on"]; 125 | AWSCognitoRecord* record = [[AWSCognitoRecord alloc] initWithId:@"wifi" data:on]; 126 | [self.manager putRecord:record datasetName:DatasetName error:&error]; 127 | [self.manager updateLastSyncCount:DatasetName syncCount:[NSNumber numberWithInt:1] lastModifiedBy:@"me"]; 128 | 129 | // check data 130 | NSArray *datasets = [self.manager getDatasets:&error]; 131 | XCTAssertTrue([datasets count] != 0, @"No datasets found"); 132 | NSArray *records = [self.manager allRecords:DatasetName]; 133 | XCTAssertTrue([records count] != 0, @"No records found"); 134 | NSUInteger curCount = [records count]; 135 | 136 | [self.manager deleteDataset:DatasetName error:&error]; 137 | XCTAssertNil(error, @"Error on deleteDataset [%@]", error); 138 | [self.manager deleteMetadata:DatasetName error:&error]; 139 | XCTAssertNil(error, @"Error on deleteMetadata [%@]", error); 140 | 141 | // check that data is gone 142 | datasets = [self.manager getDatasets:&error]; 143 | XCTAssertTrue([datasets count] == curCount-1, @"Metadata left behind"); 144 | records = [self.manager allRecords:DatasetName]; 145 | XCTAssertTrue([records count] == 0, @"Records left behind"); 146 | } 147 | 148 | - (void)testReparent { 149 | NSError * error; 150 | 151 | // simulate an identity provider that is not initialized 152 | AWSCognitoSQLiteManager *managerForOther = [[AWSCognitoSQLiteManager alloc] initWithIdentityId:TestId2 deviceId:DeviceId]; 153 | [managerForOther initializeDatasetTables:DatasetName]; 154 | 155 | // populate some data 156 | AWSCognitoRecordValue* on = [[AWSCognitoRecordValue alloc] initWithString:@"on"]; 157 | AWSCognitoRecord* record = [[AWSCognitoRecord alloc] initWithId:@"wifi" data:on]; 158 | [managerForOther putRecord:record datasetName:DatasetName error:&error]; 159 | 160 | // reparent it 161 | [managerForOther reparentDatasets:TestId2 withNewId:TestId1 error:&error]; 162 | XCTAssertNil(error, @"Error on reparent [%@]", error); 163 | 164 | // check that the old id can't see them 165 | NSArray *datasets = [managerForOther getDatasets:&error]; 166 | XCTAssertTrue([datasets count] == 0, @"Datasets left behind"); 167 | NSArray *records = [managerForOther allRecords:DatasetName]; 168 | XCTAssertTrue([records count] == 0, @"Records left behind"); 169 | 170 | // check that the new id can see them 171 | datasets = [self.manager getDatasets:&error]; 172 | XCTAssertTrue([datasets count] != 0, @"No datasets found"); 173 | records = [self.manager allRecords:[NSString stringWithFormat:@"%@.%@", DatasetName, TestId2]]; 174 | XCTAssertTrue([records count] != 0, @"No records found"); 175 | } 176 | 177 | - (void)testReparentFromUnknown { 178 | NSError * error; 179 | NSString *myDatasetName = @"reparentfromunknown"; 180 | 181 | // simulate an identity provider that is not initialized 182 | AWSCognitoSQLiteManager *managerForUnknown = [[AWSCognitoSQLiteManager alloc] initWithIdentityId:nil deviceId:DeviceId]; 183 | [managerForUnknown initializeDatasetTables:myDatasetName]; 184 | 185 | // populate some data 186 | AWSCognitoRecordValue* on = [[AWSCognitoRecordValue alloc] initWithString:@"on"]; 187 | AWSCognitoRecord* record = [[AWSCognitoRecord alloc] initWithId:@"wifi" data:on]; 188 | [managerForUnknown putRecord:record datasetName:myDatasetName error:&error]; 189 | 190 | // reparent it 191 | [managerForUnknown reparentDatasets:nil withNewId:TestId1 error:&error]; 192 | XCTAssertNil(error, @"Error on reparent [%@]", error); 193 | 194 | // check that the old id can't see them 195 | NSArray *datasets = [managerForUnknown getDatasets:&error]; 196 | XCTAssertTrue([datasets count] == 0, @"Datasets left behind"); 197 | NSArray *records = [managerForUnknown allRecords:myDatasetName]; 198 | XCTAssertTrue([records count] == 0, @"Records left behind"); 199 | 200 | // check that the new id can see them 201 | datasets = [self.manager getDatasets:&error]; 202 | XCTAssertTrue([datasets count] != 0, @"No datasets found"); 203 | records = [self.manager allRecords:myDatasetName]; 204 | XCTAssertTrue([records count] != 0, @"No records found"); 205 | } 206 | 207 | - (void)testReset { 208 | NSError * error; 209 | 210 | // populate some data 211 | NSMutableArray *records = [NSMutableArray arrayWithCapacity:2]; 212 | AWSCognitoRecordValue* on = [[AWSCognitoRecordValue alloc] initWithString:@"on"]; 213 | AWSCognitoRecord* record = [[AWSCognitoRecord alloc] initWithId:@"wifi" data:on]; 214 | record.lastModifiedBy = @"me"; 215 | record.syncCount = 1; 216 | [records addObject:[[AWSCognitoRecordTuple alloc] initWithLocalRecord:nil remoteRecord:record]]; 217 | record = [[AWSCognitoRecord alloc] initWithId:@"rememberme" data:on]; 218 | record.syncCount = 2; 219 | record.lastModifiedBy = @"me"; 220 | [records addObject:[[AWSCognitoRecordTuple alloc] initWithLocalRecord:nil remoteRecord:record]]; 221 | [self.manager updateLocalRecordMetadata:DatasetName records:records error:&error]; 222 | [self.manager updateLastSyncCount:DatasetName syncCount:[NSNumber numberWithInt:2] lastModifiedBy:@"me"]; 223 | 224 | 225 | // reset the sync counts 226 | XCTAssertTrue([self.manager resetSyncCount:DatasetName error:&error], @"reset returned false"); 227 | XCTAssertNil(error, @"Got an error on reset"); 228 | 229 | NSNumber *lastSyncCount = [self.manager lastSyncCount:DatasetName]; 230 | XCTAssertTrue([lastSyncCount intValue] == 0, @"Last sync count not reset"); 231 | 232 | NSArray *resetRecords = [self.manager allRecords:DatasetName]; 233 | for (AWSCognitoRecord* reset in resetRecords) { 234 | XCTAssertTrue(reset.dirty, @"record should be dirty"); 235 | XCTAssertTrue(reset.syncCount == 0, @"record sync count not reset"); 236 | } 237 | } 238 | @end 239 | 240 | #endif 241 | -------------------------------------------------------------------------------- /AWSCognitoSyncTests/CognitoTestUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import 17 | #import 18 | 19 | @interface CognitoTestUtils : NSObject 20 | 21 | + (void)createFBAccount; 22 | + (void)createIdentityPool; 23 | + (void)deleteFBAccount; 24 | + (void)deleteIdentityPool; 25 | + (NSString *) accountId; 26 | + (NSString *) unauthRoleArn; 27 | + (NSString *) authRoleArn; 28 | + (NSString *) identityPoolId; 29 | + (NSString *) facebookToken; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /AWSCognitoSyncTests/CognitoTestUtils.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import "CognitoTestUtils.h" 17 | #import 18 | 19 | NSString * AWSCognitoClientTestsAccountID = nil; 20 | NSString * AWSCognitoClientTestsFacebookAppID = nil; 21 | NSString * AWSCognitoClientTestsFacebookAppSecret = nil; 22 | NSString * AWSCognitoClientTestsUnauthRoleArn = nil; 23 | NSString * AWSCognitoClientTestsAuthRoleArn = nil; 24 | 25 | NSString *_identityPoolId = nil; 26 | NSString *_facebookToken = nil; 27 | NSString *_facebookAppToken = nil; 28 | NSString *_facebookId = nil; 29 | 30 | @implementation CognitoTestUtils 31 | 32 | + (void)loadConfig { 33 | static dispatch_once_t onceToken; 34 | dispatch_once(&onceToken, ^{ 35 | NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@"credentials" 36 | ofType:@"json"]; 37 | NSDictionary *credentialsJson = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:filePath] 38 | options:NSJSONReadingMutableContainers 39 | error:nil]; 40 | AWSCognitoClientTestsAccountID = credentialsJson[@"accountId"]; 41 | AWSCognitoClientTestsFacebookAppID = credentialsJson[@"facebookAppId"]; 42 | AWSCognitoClientTestsFacebookAppSecret = credentialsJson[@"facebookAppSecret"]; 43 | AWSCognitoClientTestsUnauthRoleArn = credentialsJson[@"unauthRoleArn"]; 44 | AWSCognitoClientTestsAuthRoleArn = credentialsJson[@"authRoleArn"]; 45 | }); 46 | } 47 | 48 | + (NSString *) accountId { 49 | [CognitoTestUtils loadConfig]; 50 | return AWSCognitoClientTestsAccountID; 51 | } 52 | 53 | + (NSString *) unauthRoleArn { 54 | [CognitoTestUtils loadConfig]; 55 | return AWSCognitoClientTestsUnauthRoleArn; 56 | } 57 | 58 | + (NSString *) authRoleArn { 59 | [CognitoTestUtils loadConfig]; 60 | return AWSCognitoClientTestsAuthRoleArn; 61 | } 62 | 63 | + (NSString *) identityPoolId { 64 | return _identityPoolId; 65 | } 66 | 67 | + (NSString *) facebookToken { 68 | return _facebookToken; 69 | } 70 | 71 | + (void)createFBAccount { 72 | [CognitoTestUtils loadConfig]; 73 | 74 | NSString *accessURI = [NSString stringWithFormat:@"https://graph.facebook.com/oauth/access_token?client_id=%@&client_secret=%@&grant_type=client_credentials", AWSCognitoClientTestsFacebookAppID, AWSCognitoClientTestsFacebookAppSecret]; 75 | 76 | /* This code uses FB's test user API 77 | See the following URL for more information 78 | https://developers.facebook.com/docs/test_users/ */ 79 | 80 | // Get the FB APP access token 81 | NSString *raw_response = [NSString stringWithContentsOfURL:[NSURL URLWithString:accessURI] encoding:NSUTF8StringEncoding error:nil]; 82 | NSRange startOfToken = [raw_response rangeOfString:@"="]; 83 | // Strip the 'access_token=' so we can easily encode result 84 | _facebookAppToken = [[raw_response substringFromIndex:startOfToken.location + 1] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 85 | 86 | // Add a new test user, the result contains an access key we can use to test assume role 87 | NSString *addUserURI = [NSString stringWithFormat:@"https://graph.facebook.com/%@/accounts/test-users?installed=true&name=Foo%%20Bar&locale=en_US&permissions=read_stream&method=post&access_token=%@", AWSCognitoClientTestsFacebookAppID, _facebookAppToken]; 88 | 89 | NSString *newUser = [NSString stringWithContentsOfURL:[NSURL URLWithString:addUserURI] encoding:NSASCIIStringEncoding error:nil]; 90 | NSDictionary *user = [NSJSONSerialization JSONObjectWithData: [newUser dataUsingEncoding:NSUTF8StringEncoding] 91 | options: NSJSONReadingMutableContainers 92 | error: nil]; 93 | 94 | _facebookToken = [user objectForKey:@"access_token"]; 95 | _facebookId = [user objectForKey:@"id"]; 96 | } 97 | 98 | + (void)deleteFBAccount { 99 | NSString *deleteURI = [NSString stringWithFormat:@"https://graph.facebook.com/%@?method=delete&access_token=%@", _facebookId, [_facebookAppToken stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; 100 | [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:deleteURI]] 101 | returningResponse:nil 102 | error:nil]; 103 | } 104 | 105 | + (void)createIdentityPool { 106 | [CognitoTestUtils loadConfig]; 107 | 108 | AWSStaticCredentialsProvider *credentialsProvider = [[AWSStaticCredentialsProvider alloc] initWithCredentialsFilename:@"credentials"]; 109 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 110 | credentialsProvider:credentialsProvider]; 111 | [AWSCognitoIdentity registerCognitoIdentityWithConfiguration:configuration forKey:@"createIdentityPool"]; 112 | AWSCognitoIdentity *cib = [AWSCognitoIdentity CognitoIdentityForKey:@"createIdentityPool"]; 113 | 114 | AWSCognitoIdentityCreateIdentityPoolInput *createPoolForAuthProvider = [AWSCognitoIdentityCreateIdentityPoolInput new]; 115 | createPoolForAuthProvider.identityPoolName = @"CognitoSynciOSTests"; 116 | createPoolForAuthProvider.allowUnauthenticatedIdentities = @YES; 117 | createPoolForAuthProvider.supportedLoginProviders = @{@"graph.facebook.com" : AWSCognitoClientTestsFacebookAppID}; 118 | 119 | [[[cib createIdentityPool:createPoolForAuthProvider] continueWithSuccessBlock:^id(AWSTask *task) { 120 | AWSCognitoIdentityIdentityPool *identityPool = task.result; 121 | _identityPoolId = identityPool.identityPoolId; 122 | 123 | AWSCognitoIdentitySetIdentityPoolRolesInput *setRoles = [AWSCognitoIdentitySetIdentityPoolRolesInput new]; 124 | setRoles.roles = @{ @"unauthenticated": AWSCognitoClientTestsUnauthRoleArn, 125 | @"authenticated": AWSCognitoClientTestsAuthRoleArn}; 126 | setRoles.identityPoolId = _identityPoolId; 127 | 128 | return [cib setIdentityPoolRoles:setRoles]; 129 | }] waitUntilFinished]; 130 | 131 | [AWSCognitoIdentity removeCognitoIdentityForKey:@"createIdentityPool"]; 132 | 133 | [NSThread sleepForTimeInterval:20]; 134 | } 135 | 136 | + (void)deleteIdentityPool { 137 | AWSStaticCredentialsProvider *credentialsProvider = [[AWSStaticCredentialsProvider alloc] initWithCredentialsFilename:@"credentials"]; 138 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 139 | credentialsProvider:credentialsProvider]; 140 | [AWSCognitoIdentity registerCognitoIdentityWithConfiguration:configuration forKey:@"deleteIdentityPool"]; 141 | AWSCognitoIdentity *cib = [AWSCognitoIdentity CognitoIdentityForKey:@"deleteIdentityPool"]; 142 | 143 | AWSCognitoIdentityDeleteIdentityPoolInput *deletePoolForAuth = [AWSCognitoIdentityDeleteIdentityPoolInput new]; 144 | deletePoolForAuth.identityPoolId = _identityPoolId; 145 | [[cib deleteIdentityPool:deletePoolForAuth] waitUntilFinished]; 146 | 147 | [AWSCognitoIdentity removeCognitoIdentityForKey:@"deleteIdentityPool"]; 148 | } 149 | 150 | 151 | @end 152 | -------------------------------------------------------------------------------- /AWSCognitoSyncTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # AWSCognitoSync CHANGELOG 2 | 3 | ## 2.1.1 4 | 5 | ### New Features 6 | * **Amazon Cognito** - Added support for Amazon Cognito Events. 7 | 8 | ## 2.1.0 9 | 10 | ### Misc Updates 11 | * Added `+ registerSERVICEWithConfiguration:forKey:`, `+ SERVICEForKey:`, and `+ removeSERVICEForKey:` to the service client. See the service client header for further details. 12 | * Deprecated `- initWithConfiguration:` in the service client. 13 | * Updated the framework name from `AWSCognitoSync.framework` to `AWSCognito.framework`. 14 | 15 | ### Resolved Issues 16 | * Updated the copyright year from 2014 to 2015. 17 | * Removed deprecated `synchronize` method from `UICKeyChainStore`. 18 | 19 | ## 1.0.8 20 | 21 | ### New Features 22 | * Added an ability to override the default push platform in Amazon Cognito Sync to explicitly set it to APNS or APNS Sandbox. 23 | 24 | ### Resolved Issues 25 | * Fixed a bug which caused resource conflicts in certain scenarios if you updated a record in the middle of a synchronization. 26 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/aws/amazon-cognito-ios/issues), or [recently closed](https://github.com/aws/amazon-cognito-ios/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws/amazon-cognito-ios/labels/help%20wanted) issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](https://github.com/aws/amazon-cognito-ios/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /Cognito/AWSCognito.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import "AWSCognitoService.h" 6 | #import "AWSCognitoDataset.h" 7 | #import "AWSCognitoRecord.h" 8 | #import "AWSCognitoHandlers.h" 9 | #import "AWSCognitoConflict.h" 10 | -------------------------------------------------------------------------------- /Cognito/AWSCognitoConflict.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import 6 | 7 | @class AWSCognitoRecord; 8 | 9 | /** 10 | An object that encapsulates a resolved conflict in Amazon Cognito. 11 | */ 12 | @interface AWSCognitoResolvedConflict : NSObject 13 | @end 14 | 15 | /** 16 | An object that encapsulates a tuple of Amazon Cognito records. 17 | */ 18 | @interface AWSCognitoRecordTuple : NSObject 19 | /** 20 | The local copy of the record. 21 | */ 22 | @property (nonatomic, readonly) AWSCognitoRecord *localRecord; 23 | /** 24 | The remote (cloud) copy of the record. 25 | */ 26 | @property (nonatomic, readonly) AWSCognitoRecord *remoteRecord; 27 | @end 28 | 29 | /** 30 | An object that encapsulates a conflicting record where both 31 | the local and remote have been modified since the last synchronization. 32 | */ 33 | @interface AWSCognitoConflict : AWSCognitoRecordTuple 34 | 35 | /** 36 | Create a AWSCognitoResolvedConflict object with the value of the 37 | local record. 38 | 39 | @return AWSCognitoResolvedConflict object using local value 40 | */ 41 | -(AWSCognitoResolvedConflict *) resolveWithLocalRecord; 42 | /** 43 | Create a AWSCognitoResolvedConflict object with the value of the 44 | remote (cloud) record. 45 | 46 | @return AWSCognitoResolvedConflict object using remote (cloud) value 47 | */ 48 | -(AWSCognitoResolvedConflict *) resolveWithRemoteRecord; 49 | /** 50 | Create a AWSCognitoResolvedConflict object with a custom value that 51 | is neither the local nor remote value. 52 | 53 | @param value the value to use to resolve the conflict 54 | 55 | @return AWSCognitoResolvedConflict object using passed value 56 | */ 57 | -(AWSCognitoResolvedConflict *) resolveWithValue:(NSString *)value; 58 | @end 59 | 60 | -------------------------------------------------------------------------------- /Cognito/AWSCognitoConflict.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import "AWSCognitoConflict_Internal.h" 6 | #import "AWSCognitoRecord.h" 7 | 8 | 9 | @implementation AWSCognitoRecordTuple 10 | -(instancetype) initWithLocalRecord:(AWSCognitoRecord *) local remoteRecord:(AWSCognitoRecord *) remote { 11 | self = [super init]; 12 | if (nil != self) { 13 | _localRecord = local; 14 | _remoteRecord = remote; 15 | } 16 | return self; 17 | } 18 | @end 19 | 20 | @implementation AWSCognitoConflict 21 | -(AWSCognitoResolvedConflict *) resolveWithLocalRecord { 22 | return [AWSCognitoResolvedConflict resolvedConflictWithLocalRecord:self]; 23 | } 24 | 25 | -(AWSCognitoResolvedConflict *) resolveWithRemoteRecord { 26 | return [AWSCognitoResolvedConflict resolvedConflictWithRemoteRecord:self]; 27 | } 28 | 29 | -(AWSCognitoResolvedConflict *) resolveWithValue:(NSString *)value { 30 | return [AWSCognitoResolvedConflict resolvedConflictWithValue:self newValue:value]; 31 | } 32 | 33 | @end 34 | 35 | @implementation AWSCognitoResolvedConflict 36 | - (instancetype) initWithRemoteRecord:(AWSCognitoConflict *) conflict { 37 | self = [super init]; 38 | if (nil != self) { 39 | _conflict = conflict; 40 | _resolvedConflict = [conflict.remoteRecord copy]; 41 | } 42 | return self; 43 | } 44 | 45 | - (instancetype) initWithLocalRecord:(AWSCognitoConflict *) conflict { 46 | self = [super init]; 47 | if (nil != self) { 48 | _conflict = conflict; 49 | _resolvedConflict = [conflict.localRecord copy]; 50 | _resolvedConflict.syncCount = conflict.remoteRecord.syncCount; 51 | } 52 | return self; 53 | } 54 | 55 | - (instancetype) initWithValue:(AWSCognitoConflict *)conflict newValue:(NSString *)value { 56 | self = [self initWithLocalRecord:conflict]; 57 | if (nil != self) { 58 | _resolvedConflict.data = [[AWSCognitoRecordValue alloc] initWithString:value]; 59 | } 60 | return self; 61 | } 62 | 63 | + (instancetype) resolvedConflictWithRemoteRecord:(AWSCognitoConflict *)conflict { 64 | return [[AWSCognitoResolvedConflict alloc] initWithRemoteRecord:conflict]; 65 | } 66 | 67 | + (instancetype) resolvedConflictWithLocalRecord:(AWSCognitoConflict *)conflict { 68 | return [[AWSCognitoResolvedConflict alloc] initWithLocalRecord:conflict]; 69 | } 70 | 71 | + (instancetype) resolvedConflictWithValue:(AWSCognitoConflict *)conflict newValue:(NSString *)value { 72 | return [[AWSCognitoResolvedConflict alloc] initWithValue:conflict newValue:value]; 73 | } 74 | 75 | @end 76 | 77 | -------------------------------------------------------------------------------- /Cognito/AWSCognitoDataset.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import 6 | #import "AWSCognitoHandlers.h" 7 | 8 | @class AWSCognitoRecord; 9 | @class AWSTask; 10 | 11 | /** 12 | An object that encapsulates the dataset metadata. 13 | */ 14 | @interface AWSCognitoDatasetMetadata : NSObject 15 | 16 | /** 17 | The name of this dataset 18 | */ 19 | @property (nonatomic, readonly) NSString *name; 20 | /** 21 | The last sync count known on the client device. 22 | */ 23 | @property (nonatomic, readonly) NSNumber *lastSyncCount; 24 | /** 25 | The creation date of the dataset on the remote store. 26 | */ 27 | @property (nonatomic, readonly) NSDate *creationDate; 28 | /** 29 | The amount of storage on the remote store this dataset uses. 30 | */ 31 | @property (nonatomic, readonly) NSNumber *dataStorage; 32 | /** 33 | The id of the last device to modify this dataset. 34 | */ 35 | @property (nonatomic, readonly) NSString *lastModifiedBy; 36 | /** 37 | The date this dataset was last modified 38 | */ 39 | @property (nonatomic, readonly) NSDate *lastModifiedDate; 40 | /** 41 | The number of records in this dataset on the remote store. 42 | */ 43 | @property (nonatomic, readonly) NSNumber *numRecords; 44 | 45 | /** 46 | Returns true if this dataset has been cleared locally, but not synchronized. 47 | */ 48 | - (BOOL)isDeleted; 49 | 50 | @end 51 | 52 | /** 53 | An object that encapsulates the dataset. The dataset is the unit of sync 54 | for Amazon Cognito. 55 | */ 56 | @interface AWSCognitoDataset : AWSCognitoDatasetMetadata 57 | 58 | /** 59 | A conflict resolution handler that will receive calls when there is a 60 | conflict during a sync operation. A conflict will occur when both remote and 61 | local data have been updated since the last sync time. 62 | When not explicitly set, we will use the default conflict resolution of 63 | 'last writer wins', where the data most recently updated will be persisted. 64 | */ 65 | @property (nonatomic, copy) AWSCognitoRecordConflictHandler conflictHandler; 66 | 67 | /** 68 | A deleted dataset handler. This handler will be called during a synchronization 69 | when the remote service indicates that a dataset has been deleted. 70 | Returning YES from the handler will cause the service to recreate the dataset 71 | on the remote on the next synchronization. Returning NO or leaving this property 72 | nil will cause the client to delete the dataset locally. 73 | */ 74 | @property (nonatomic, copy) AWSCognitoDatasetDeletedHandler datasetDeletedHandler; 75 | 76 | /** 77 | A merged dataset handler. This handler will be called during a synchronization 78 | when the remote service indicates that other datasets should be merged with this one. 79 | Merged datasets should be fetched, their data overlayed locally and then removed. 80 | Failing to implement this handler will result in merged datasets remaining on the 81 | service indefinitely. 82 | */ 83 | @property (nonatomic, copy) AWSCognitoDatasetMergedHandler datasetMergedHandler; 84 | 85 | /** 86 | The number of times to attempt a synchronization before failing. Defaults to 87 | to the value on the AWSCognito client that opened this dataset. 88 | */ 89 | @property (nonatomic, assign) uint32_t synchronizeRetries; 90 | 91 | /** 92 | Only synchronize if device is on a WiFi network. Defaults to 93 | to the value on the AWSCognito client that opened this dataset. 94 | */ 95 | @property (nonatomic, assign) BOOL synchronizeOnWiFiOnly; 96 | 97 | /** 98 | Sets a string object for the specified key in the dataset. 99 | */ 100 | - (void)setString:(NSString *) aString forKey:(NSString *) aKey; 101 | 102 | /** 103 | Returns the string associated with the specified key. 104 | */ 105 | - (NSString *)stringForKey:(NSString *) aKey; 106 | 107 | /** 108 | Synchronize local changes with remote changes on the service. First it pulls down changes from the service 109 | and attempts to overlay them on the local store. Then it pushes any local updates to the service. If at any 110 | point there is a conflict, conflict resolution is invoked. No changes are pushed to the service until 111 | all conflicts are resolved. 112 | */ 113 | - (AWSTask *)synchronize; 114 | 115 | /** 116 | Attempts to synchronize when device has connectivity. First it checks connectivity, if device is online 117 | immediately invokes synchronize and returns the AWSTask associated with the attempt. If the device is offline, 118 | schedules a synchronize for the next time the device comes online and returns a AWSTask with a nil result. 119 | The scheduled synchronize is only valid for the lifecycle of the dataset object. The data will not be synchronized 120 | if the app is exited before connectivity is regained. If you want to be notified when events occur during the 121 | scheduled synchronize, you must add observers of the notifications found in AWSCognito 122 | */ 123 | - (AWSTask *)synchronizeOnConnectivity; 124 | 125 | /** 126 | Subscribes this dataset to push notifications 127 | 128 | @return AWSTask with nil result. task.error will contain any errors. 129 | */ 130 | - (AWSTask *)subscribe; 131 | 132 | /** 133 | Unsubscribes this dataset to push notifications 134 | 135 | @return AWSTask with nil result. task.error will contain any errors. 136 | */ 137 | - (AWSTask *)unsubscribe; 138 | 139 | 140 | /** 141 | Returns all of the records in the dataset. Will return deleted records. 142 | 143 | @return NSArray of AWSCognitoRecord objects 144 | */ 145 | - (NSArray *)getAllRecords; 146 | 147 | /** 148 | Returns all the key value pairs in the dataset, ignore any deleted data. 149 | 150 | @return NSDictionary of all key value pairs. Contains no metadata. 151 | */ 152 | - (NSDictionary *)getAll; 153 | 154 | /** 155 | Remove a record from the dataset. 156 | 157 | @param aKey the key to remove 158 | */ 159 | - (void)removeObjectForKey:(NSString *) aKey; 160 | 161 | /** 162 | Returns the record associated with the specified key. 163 | 164 | @param aKey the key to return 165 | 166 | @return AWSCognitoRecord for this particular record. Will return nil if record does not exist. 167 | */ 168 | - (AWSCognitoRecord *)recordForKey:(NSString *) aKey; 169 | 170 | /** 171 | Clear this dataset locally. Dataset will not be removed from the service until the next synchronize call. 172 | */ 173 | - (void) clear; 174 | 175 | /** 176 | Returns the size in bytes for this dataset. 177 | */ 178 | - (long) size; 179 | 180 | /** 181 | Returns the size in bytes for the specified key. 182 | 183 | @param aKey the key to check 184 | */ 185 | - (long) sizeForKey:(NSString *) aKey; 186 | 187 | 188 | 189 | 190 | @end 191 | -------------------------------------------------------------------------------- /Cognito/AWSCognitoHandlers.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import 6 | 7 | @class AWSCognitoResolvedConflict; 8 | @class AWSCognitoConflict; 9 | 10 | /** 11 | DatasetDeletedHandler 12 | 13 | @param datasetName The name of the dataset that was deleted 14 | 15 | @return YES if Cognito should recreate the dataset, NO if Cognito should delete 16 | the local copy of the dataset. 17 | */ 18 | typedef BOOL (^AWSCognitoDatasetDeletedHandler)(NSString *datasetName); 19 | 20 | /** 21 | DatasetMergedHandler 22 | 23 | @param datasetName The name of the local dataset that is the destination of the merge 24 | @param datasets The list of dataset names that should be merged into the destination 25 | */ 26 | typedef void (^AWSCognitoDatasetMergedHandler)(NSString *datasetName, NSArray *datasets); 27 | 28 | /** 29 | ConflictHandler 30 | 31 | @param conflict The AWSCognitoConflict for this record. Conflict contains 32 | both local and remote data as properties. 33 | 34 | @return An instance of AWSCognitoResolvedConflict which indicates what data should be 35 | stored and syncronized. Returning nil will cancel synchronization. 36 | */ 37 | typedef AWSCognitoResolvedConflict* (^AWSCognitoRecordConflictHandler)(NSString *datasetName, AWSCognitoConflict *conflict); 38 | -------------------------------------------------------------------------------- /Cognito/AWSCognitoRecord.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import 6 | 7 | typedef NS_ENUM(NSInteger, AWSCognitoRecordValueType) { 8 | AWSCognitoRecordValueTypeUnknown, 9 | AWSCognitoRecordValueTypeString, 10 | AWSCognitoRecordValueTypeDeleted, 11 | }; 12 | 13 | /** 14 | An object that encapsulates the record value. 15 | */ 16 | @interface AWSCognitoRecordValue : NSObject 17 | 18 | 19 | /** 20 | The type of the record value. 21 | 22 | The record value datatypes. 23 |
    24 |
  • AWSCognitoRecordValueTypeUnknown - Unknown type.
  • 25 |
  • AWSCognitoRecordValueTypeString - The string value.
  • 26 |
  • AWSCognitoRecordValueTypeDeleted - A deleted value.
  • 27 |
28 | */ 29 | @property (nonatomic, readonly) AWSCognitoRecordValueType type; 30 | 31 | /** 32 | Initializes a AWSCognitoRecordValue with the given string value. 33 | The type property is automatically set to AWSCognitoRecordValueTypeString. 34 | 35 | @param value The string value of the AWSCognitoRecordValue. 36 | 37 | @return The initialized instance 38 | */ 39 | - (instancetype)initWithString:(NSString *)value; 40 | 41 | /** 42 | Returns the string value. 43 | 44 | @return The string value stored by the record value object. 45 | */ 46 | - (NSString *)string; 47 | 48 | @end 49 | 50 | @interface AWSCognitoRecordMetadata : NSObject 51 | 52 | /** 53 | Record ID or name. 54 | */ 55 | @property (nonatomic, readonly) NSString *recordId; 56 | 57 | /** 58 | The last date the record was modified. 59 | */ 60 | @property (nonatomic, readonly) NSDate *lastModified; 61 | 62 | /** 63 | The ID of the client that last modified the record. Set in AWSCognitoConfig under the clientID property. 64 | */ 65 | @property (nonatomic, strong) NSString *lastModifiedBy; 66 | 67 | /** 68 | Boolean indicating whether or not the record has updates/deletes that need to be synced with the server. 69 | */ 70 | @property (nonatomic, readonly, getter = isDirty) BOOL dirty; 71 | 72 | /** 73 | Integer value indicating how many times the record has been written since the last sync. 74 | The value is 0 if the record has not been modified. The value is incremented by 1 each time the record is updated. 75 | The value is set to -1 when the record is marked as deleted from the local database. 76 | */ 77 | @property (nonatomic, assign) int64_t dirtyCount; 78 | 79 | /** 80 | Integer value of the server sync count of the record. 81 | */ 82 | @property (nonatomic, assign) int64_t syncCount; 83 | 84 | - (instancetype)initWithId:(NSString *)recordId; 85 | 86 | /** 87 | Checks if the metadata matches. 88 | 89 | @param object The object to be compared to the receiver. 90 | May be nil, in which case this method returns NO. 91 | @return YES if the receiver and object have equal metadata, otherwise NO. 92 | */ 93 | - (BOOL)isEqualMetadata:(id)object; 94 | 95 | @end 96 | 97 | @interface AWSCognitoRecord : AWSCognitoRecordMetadata 98 | 99 | /** 100 | The data for the record. 101 | */ 102 | @property (nonatomic, strong) AWSCognitoRecordValue *data; 103 | 104 | /** 105 | Initializes a AWSCognitoRecord with the given recordID, given data, and a dirtyCount and recordVersion of 0. 106 | 107 | @param recordId The record ID of the AWSCognitoRecord 108 | @param data the initial data that the AWSCognitoRecord will contain 109 | */ 110 | - (instancetype)initWithId:(NSString *)recordId 111 | data:(AWSCognitoRecordValue *)data; 112 | 113 | /** 114 | Returns true if this record has been deleted 115 | 116 | @return YES if the record is deleted, NO otherwise 117 | */ 118 | - (BOOL)isDeleted; 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /Cognito/AWSCognitoRecord.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import "AWSCognitoService.h" 6 | #import "AWSCognitoRecord.h" 7 | #import "AWSCognitoUtil.h" 8 | #import "AWSCognitoConstants.h" 9 | #import "AWSCognitoRecord_Internal.h" 10 | 11 | @implementation AWSCognitoRecordMetadata 12 | 13 | - (instancetype)initWithId:(NSString *)recordId { 14 | if (self = [super init]) { 15 | _recordId = recordId; 16 | } 17 | return self; 18 | } 19 | 20 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary 21 | { 22 | self = [super init]; 23 | if (nil != self) { 24 | NSString *value = nil; 25 | 26 | value = [dictionary objectForKey:AWSCognitoTableRecordKeyName]; 27 | _recordId = value; 28 | 29 | value = [dictionary objectForKey:AWSCognitoLastModifiedFieldName]; 30 | _lastModified = [AWSCognitoUtil millisSinceEpochToDate:[NSNumber numberWithLongLong:[value longLongValue]]]; 31 | 32 | value = [dictionary objectForKey:AWSCognitoModifiedByFieldName]; 33 | _lastModifiedBy = value; 34 | 35 | value = [dictionary objectForKey:AWSCognitoDirtyFieldName]; 36 | _dirtyCount = [value longLongValue]; 37 | 38 | value = [dictionary objectForKey:AWSCognitoSyncCountFieldName]; 39 | _syncCount = [value longLongValue]; 40 | } 41 | return self; 42 | } 43 | 44 | - (BOOL)isEqualMetadata:(id)object 45 | { 46 | if([object isKindOfClass:[AWSCognitoRecordMetadata class]]) 47 | { 48 | return NO; 49 | } 50 | 51 | AWSCognitoRecordMetadata *other = object; 52 | if (self.syncCount != other.syncCount) { 53 | return NO; 54 | } 55 | 56 | if (self.dirtyCount != other.dirtyCount) { 57 | return NO; 58 | } 59 | 60 | if (![self.recordId isEqualToString:other.recordId]) { 61 | return NO; 62 | } 63 | 64 | if (![self.lastModifiedBy isEqualToString:other.lastModifiedBy]) { 65 | return NO; 66 | } 67 | 68 | if ([self.lastModified compare:other.lastModified] != NSOrderedSame) { 69 | return NO; 70 | } 71 | 72 | return YES; 73 | } 74 | 75 | @end 76 | 77 | @implementation AWSCognitoRecord 78 | 79 | - (instancetype)initWithId:(NSString *)recordId 80 | data:(AWSCognitoRecordValue *)data { 81 | self = [super initWithId:recordId]; 82 | if (nil != self) { 83 | _data = data; 84 | } 85 | return self; 86 | } 87 | 88 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary 89 | { 90 | self = [super initWithDictionary:dictionary]; 91 | 92 | if (nil != self) { 93 | _data = [[AWSCognitoRecordValue alloc] initWithString:[dictionary objectForKey:AWSCognitoRecordValueName]]; 94 | } 95 | return self; 96 | } 97 | 98 | - (BOOL)isEqual:(id)object 99 | { 100 | if(![self isEqualMetadata:object]) 101 | { 102 | return NO; 103 | } 104 | 105 | AWSCognitoRecord *other = object; 106 | if (![[self.data toJsonString] isEqualToString:[other.data toJsonString]]) { 107 | return NO; 108 | } 109 | 110 | return YES; 111 | } 112 | 113 | - (NSDictionary *)dictionaryRepresentation 114 | { 115 | 116 | NSString *lastModifiedValue = [NSString stringWithFormat:@"%lld", [AWSCognitoUtil getTimeMillisForDate:self.lastModified]]; 117 | 118 | 119 | NSString *recordVersionValue= [NSString stringWithFormat:@"%lld", self.syncCount]; 120 | 121 | NSString *recordTypeValue = [NSString stringWithFormat:@"%ld", (long)self.data.type]; 122 | 123 | return [NSDictionary dictionaryWithObjectsAndKeys: 124 | self.recordId, AWSCognitoTableRecordKeyName, 125 | lastModifiedValue, AWSCognitoLastModifiedFieldName, 126 | self.data.string, AWSCognitoRecordValueName, 127 | recordTypeValue, AWSCognitoTypeFieldName, 128 | self.lastModifiedBy, AWSCognitoModifiedByFieldName, 129 | recordVersionValue, AWSCognitoSyncCountFieldName, nil]; 130 | } 131 | 132 | - (AWSCognitoRecord *)copyForFlush 133 | { 134 | AWSCognitoRecord *flushableCopy = [[AWSCognitoRecord alloc] initWithId:self.recordId data:self.data]; 135 | flushableCopy.lastModified = self.lastModified; 136 | flushableCopy.lastModifiedBy = self.lastModifiedBy; 137 | flushableCopy.syncCount = self.syncCount; 138 | flushableCopy.dirtyCount = 0; 139 | 140 | return flushableCopy; 141 | } 142 | 143 | - (AWSCognitoRecord *)copy 144 | { 145 | AWSCognitoRecord *copy = [[AWSCognitoRecord alloc] initWithId:self.recordId data:self.data]; 146 | copy.lastModified = self.lastModified; 147 | copy.lastModifiedBy = self.lastModifiedBy; 148 | copy.syncCount = self.syncCount; 149 | copy.dirtyCount = self.dirtyCount; 150 | 151 | return copy; 152 | } 153 | 154 | - (BOOL)isDirty 155 | { 156 | return self.dirtyCount != 0; 157 | } 158 | 159 | - (BOOL)isDeleted { 160 | return self.data.type == AWSCognitoRecordValueTypeDeleted; 161 | } 162 | 163 | - (NSString *)description 164 | { 165 | NSMutableString *buffer = [NSMutableString new]; 166 | 167 | [buffer appendString:[super description]]; 168 | 169 | [buffer appendFormat:@"recordId: %@\n", self.recordId]; 170 | [buffer appendFormat:@"lastModified: %@\n", self.lastModified]; 171 | [buffer appendFormat:@"data: %@\n", self.data]; 172 | [buffer appendFormat:@"lastModifiedBy: %@\n", self.lastModifiedBy]; 173 | [buffer appendFormat:@"dirtyCount: %lld\n", self.dirtyCount]; 174 | [buffer appendFormat:@"recordVersion: %lld\n", self.syncCount]; 175 | 176 | return [NSString stringWithString:buffer]; 177 | } 178 | 179 | @end 180 | 181 | @implementation AWSCognitoRecordValue 182 | 183 | #pragma mark - Init methods 184 | 185 | - (instancetype)init { 186 | if(self = [super init]) { 187 | _type = AWSCognitoRecordValueTypeUnknown; 188 | } 189 | 190 | return self; 191 | } 192 | 193 | - (instancetype)initWithString:(NSString *)value { 194 | return [self initWithString:value type:AWSCognitoRecordValueTypeString]; 195 | } 196 | 197 | #pragma mark - Private init methods 198 | - (instancetype)initWithJson:(NSString *)json 199 | type:(AWSCognitoRecordValueType)type { 200 | if(json == nil){ 201 | return [self initWithString:nil type:type]; 202 | } 203 | NSError *error; 204 | NSObject *value = [[NSJSONSerialization 205 | JSONObjectWithData:[json dataUsingEncoding:NSUTF8StringEncoding] 206 | options:NSJSONReadingMutableContainers 207 | error:&error] objectForKey:AWSCognitoDataFieldKeyName]; 208 | NSString *stringValue = nil; 209 | 210 | switch (type) { 211 | case AWSCognitoRecordValueTypeString: 212 | stringValue = (NSString *)value; 213 | break; 214 | default: 215 | NSAssert(YES,@"Type: %lld is unsupported for this initializer", (long long)type); 216 | break; 217 | } 218 | return [self initWithString:stringValue type:type]; 219 | 220 | } 221 | 222 | - (instancetype)initWithString:(NSString *)value 223 | type:(AWSCognitoRecordValueType)type 224 | { 225 | if(self = [super init]) 226 | { 227 | _type = type; 228 | switch (type) { 229 | case AWSCognitoRecordValueTypeString: 230 | _stringValue = value; 231 | break; 232 | case AWSCognitoRecordValueTypeDeleted: 233 | _stringValue = AWSCognitoDeletedRecord; 234 | break; 235 | default: 236 | NSAssert(YES,@"Type: %lld is unsupported for this initializer", (long long)type); 237 | break; 238 | } 239 | } 240 | 241 | return self; 242 | } 243 | #pragma mark - Getters 244 | 245 | - (NSString *)string 246 | { 247 | if(self.type == AWSCognitoRecordValueTypeString) 248 | { 249 | return (NSString *)self.stringValue; 250 | } 251 | 252 | return nil; 253 | } 254 | 255 | #pragma mark json 256 | - (NSString *)toJsonString 257 | { 258 | if(self.stringValue == nil) 259 | return nil; 260 | 261 | NSObject * value = nil; 262 | switch (self.type) { 263 | 264 | case AWSCognitoRecordValueTypeString: 265 | value = self.stringValue; 266 | break; 267 | case AWSCognitoRecordValueTypeDeleted: 268 | value = AWSCognitoDeletedRecord; 269 | break; 270 | default: 271 | NSAssert(YES,@"Type: %lld is unsupported for this method", (long long)self.type); 272 | break; 273 | } 274 | 275 | if(value != nil){ 276 | NSError *error; 277 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject: [NSDictionary dictionaryWithObjectsAndKeys: 278 | value, AWSCognitoDataFieldKeyName, nil] 279 | options:0 error:&error]; 280 | if(jsonData != nil){ 281 | return [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding]; 282 | } 283 | } 284 | return nil; 285 | } 286 | 287 | #pragma mark - 288 | 289 | - (BOOL)isEqual:(id)object { 290 | if([object isKindOfClass:[AWSCognitoRecordValue class]]) { 291 | AWSCognitoRecordValue *recordValue = object; 292 | if(recordValue.type == self.type) { 293 | switch (self.type) { 294 | case AWSCognitoRecordValueTypeString: 295 | if([recordValue.string isEqualToString:self.string]) { 296 | return YES; 297 | } 298 | break; 299 | 300 | case AWSCognitoRecordValueTypeDeleted: 301 | return YES; 302 | break; 303 | default: 304 | break; 305 | } 306 | } 307 | } 308 | 309 | return NO; 310 | } 311 | 312 | - (NSString *)description 313 | { 314 | NSMutableString *buffer = [NSMutableString new]; 315 | 316 | [buffer appendString:[super description]]; 317 | 318 | [buffer appendFormat:@"\nType: %lld\n", (long long)self.type]; 319 | [buffer appendFormat:@"Value: %@", self.stringValue]; 320 | 321 | return [NSString stringWithString:buffer]; 322 | } 323 | 324 | @end 325 | 326 | -------------------------------------------------------------------------------- /Cognito/AWSCognitoService.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import 6 | #import 7 | #import "AWSCognitoHandlers.h" 8 | #import "AWSCognitoSyncService.h" 9 | 10 | @class AWSCognitoDataset; 11 | @class AWSCognitoCredentialsProvider; 12 | @class AWSTask; 13 | 14 | @interface AWSCognito : AWSService 15 | 16 | /** 17 | Posted when the synchronization is started. 18 | The notification sender is an instance of AWSCognitoClient. The userInfo 19 | contains the dataset name. 20 | @discussion This notification is posted once per synchronization. 21 | The notification is posted on the Grand Central Dispatch 22 | DISPATCH_QUEUE_PRIORITY_DEFAULT queue. The user interface should not be 23 | modified on the thread. 24 | */ 25 | extern NSString *const AWSCognitoDidStartSynchronizeNotification; 26 | /** 27 | Posted when the synchronization is finished with or without errors. 28 | The notification sender is an instance of AWSCognitoClient. The userInfo 29 | contains the dataset name. 30 | @discussion This notification is posted once per synchronization. 31 | The notification is posted on the Grand Central Dispatch 32 | DISPATCH_QUEUE_PRIORITY_DEFAULT queue. The user interface should not be 33 | modified on the thread. 34 | */ 35 | extern NSString *const AWSCognitoDidEndSynchronizeNotification; 36 | /** 37 | Posted when values are changed to the value from the remote data store. The notification 38 | sender is an instance of AWSCognitoClient. The userInfo contains the dataset name and 39 | an NSArray of changed keys. 40 | @discussion This notification may be posted multiple times per synchronization. 41 | The notification is posted on the Grand Central Dispatch 42 | DISPATCH_QUEUE_PRIORITY_DEFAULT queue. The user interface should not be 43 | modified on the thread. 44 | */ 45 | extern NSString *const AWSCognitoDidChangeLocalValueFromRemoteNotification; 46 | /** 47 | Posted when locally changed values are pushed to the remote store. The notification 48 | sender is an instance of AWSCognitoClient. The userInfo contains the dataset name and 49 | an NSArray of changed keys. 50 | @discussion This notification may be posted multiple times per synchronization. 51 | The notification is posted on the Grand Central Dispatch 52 | DISPATCH_QUEUE_PRIORITY_DEFAULT queue. The user interface should not be 53 | modified on the thread. 54 | */ 55 | extern NSString *const AWSCognitoDidChangeRemoteValueNotification; 56 | /** 57 | Posted when the synchronization for the for the dataset failed. The notification 58 | sender is an instance of AWSCognitoClient. The userInfo contains the dataset name 59 | and error. 60 | @discussion This notification may be posted multiple times per synchronization. 61 | The notification is posted on the Grand Central Dispatch 62 | DISPATCH_QUEUE_PRIORITY_DEFAULT queue. The user interface should not be 63 | modified on the thread. 64 | */ 65 | extern NSString *const AWSCognitoDidFailToSynchronizeNotification; 66 | 67 | /** 68 | The error domain for AWSCognito errors. 69 |
    70 |
  • AWSCognitoErrorUnknown - Unknow error.
  • 71 |
  • AWSCognitoErrorRemoteDataStorageFailed - The Amazon Cognito call temporarily failed.
  • 72 |
  • AWSCognitoErrorInvalidDataValue - The Amazon Cognito call failed. The value for the 73 | key is invalid and has been deleted from the local database.
  • 74 |
  • AWSCognitoErrorDataSizeLimitExceeded - The Amazon Cognito call failed. A 75 | dataset has exceeded the max dataset size.
  • 76 |
  • AWSCognitoErrorLocalDataStorageFailed - The SQLite call failed.
  • 77 |
  • AWSCognitoErrorIllegalArgument - The input value is invalid.
  • 78 |
  • AWSCognitoErrorConflictRetriesExhausted - The number of attempts to resolve a conflict 79 | has exceeded the max number of retries.
  • 80 |
  • AWSCognitoErrorWiFiNotAvailable - WiFi is required and not currently available.
  • 81 |
  • AWSCognitoErrorDeviceNotRegistered - The device has not been registered yet.
  • 82 |
83 | */ 84 | FOUNDATION_EXPORT NSString *const AWSCognitoErrorDomain; 85 | typedef NS_ENUM(NSInteger, AWSCognitoErrorType) { 86 | AWSCognitoErrorUnknown = 0, 87 | AWSCognitoErrorRemoteDataStorageFailed = -1000, 88 | AWSCognitoErrorInvalidDataValue = -1001, 89 | AWSCognitoErrorUserDataSizeLimitExceeded = -1002, 90 | AWSCognitoErrorLocalDataStorageFailed = -2000, 91 | AWSCognitoErrorIllegalArgument = -3000, 92 | AWSCognitoAuthenticationFailed = -4000, 93 | AWSCognitoErrorTaskCanceled = -5000, 94 | AWSCognitoErrorConflictRetriesExhausted = -6000, 95 | AWSCognitoErrorWiFiNotAvailable = -7000, 96 | AWSCognitoErrorDeviceNotRegistered = -8000, 97 | }; 98 | 99 | @property (nonatomic, strong, readonly) AWSServiceConfiguration *configuration; 100 | 101 | /** 102 | A conflict resolution handler that will receive calls when there is a 103 | conflict during a sync operation. A conflict will occur when both remote and 104 | local data have been updated since the last sync time. 105 | When not explicitly set, we will use the default conflict resolution of 106 | 'last writer wins', where the data most recently updated will be persisted. 107 | This handler will be propagated to any AWSCognitoDataset opened by this client. 108 | */ 109 | @property (nonatomic, strong) AWSCognitoRecordConflictHandler conflictHandler; 110 | 111 | /** 112 | A deleted dataset handler. This handler will be called during a synchronization 113 | when the remote service indicates that a dataset has been deleted. 114 | Returning YES from the handler will cause the service to recreate the dataset 115 | on the remote on the next synchronization. Returning NO or leaving this property 116 | nil will cause the client to delete the dataset locally. 117 | This handler will be propagated to any AWSCognitoDataset opened by this client. 118 | */ 119 | @property (nonatomic, strong) AWSCognitoDatasetDeletedHandler datasetDeletedHandler; 120 | 121 | /** 122 | A merged dataset handler. This handler will be called during a synchronization 123 | when the remote service indicates that other datasets should be merged with this one. 124 | Merged datasets should be fetched, their data overlayed locally and then removed. 125 | Failing to implement this handler will result in merged datasets remaining on the 126 | service indefinitely. 127 | This handler will be propagated to any AWSCognitoDataset opened by this client. 128 | */ 129 | @property (nonatomic, strong) AWSCognitoDatasetMergedHandler datasetMergedHandler; 130 | 131 | /** 132 | The identifier used for this client in Amazon Cognito. If not supplied 133 | Amazon Cognito will create a random GUID for the device. 134 | */ 135 | @property (nonatomic, strong) NSString *deviceId; 136 | 137 | /** 138 | The number of times to attempt a synchronization before failing. This will 139 | be set on any AWSCognitoDatasets opened with this client. Defaults to 5 if not set. 140 | */ 141 | @property (nonatomic, assign) uint32_t synchronizeRetries; 142 | 143 | /** 144 | Only synchronize if device is on a WiFi network. Defaults to NO if not set. 145 | */ 146 | @property (nonatomic, assign) BOOL synchronizeOnWiFiOnly; 147 | 148 | /** 149 | Returns the singleton service client. If the singleton object does not exist, the SDK instantiates the default service client with `defaultServiceConfiguration` from `[AWSServiceManager defaultServiceManager]`. The reference to this object is maintained by the SDK, and you do not need to retain it manually. Returns `nil` if the credentials provider is not an instance of `AWSCognitoCredentials` provider. 150 | 151 | For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` 152 | 153 | *Swift* 154 | 155 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 156 | let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") 157 | let configuration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: credentialProvider) 158 | AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration 159 | 160 | return true 161 | } 162 | 163 | *Objective-C* 164 | 165 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 166 | AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 167 | identityPoolId:@"YourIdentityPoolId"]; 168 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 169 | credentialsProvider:credentialsProvider]; 170 | [AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration; 171 | 172 | return YES; 173 | } 174 | 175 | Then call the following to get the default service client: 176 | 177 | *Swift* 178 | 179 | let Cognito = AWSCognito.defaultCognito() 180 | 181 | *Objective-C* 182 | 183 | AWSCognito *Cognito = [AWSCognito defaultCognito]; 184 | 185 | @return The default service client. 186 | */ 187 | + (instancetype)defaultCognito; 188 | 189 | /** 190 | Creates a service client with the given service configuration and registers it for the key. 191 | 192 | For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` 193 | 194 | *Swift* 195 | 196 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 197 | let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") 198 | let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialProvider) 199 | AWSCognito.registerCognitoWithConfiguration(configuration, forKey: "USWest2Cognito") 200 | 201 | return true 202 | } 203 | 204 | *Objective-C* 205 | 206 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 207 | AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 208 | identityPoolId:@"YourIdentityPoolId"]; 209 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSWest2 210 | credentialsProvider:credentialsProvider]; 211 | 212 | [AWSCognito registerCognitoWithConfiguration:configuration forKey:@"USWest2Cognito"]; 213 | 214 | return YES; 215 | } 216 | 217 | Then call the following to get the service client: 218 | 219 | *Swift* 220 | 221 | let Cognito = AWSCognito(forKey: "USWest2Cognito") 222 | 223 | *Objective-C* 224 | 225 | AWSCognito *Cognito = [AWSCognito CognitoForKey:@"USWest2Cognito"]; 226 | 227 | @warning After calling this method, do not modify the configuration object. It may cause unspecified behaviors. 228 | 229 | @param configuration A service configuration object. 230 | @param key A string to identify the service client. 231 | */ 232 | + (void)registerCognitoWithConfiguration:(AWSServiceConfiguration *)configuration forKey:(NSString *)key; 233 | 234 | /** 235 | Retrieves the service client associated with the key. You need to call `+ registerCognitoWithConfiguration:forKey:` before invoking this method. 236 | 237 | For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` 238 | 239 | *Swift* 240 | 241 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 242 | let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") 243 | let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialProvider) 244 | AWSCognito.registerCognitoWithConfiguration(configuration, forKey: "USWest2Cognito") 245 | 246 | return true 247 | } 248 | 249 | *Objective-C* 250 | 251 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 252 | AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 253 | identityPoolId:@"YourIdentityPoolId"]; 254 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSWest2 255 | credentialsProvider:credentialsProvider]; 256 | 257 | [AWSCognito registerCognitoWithConfiguration:configuration forKey:@"USWest2Cognito"]; 258 | 259 | return YES; 260 | } 261 | 262 | Then call the following to get the service client: 263 | 264 | *Swift* 265 | 266 | let Cognito = AWSCognito(forKey: "USWest2Cognito") 267 | 268 | *Objective-C* 269 | 270 | AWSCognito *Cognito = [AWSCognito CognitoForKey:@"USWest2Cognito"]; 271 | 272 | @param key A string to identify the service client. 273 | 274 | @return An instance of the service client. 275 | */ 276 | + (instancetype)CognitoForKey:(NSString *)key; 277 | 278 | /** 279 | Removes the service client associated with the key and release it. 280 | 281 | @warning Before calling this method, make sure no method is running on this client. 282 | 283 | @param key A string to identify the service client. 284 | */ 285 | + (void)removeCognitoForKey:(NSString *)key; 286 | 287 | /** 288 | Initialize the instance with the supplied service config. 289 | Will return nil if the credentials provider is not an instance of 290 | AWSCognitoCredentials provider. 291 | */ 292 | - (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration __attribute__ ((deprecated("Use '+ registerCognitoWithConfiguration:forKey:' and '+ CognitoForKey:' instead."))); 293 | 294 | /** 295 | Opens an existing dataset or creates a new one. 296 | 297 | @return handle to AWSCognitoDataset 298 | */ 299 | - (AWSCognitoDataset *)openOrCreateDataset:(NSString *)datasetName; 300 | 301 | /** 302 | List all datasets our client is aware of. Call refreshDatasetMetadata to ensure 303 | the client has knowledge of all datasets available on the remote store. 304 | 305 | @return NSArray of AWSCognitoDatasetMetadata 306 | */ 307 | - (NSArray *)listDatasets; 308 | 309 | /** 310 | List all of the datasets. Returns a AWSTask. The result of this task will be an array of 311 | AWSCognitoDatasetMetadata objects. 312 | */ 313 | - (AWSTask *)refreshDatasetMetadata; 314 | 315 | /** 316 | Wipe all cached data. 317 | */ 318 | - (void)wipe; 319 | 320 | /** 321 | Get the default, last writer wins conflict handler 322 | */ 323 | + (AWSCognitoRecordConflictHandler) defaultConflictHandler; 324 | 325 | /** 326 | Register this device for push notifications. You will not receive any notifications until you actually subscribe the 327 | dataset you want to receive push notifications for. If your build targets Release, this will register the device 328 | with APNS, if your build targets Debug this will register the device with APNS_SANDBOX. Returns a AWSTask. 329 | The result of this task will be a AWSCognitoSyncRegisterDeviceResponse. 330 | */ 331 | - (AWSTask *)registerDevice: (NSData *) deviceToken; 332 | 333 | /** 334 | Get the device id Cognito Sync gave this device. nil if device has never been registered 335 | */ 336 | + (NSString *) cognitoDeviceId; 337 | 338 | /** 339 | Used to override the platform for push notifications. If you are not using the CocoaPods distribution, 340 | #ifdef DEBUG 341 | [[AWSCognito defaultCognito] setPushPlatform:AWSCognitoSyncPlatformApnsSandbox]; 342 | #endif 343 | will set push notifications to use the APNS_SANDBOX if your build targets Debug. Otherwise it will 344 | always use APNS. 345 | */ 346 | 347 | + (void)setPushPlatform:(AWSCognitoSyncPlatform) pushPlatform; 348 | 349 | /** 350 | The push platform for push notifications 351 | */ 352 | + (AWSCognitoSyncPlatform)pushPlatform; 353 | 354 | /** 355 | Subscribe to a list of datasets. Make sure you have called synchronize on each of the datasets in the list 356 | at least once prior to calling this. Returns a AWSTask. The result of this task will be a NSArray of 357 | AWSCognitoSyncSubscribeToDatasetResponse 358 | */ 359 | - (AWSTask *)subscribe:(NSArray *) datasetNames; 360 | 361 | /** 362 | Subscribe to all datasets you have locally. Make sure you have called synchronize on all of your local datasets 363 | at least once prior to calling this. Returns a AWSTask. The result of this task will be a NSArray of 364 | AWSCognitoSyncSubscribeToDatasetResponse 365 | */ 366 | - (AWSTask *)subscribeAll; 367 | 368 | /** 369 | Unsubscribe to a list of datasets. Returns a AWSTask. The result of this task will be a NSArray of 370 | AWSCognitoSyncUnsubscribeToDatasetResponse 371 | */ 372 | - (AWSTask *)unsubscribe:(NSArray *) datasetNames; 373 | 374 | /** 375 | Unsubscribe to all datasets you have locally. Make sure you have called synchronize on all of your local datasets 376 | at least once prior to calling this. Returns a AWSTask. The result of this task will be a NSArray of 377 | AWSCognitoSyncUnsubscribeToDatasetResponse 378 | */ 379 | - (AWSTask *)unsubscribeAll; 380 | 381 | @end 382 | -------------------------------------------------------------------------------- /Cognito/AWSCognitoService.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import "AWSCognitoService.h" 6 | #import 7 | #import "AWSCognitoRecord_Internal.h" 8 | #import "AWSCognitoSQLiteManager.h" 9 | #import "AWSCognitoDataset.h" 10 | #import "AWSCognitoConstants.h" 11 | #import "AWSCognitoUtil.h" 12 | #import "AWSCognitoDataset_Internal.h" 13 | #import 14 | #import "AWSCognitoHandlers.h" 15 | #import "AWSCognitoConflict_Internal.h" 16 | #import 17 | #import 18 | 19 | #import "FABKitProtocol.h" 20 | #import "Fabric+FABKits.h" 21 | 22 | NSString *const AWSCognitoDidStartSynchronizeNotification = @"com.amazon.cognito.AWSCognitoDidStartSynchronizeNotification"; 23 | NSString *const AWSCognitoDidEndSynchronizeNotification = @"com.amazon.cognito.AWSCognitoDidEndSynchronizeNotification"; 24 | NSString *const AWSCognitoDidChangeLocalValueFromRemoteNotification = @"com.amazon.cognito.AWSCognitoDidChangeLocalValueFromRemoteNotification"; 25 | NSString *const AWSCognitoDidChangeRemoteValueNotification = @"com.amazon.cognito.AWSCognitoDidChangeRemoteValueNotification"; 26 | NSString *const AWSCognitoDidFailToSynchronizeNotification = @"com.amazon.cognito.AWSCognitoDidFailToSynchronizeNotification"; 27 | NSString *const AWSCognitoUnknownDataTypeNotification = @"com.amazon.cognito.AWSCognitoUnknownDataTypeNotification"; 28 | 29 | // For the cognito client to communicate to open datasets 30 | NSString *const AWSCognitoIdentityIdChangedInternalNotification = @"com.amazonaws.services.cognitoidentity.AWSCognitoIdentityIdChangedInternalNotification"; 31 | 32 | NSString *const AWSCognitoErrorDomain = @"com.amazon.cognito.AWSCognitoErrorDomain"; 33 | 34 | static AWSUICKeyChainStore *keychain = nil; 35 | 36 | static AWSCognitoSyncPlatform _pushPlatform; 37 | 38 | @interface AWSCognito() 39 | 40 | @property (nonatomic, strong) AWSCognitoSQLiteManager *sqliteManager; 41 | @property (nonatomic, strong) AWSCognitoSync *cognitoService; 42 | @property (nonatomic, strong) AWSCognitoCredentialsProvider *cognitoCredentialsProvider; 43 | @property (nonatomic, strong) AWSUICKeyChainStore *keychain; 44 | 45 | @end 46 | 47 | @interface AWSCognitoIdentity() 48 | 49 | + (void)internalInitializeIfNeeded; 50 | 51 | @end 52 | 53 | @implementation AWSCognito 54 | 55 | static AWSSynchronizedMutableDictionary *_serviceClients = nil; 56 | 57 | #pragma mark - Fabric 58 | 59 | + (NSString *)bundleIdentifier { 60 | return @"com.amazonaws.sdk.ios.AWSCognito"; 61 | } 62 | 63 | + (NSString *)kitDisplayVersion { 64 | return AWSiOSSDKVersion; 65 | } 66 | 67 | + (void)initializeIfNeeded { 68 | [AWSCognitoIdentity internalInitializeIfNeeded]; 69 | } 70 | 71 | #pragma mark - Setups 72 | 73 | + (void)initialize { 74 | keychain = [AWSUICKeyChainStore keyChainStoreWithService:[NSString stringWithFormat:@"%@.%@", [NSBundle mainBundle].bundleIdentifier, [AWSCognito class]]]; 75 | _pushPlatform = [AWSCognitoUtil pushPlatform]; 76 | } 77 | 78 | + (instancetype)defaultCognito { 79 | if (![AWSServiceManager defaultServiceManager].defaultServiceConfiguration) { 80 | return nil; 81 | } 82 | 83 | // Cognito needs an AWSCognitoCredentialsProvider 84 | if (![[AWSServiceManager defaultServiceManager].defaultServiceConfiguration.credentialsProvider isKindOfClass:[AWSCognitoCredentialsProvider class]]) { 85 | return nil; 86 | } 87 | 88 | static AWSCognito *_defaultCognito = nil; 89 | static dispatch_once_t onceToken; 90 | dispatch_once(&onceToken, ^{ 91 | #pragma clang diagnostic push 92 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" 93 | _defaultCognito = [[AWSCognito alloc] initWithConfiguration:AWSServiceManager.defaultServiceManager.defaultServiceConfiguration]; 94 | #pragma clang diagnostic pop 95 | }); 96 | 97 | return _defaultCognito; 98 | } 99 | 100 | + (void)registerCognitoWithConfiguration:(AWSServiceConfiguration *)configuration forKey:(NSString *)key { 101 | static dispatch_once_t onceToken; 102 | dispatch_once(&onceToken, ^{ 103 | _serviceClients = [AWSSynchronizedMutableDictionary new]; 104 | }); 105 | #pragma clang diagnostic push 106 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" 107 | [_serviceClients setObject:[[AWSCognito alloc] initWithConfiguration:configuration] 108 | forKey:key]; 109 | #pragma clang diagnostic pop 110 | } 111 | 112 | + (instancetype)CognitoForKey:(NSString *)key { 113 | return [_serviceClients objectForKey:key]; 114 | } 115 | 116 | + (void)removeCognitoForKey:(NSString *)key { 117 | [_serviceClients removeObjectForKey:key]; 118 | } 119 | 120 | - (instancetype)init { 121 | @throw [NSException exceptionWithName:NSInternalInconsistencyException 122 | reason:@"`- init` is not a valid initializer. Use `+ defaultCognito` or `+ CognitoForKey:` instead." 123 | userInfo:nil]; 124 | return nil; 125 | } 126 | 127 | - (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration 128 | { 129 | // Cognito needs an AWSCognitoCredentialsProvider 130 | if (![configuration.credentialsProvider isKindOfClass:[AWSCognitoCredentialsProvider class]]) { 131 | return nil; 132 | } 133 | 134 | if (self = [super init]) { 135 | _configuration = [configuration copy]; 136 | _cognitoCredentialsProvider = _configuration.credentialsProvider; 137 | 138 | // set other default values 139 | NSString * serviceDeviceId = [AWSCognito cognitoDeviceId]; 140 | _deviceId = (serviceDeviceId) == nil ? @"LOCAL" : serviceDeviceId; 141 | _synchronizeRetries = AWSCognitoMaxSyncRetries; 142 | _synchronizeOnWiFiOnly = AWSCognitoSynchronizeOnWiFiOnly; 143 | 144 | _conflictHandler = [AWSCognito defaultConflictHandler]; 145 | _sqliteManager = [[AWSCognitoSQLiteManager alloc] initWithIdentityId:_cognitoCredentialsProvider.identityId deviceId:_deviceId]; 146 | #pragma clang diagnostic push 147 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" 148 | _cognitoService = [[AWSCognitoSync alloc] initWithConfiguration:configuration]; 149 | #pragma clang diagnostic pop 150 | // register to know when the identity on our provider changes 151 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(identityChanged:) name:AWSCognitoIdentityIdChangedNotification object:_cognitoCredentialsProvider.identityProvider]; 152 | 153 | 154 | } 155 | 156 | return self; 157 | } 158 | 159 | -(void)dealloc { 160 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 161 | } 162 | 163 | - (AWSCognitoDataset *)openOrCreateDataset:(NSString * ) datasetName{ 164 | AWSCognitoDataset *dataset = [[AWSCognitoDataset alloc] initWithDatasetName:datasetName 165 | sqliteManager:self.sqliteManager 166 | cognitoService:self.cognitoService]; 167 | dataset.conflictHandler = self.conflictHandler; 168 | dataset.datasetDeletedHandler = self.datasetDeletedHandler; 169 | dataset.datasetMergedHandler = self.datasetMergedHandler; 170 | dataset.synchronizeRetries = self.synchronizeRetries; 171 | dataset.synchronizeOnWiFiOnly = self.synchronizeOnWiFiOnly; 172 | 173 | // register the dataset to receive notifications from this instance when the identity changes 174 | [[NSNotificationCenter defaultCenter] addObserver:dataset selector:@selector(identityChanged:) name:AWSCognitoIdentityIdChangedInternalNotification object:self]; 175 | 176 | return dataset; 177 | } 178 | 179 | - (void)wipe { 180 | [self.sqliteManager deleteAllData]; 181 | [self.cognitoCredentialsProvider clearKeychain]; 182 | } 183 | 184 | - (AWSTask *)refreshDatasetMetadata { 185 | return [[[self.cognitoCredentialsProvider getIdentityId] continueWithBlock:^id(AWSTask *task) { 186 | if (task.error) { 187 | return [AWSTask taskWithError:[NSError errorWithDomain:AWSCognitoErrorDomain code:AWSCognitoAuthenticationFailed userInfo:nil]]; 188 | } 189 | AWSCognitoSyncListDatasetsRequest *request = [AWSCognitoSyncListDatasetsRequest new]; 190 | request.identityPoolId = self.cognitoCredentialsProvider.identityPoolId; 191 | request.identityId = self.cognitoCredentialsProvider.identityId; 192 | return [self.cognitoService listDatasets:request]; 193 | }] continueWithBlock:^id(AWSTask *task) { 194 | if(task.isCancelled){ 195 | return [AWSTask taskWithError:[NSError errorWithDomain:AWSCognitoErrorDomain code:AWSCognitoErrorTaskCanceled userInfo:nil]]; 196 | }else if(task.error){ 197 | AWSLogError(@"Unable to list datasets: %@", task.error); 198 | return task; 199 | }else { 200 | AWSCognitoSyncListDatasetsResponse* response = task.result; 201 | [self.sqliteManager putDatasetMetadata: response.datasets error:nil]; 202 | return [AWSTask taskWithResult:response.datasets]; 203 | } 204 | }]; 205 | } 206 | 207 | - (NSArray *)listDatasets { 208 | return [self.sqliteManager getDatasets:nil]; 209 | } 210 | 211 | - (void) setDeviceId:(NSString *)deviceId { 212 | self.sqliteManager.deviceId = deviceId; 213 | _deviceId = deviceId; 214 | } 215 | 216 | - (void)identityChanged:(NSNotification *)notification { 217 | AWSLogDebug(@"IdentityChanged"); 218 | NSDictionary *userInfo = notification.userInfo; 219 | 220 | NSString *oldId = [userInfo objectForKey:AWSCognitoNotificationPreviousId]; 221 | NSString *newId = [userInfo objectForKey:AWSCognitoNotificationNewId]; 222 | 223 | NSError *error; 224 | 225 | if ([self.sqliteManager reparentDatasets:oldId withNewId:newId error:&error]) { 226 | // update the id for the sqlitemanager 227 | self.sqliteManager.identityId = newId; 228 | 229 | // Now that we've udpated the data, notify open datasets 230 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 231 | [[NSNotificationCenter defaultCenter] postNotificationName:AWSCognitoIdentityIdChangedInternalNotification 232 | object:self 233 | userInfo:userInfo]; 234 | }); 235 | } 236 | else { 237 | // TODO: How do we surface this error? 238 | } 239 | } 240 | 241 | +(NSString *) cognitoDeviceId { 242 | return keychain[[AWSCognitoUtil deviceIdKey:_pushPlatform]]; 243 | } 244 | 245 | +(NSString *) cognitoDeviceIdentity { 246 | return keychain[[AWSCognitoUtil deviceIdentityKey:_pushPlatform]]; 247 | } 248 | 249 | -(AWSTask *)registerDevice:(NSData *) deviceToken { 250 | const unsigned char* bytes = (const unsigned char*)[deviceToken bytes]; 251 | NSMutableString * devTokenHex = [[NSMutableString alloc] initWithCapacity:2*deviceToken.length]; 252 | for(int i=0; i * _Nonnull task) { 275 | AWSCognitoSyncRegisterDeviceResponse* response = task.result; 276 | keychain[[AWSCognitoUtil deviceIdKey:_pushPlatform]] = response.deviceId; 277 | keychain[[AWSCognitoUtil deviceIdentityKey:_pushPlatform]] = self.cognitoCredentialsProvider.identityId; 278 | [self setDeviceId:response.deviceId]; 279 | return [AWSTask taskWithResult:response.deviceId]; 280 | }]; 281 | }] continueWithBlock:^id(AWSTask *task) { 282 | if(task.isCancelled){ 283 | return [AWSTask taskWithError:[NSError errorWithDomain:AWSCognitoErrorDomain code:AWSCognitoErrorTaskCanceled userInfo:nil]]; 284 | } 285 | 286 | if(task.error){ 287 | AWSLogError(@"Unable to register device: %@", task.error); 288 | } 289 | 290 | return task; 291 | }]; 292 | } 293 | 294 | +(void)setPushPlatform:(AWSCognitoSyncPlatform) pushPlatform { 295 | _pushPlatform = pushPlatform; 296 | } 297 | 298 | +(AWSCognitoSyncPlatform)pushPlatform { 299 | return _pushPlatform; 300 | } 301 | 302 | -(AWSTask *)subscribe:(NSArray *) datasetNames { 303 | NSMutableArray *tasks = [NSMutableArray new]; 304 | for (NSString * datasetName in datasetNames) { 305 | [tasks addObject:[[self openOrCreateDataset:datasetName] subscribe]]; 306 | } 307 | return [AWSTask taskForCompletionOfAllTasks:tasks]; 308 | } 309 | 310 | -(AWSTask *)subscribeAll { 311 | NSArray * datasets = [self listDatasets]; 312 | NSMutableArray * datasetNames = [NSMutableArray new]; 313 | for (AWSCognitoDatasetMetadata * dataset in datasets) { 314 | [datasetNames addObject: dataset.name]; 315 | } 316 | return [self subscribe:datasetNames]; 317 | } 318 | 319 | -(AWSTask *)unsubscribe:(NSArray *) datasetNames { 320 | NSMutableArray *tasks = [NSMutableArray new]; 321 | for (NSString * datasetName in datasetNames) { 322 | [tasks addObject:[[self openOrCreateDataset:datasetName] unsubscribe]]; 323 | } 324 | return [AWSTask taskForCompletionOfAllTasks:tasks]; 325 | } 326 | 327 | -(AWSTask *)unsubscribeAll { 328 | NSArray * datasets = [self listDatasets]; 329 | NSMutableArray * datasetNames = [NSMutableArray new]; 330 | for (AWSCognitoDatasetMetadata * dataset in datasets) { 331 | [datasetNames addObject:dataset.name]; 332 | } 333 | return [self unsubscribe:datasetNames]; 334 | } 335 | 336 | + (AWSCognitoRecordConflictHandler) defaultConflictHandler { 337 | return ^AWSCognitoResolvedConflict* (NSString *datasetName, AWSCognitoConflict *conflict) { 338 | AWSLogDebug(@"Last writer wins conflict resolution for dataset %@", datasetName); 339 | if (conflict.remoteRecord == nil || [conflict.localRecord.lastModified compare:conflict.remoteRecord.lastModified] == NSOrderedDescending) 340 | { 341 | return [[AWSCognitoResolvedConflict alloc] initWithLocalRecord: conflict]; 342 | } 343 | else 344 | { 345 | return [[AWSCognitoResolvedConflict alloc] initWithRemoteRecord: conflict]; 346 | } 347 | }; 348 | } 349 | 350 | @end 351 | -------------------------------------------------------------------------------- /Cognito/Fabric/FABAttributes.h: -------------------------------------------------------------------------------- 1 | // 2 | // FABAttributes.h 3 | // Fabric 4 | // 5 | // Copyright (C) 2015 Twitter, Inc. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #pragma once 21 | 22 | #define FAB_UNAVAILABLE(x) __attribute__((unavailable(x))) 23 | 24 | #if __has_feature(nullability) 25 | #define fab_nullable nullable 26 | #define fab_nonnull nonnull 27 | #define fab_null_unspecified null_unspecified 28 | #define fab_null_resettable null_resettable 29 | #define __fab_nullable __nullable 30 | #define __fab_nonnull __nonnull 31 | #define __fab_null_unspecified __null_unspecified 32 | #else 33 | #define fab_nullable 34 | #define fab_nonnull 35 | #define fab_null_unspecified 36 | #define fab_null_resettable 37 | #define __fab_nullable 38 | #define __fab_nonnull 39 | #define __fab_null_unspecified 40 | #endif 41 | 42 | #ifndef NS_ASSUME_NONNULL_BEGIN 43 | #define NS_ASSUME_NONNULL_BEGIN 44 | #endif 45 | 46 | #ifndef NS_ASSUME_NONNULL_END 47 | #define NS_ASSUME_NONNULL_END 48 | #endif 49 | 50 | 51 | /** 52 | * The following macros are defined here to provide 53 | * backwards compatability. If you are still using 54 | * them you should migrate to the new versions that 55 | * are defined above. 56 | */ 57 | #define FAB_NONNULL __fab_nonnull 58 | #define FAB_NULLABLE __fab_nullable 59 | #define FAB_START_NONNULL NS_ASSUME_NONNULL_BEGIN 60 | #define FAB_END_NONNULL NS_ASSUME_NONNULL_END 61 | -------------------------------------------------------------------------------- /Cognito/Fabric/FABKitProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // FABKitProtocol.h 3 | // Fabric 4 | // 5 | // Copyright (C) 2015 Twitter, Inc. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import 21 | 22 | /** 23 | * Protocol that a class in a Fabric Kit must conform to to provide information to Fabric at runtime. 24 | */ 25 | @protocol FABKit 26 | 27 | @required 28 | 29 | /** 30 | * Required. The globally unique identifier of the Kit. 31 | * We encourage the use of reverse-DNS notation. 32 | * Example: @"io.fabric.sdk.ios" 33 | */ 34 | + (NSString *)bundleIdentifier; 35 | 36 | /** 37 | * Required. Must return the current version of the Kit that is being used at runtime. 38 | * We encourage the use of semantic versioning (http://semver.org/), without prefixing the version with a "v". 39 | * This is commonly referred to as the "marketing version". 40 | * Example: @"1.2.3" 41 | */ 42 | + (NSString *)kitDisplayVersion; 43 | 44 | @optional 45 | 46 | /** 47 | * The build version of the kit. Should be monotonically increasing and unique. 48 | * Example: 137 49 | */ 50 | + (NSString *)kitBuildVersion; 51 | 52 | /** 53 | * Perform any necessary initialization. 54 | * This method will be invoked on the Kit when the user calls +[Fabric initializeKits]. 55 | * @note This method being called does not necessarily imply that the developer has started using the Kit yet. 56 | */ 57 | + (void)initializeIfNeeded; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Cognito/Fabric/Fabric+FABKits.h: -------------------------------------------------------------------------------- 1 | // 2 | // Fabric+FABKits.h 3 | // Fabric 4 | // 5 | // Copyright (C) 2015 Twitter, Inc. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import "Fabric.h" 21 | 22 | @protocol FABKit; 23 | // Use this category for methods that kits can call on Fabric. 24 | @interface Fabric (FABKits) 25 | 26 | /** 27 | * Returns a dictionary containing the kit configuration info for the provided kit. 28 | * The configuration information is parsed from the application's Info.plist. This 29 | * method is primarily intended to be used by kits to retrieve their configuration. 30 | * 31 | * @param kitClass The class of the kit whose configuration should be returned. 32 | * It should conform to the FABKit protocol. 33 | * 34 | * @return A dictionary containing kit specific configuration information or nil if none exists. 35 | */ 36 | + (fab_nonnull NSDictionary *)configurationDictionaryForKitClass:(fab_nonnull Class)kitClass; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Cognito/Fabric/Fabric.h: -------------------------------------------------------------------------------- 1 | // 2 | // Fabric.h 3 | // Fabric 4 | // 5 | // Copyright (C) 2015 Twitter, Inc. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import 21 | #import "FABAttributes.h" 22 | 23 | NS_ASSUME_NONNULL_BEGIN 24 | 25 | /** 26 | * Fabric Base. Coordinates configuration and starts all provided kits. 27 | */ 28 | @interface Fabric : NSObject 29 | 30 | /** 31 | * Initialize Fabric and all provided kits. Call this method within your App Delegate's `application:didFinishLaunchingWithOptions:` and provide the kits you wish to use. 32 | * 33 | * For example, in Objective-C: 34 | * 35 | * `[Fabric with:@[[Crashlytics class], [Twitter class], [Digits class], [MoPub class]]];` 36 | * 37 | * Swift: 38 | * 39 | * `Fabric.with([Crashlytics.self(), Twitter.self(), Digits.self(), MoPub.self()])` 40 | * 41 | * Only the first call to this method is honored. Subsequent calls are no-ops. 42 | * 43 | * @param kits An array of kit Class objects 44 | * 45 | * @return Returns the shared Fabric instance. In most cases this can be ignored. 46 | */ 47 | + (instancetype)with:(NSArray *)kitClasses; 48 | 49 | /** 50 | * Returns the Fabric singleton object. 51 | */ 52 | + (instancetype)sharedSDK; 53 | 54 | /** 55 | * This BOOL enables or disables debug logging, such as kit version information. The default value is NO. 56 | */ 57 | @property (nonatomic, assign) BOOL debug; 58 | 59 | /** 60 | * Unavailable. Use `+sharedSDK` to retrieve the shared Fabric instance. 61 | */ 62 | - (id)init FAB_UNAVAILABLE("Use +sharedSDK to retrieve the shared Fabric instance."); 63 | 64 | @end 65 | 66 | NS_ASSUME_NONNULL_END 67 | 68 | -------------------------------------------------------------------------------- /Cognito/Internal/AWSCognitoConflict_Internal.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import "AWSCognitoConflict.h" 6 | 7 | @interface AWSCognitoRecordTuple () 8 | -(instancetype) initWithLocalRecord:(AWSCognitoRecord *)local remoteRecord:(AWSCognitoRecord *)remote; 9 | @end 10 | 11 | @interface AWSCognitoResolvedConflict() 12 | @property (nonatomic, readonly) AWSCognitoRecord *resolvedConflict; 13 | @property (nonatomic, readonly) AWSCognitoConflict *conflict; 14 | - (instancetype) initWithRemoteRecord:(AWSCognitoConflict *)conflict; 15 | - (instancetype) initWithLocalRecord:(AWSCognitoConflict *)conflict; 16 | - (instancetype) initWithValue:(AWSCognitoConflict *)conflict newValue:(NSString *)value; 17 | + (instancetype) resolvedConflictWithRemoteRecord:(AWSCognitoConflict *)conflict; 18 | + (instancetype) resolvedConflictWithLocalRecord:(AWSCognitoConflict *)conflict; 19 | + (instancetype) resolvedConflictWithValue:(AWSCognitoConflict *)conflict newValue:(NSString *)value; 20 | @end -------------------------------------------------------------------------------- /Cognito/Internal/AWSCognitoConstants.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import 6 | 7 | FOUNDATION_EXPORT NSString *const AWSCognitoDefaultSqliteDataTableName; 8 | FOUNDATION_EXPORT NSString *const AWSCognitoTableIdentityKeyName; 9 | FOUNDATION_EXPORT NSString *const AWSCognitoTableDatasetKeyName; 10 | FOUNDATION_EXPORT NSString *const AWSCognitoTableRecordKeyName; 11 | FOUNDATION_EXPORT NSString *const AWSCognitoUnknownIdentity; 12 | FOUNDATION_EXPORT NSString *const AWSCognitoRecordValueName; 13 | FOUNDATION_EXPORT NSString *const AWSCognitoDataFieldKeyName; 14 | FOUNDATION_EXPORT NSString *const AWSCognitoTypeFieldName; 15 | FOUNDATION_EXPORT NSString *const AWSCognitoLastModifiedFieldName; 16 | FOUNDATION_EXPORT NSString *const AWSCognitoModifiedByFieldName; 17 | FOUNDATION_EXPORT NSString *const AWSCognitoRecordCountFieldName; 18 | FOUNDATION_EXPORT NSString *const AWSCognitoDataStorageFieldName; 19 | FOUNDATION_EXPORT NSString *const AWSCognitoDatasetCreationDateFieldName; 20 | FOUNDATION_EXPORT NSString *const AWSCognitoDirtyFieldName; 21 | FOUNDATION_EXPORT NSString *const AWSCognitoSyncCountFieldName; 22 | FOUNDATION_EXPORT NSString *const AWSCognitoDefaultSqliteMetadataTableName; 23 | FOUNDATION_EXPORT NSString *const AWSCognitoDatasetFieldName; 24 | FOUNDATION_EXPORT NSString *const AWSCognitoLastSyncCount; 25 | 26 | FOUNDATION_EXPORT NSString* const AWSCognitoDeletedRecord; 27 | FOUNDATION_EXPORT int64_t const AWSCognitoNotSyncedDeletedRecordDirty; 28 | FOUNDATION_EXPORT NSString *const AWSCognitoUserDefaultsUserAgentPrefix; 29 | 30 | FOUNDATION_EXPORT uint32_t const AWSCognitoMaxSyncRetries; 31 | FOUNDATION_EXPORT BOOL const AWSCognitoSynchronizeOnWiFiOnly; 32 | 33 | FOUNDATION_EXPORT uint32_t const AWSCognitoMaxDatasetSize; 34 | FOUNDATION_EXPORT uint32_t const AWSCognitoMinKeySize; 35 | FOUNDATION_EXPORT uint32_t const AWSCognitoMaxKeySize; 36 | FOUNDATION_EXPORT uint32_t const AWSCognitoMaxRecordValueSize; 37 | FOUNDATION_EXPORT uint32_t const AWSCognitoMaxNumRecords; 38 | 39 | FOUNDATION_EXPORT NSString *const AWSCognitoSyncPushApns; 40 | FOUNDATION_EXPORT NSString *const AWSCognitoSyncPushApnsSandbox; 41 | 42 | #pragma mark - Standard error messages 43 | 44 | FOUNDATION_EXPORT NSString *const AWSCognitoErrorRemoteDataStorageFailedDescription; 45 | FOUNDATION_EXPORT NSString *const AWSCognitoErrorRemoteDataStorageFailedRecoverySuggestion; 46 | FOUNDATION_EXPORT NSString *const AWSCognitoErrorInvalidDataValueDescription; 47 | FOUNDATION_EXPORT NSString *const AWSCognitoErrorInvalidDataValueRecoverySuggestion; 48 | FOUNDATION_EXPORT NSString *const AWSCognitoErrorUserDataSizeLimitExceededDescription; 49 | FOUNDATION_EXPORT NSString *const AWSCognitoErrorUserDataSizeLimitExceededRecoverySuggestion; 50 | FOUNDATION_EXPORT NSString *const AWSCognitoErrorLocalDataStorageFailedDescription; 51 | FOUNDATION_EXPORT NSString *const AWSCognitoErrorLocalDataStorageFailedRecoverySuggestion; 52 | FOUNDATION_EXPORT NSString *const AWSCognitoErrorIllegalArgumentDescription; 53 | FOUNDATION_EXPORT NSString *const AWSCognitoErrorIllegalArgumentRecoverySuggestion; 54 | FOUNDATION_EXPORT NSString *const AWSCognitoErrorUnknownDataTypeDescription; 55 | FOUNDATION_EXPORT NSString *const AWSCognitoErrorUnknownDataTypeRecoverySuggestion; 56 | -------------------------------------------------------------------------------- /Cognito/Internal/AWSCognitoConstants.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import "AWSCognitoConstants.h" 6 | 7 | NSString *const AWSCognitoDefaultSqliteDataTableName = @"CognitoData"; 8 | NSString *const AWSCognitoTableDatasetKeyName = @"Dataset"; 9 | NSString *const AWSCognitoTableIdentityKeyName = @"IdentityId"; 10 | NSString *const AWSCognitoUnknownIdentity = @"UnknownId"; 11 | NSString *const AWSCognitoTableRecordKeyName = @"Key"; 12 | NSString *const AWSCognitoRecordValueName = @"Data"; 13 | NSString *const AWSCognitoDataFieldKeyName = @"v"; 14 | NSString *const AWSCognitoTypeFieldName = @"Type"; 15 | NSString *const AWSCognitoLastModifiedFieldName = @"LastModified"; 16 | NSString *const AWSCognitoModifiedByFieldName = @"ModifiedBy"; 17 | NSString *const AWSCognitoRecordCountFieldName = @"RecordCount"; 18 | NSString *const AWSCognitoDataStorageFieldName = @"DataStorage"; 19 | NSString *const AWSCognitoDatasetCreationDateFieldName = @"CreationDate"; 20 | NSString *const AWSCognitoDirtyFieldName = @"Dirty"; 21 | NSString *const AWSCognitoDatasetFieldName = @"Dataset"; 22 | NSString *const AWSCognitoSyncCountFieldName = @"SyncCount"; 23 | NSString *const AWSCognitoDefaultSqliteMetadataTableName = @"CognitoMetadata"; 24 | NSString *const AWSCognitoLastSyncCount = @"LastSyncCount"; 25 | int64_t const AWSCognitoNotSyncedDeletedRecordDirty = -1; 26 | NSString* const AWSCognitoDeletedRecord = @"\0"; 27 | NSString *const AWSCognitoUserDefaultsUserAgentPrefix = @"CognitoV1.0"; 28 | 29 | NSString *const AWSCognitoSyncPushApns = @"APNS"; 30 | NSString *const AWSCognitoSyncPushApnsSandbox = @"APNS_SANDBOX"; 31 | 32 | uint32_t const AWSCognitoMaxSyncRetries = 5; 33 | BOOL const AWSCognitoSynchronizeOnWiFiOnly = NO; 34 | 35 | uint32_t const AWSCognitoMaxDatasetSize = 1024*1024; 36 | uint32_t const AWSCognitoMinKeySize = 1; 37 | uint32_t const AWSCognitoMaxKeySize = 128; 38 | uint32_t const AWSCognitoMaxRecordValueSize = AWSCognitoMaxDatasetSize-1; 39 | uint32_t const AWSCognitoMaxNumRecords = 1024; 40 | 41 | 42 | #pragma mark - Standard error messages 43 | 44 | NSString *const AWSCognitoErrorRemoteDataStorageFailedDescription = @"The Amazon Cognito call failed."; 45 | NSString *const AWSCognitoErrorRemoteDataStorageFailedRecoverySuggestion = @"Try again later."; 46 | NSString *const AWSCognitoErrorInvalidDataValueDescription = @"The Amazon Cognito call failed. The value for the key is invalid and has been deleted from the local database."; 47 | NSString *const AWSCognitoErrorInvalidDataValueRecoverySuggestion = @"Investigate userInfo to retrieve the key and value of the failed request."; 48 | NSString *const AWSCognitoErrorUserDataSizeLimitExceededDescription = @"The Amazon Cognito call failed. An item collection is too large. For each dataset, the total sizes of keys and values cannot exceed 1 MB."; 49 | NSString *const AWSCognitoErrorUserDataSizeLimitExceededRecoverySuggestion = @"Fatal error."; 50 | NSString *const AWSCognitoErrorLocalDataStorageFailedDescription = @"The SQLite call failed."; 51 | NSString *const AWSCognitoErrorLocalDataStorageFailedRecoverySuggestion = @"Make sure you have enough disk space and the SQLite database file path is accessible."; 52 | NSString *const AWSCognitoErrorIllegalArgumentDescription = @"The input value is invalid."; 53 | NSString *const AWSCognitoErrorIllegalArgumentRecoverySuggestion = @"Make sure the input value is valid and try again."; 54 | NSString *const AWSCognitoErrorUnknownDataTypeDescription = @"The data type is not recognized by this library version."; 55 | NSString *const AWSCognitoErrorUnknownDataTypeRecoverySuggestion = @"Request the user upgrades to the latest version of your app."; 56 | NSString *const AWSCognitoDeviceNotOnWifiNetworkDescription = @"The WiFi network is unreachable at this time."; 57 | NSString *const AWSCognitoDeviceNotOnWifiNetworkRecoverySuggestion = @"Request the user connects to a WiFi network."; -------------------------------------------------------------------------------- /Cognito/Internal/AWSCognitoDataset_Internal.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import "AWSCognitoDataset.h" 6 | 7 | @class AWSCognitoSync; 8 | 9 | @interface AWSCognitoDatasetMetadata() 10 | 11 | @property (nonatomic, strong) NSString *name; 12 | @property (nonatomic, strong) NSNumber *lastSyncCount; 13 | @property (nonatomic, strong) NSDate *creationDate; 14 | @property (nonatomic, strong) NSNumber *dataStorage; 15 | @property (nonatomic, strong) NSString *lastModifiedBy; 16 | @property (nonatomic, strong) NSDate *lastModifiedDate; 17 | @property (nonatomic, strong) NSNumber *numRecords; 18 | 19 | @end 20 | 21 | @interface AWSCognitoDataset() 22 | 23 | /** 24 | * Use AWSCognitoClient.openOrCreateDataset to get a dataset. 25 | */ 26 | - (instancetype)initWithDatasetName:(NSString *)datasetName 27 | sqliteManager:(AWSCognitoSQLiteManager *)sqliteManager 28 | cognitoService:(AWSCognitoSync *)cognitoService; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Cognito/Internal/AWSCognitoRecord_Internal.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import "AWSCognitoRecord.h" 6 | 7 | @interface AWSCognitoRecordMetadata() 8 | 9 | @property (nonatomic, strong) NSDate *lastModified; 10 | 11 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary; 12 | 13 | @end 14 | 15 | @interface AWSCognitoRecord() 16 | 17 | /** 18 | * Initializes a AWSCognitoRecord with the values from a dictionary. 19 | * 20 | * @param dictionary The dictionary must contain a mapping of NSStrings to NSStrings. 21 | */ 22 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary; 23 | 24 | /** 25 | * Returns a copy of the AWSCognitoRecord with the last written time updated to the current time and the version number set based on the dirty count. 26 | * 27 | */ 28 | - (AWSCognitoRecord *)copyForFlush; 29 | 30 | @end 31 | 32 | @interface AWSCognitoRecordValue() 33 | 34 | @property (nonatomic, assign) AWSCognitoRecordValueType type; 35 | @property (nonatomic, strong) NSObject *stringValue; 36 | 37 | 38 | - (instancetype)initWithString:(NSString *)value 39 | type:(AWSCognitoRecordValueType)type; 40 | 41 | - (NSString *)toJsonString; 42 | - (instancetype)initWithJson:(NSString *)json 43 | type:(AWSCognitoRecordValueType)type; 44 | @end -------------------------------------------------------------------------------- /Cognito/Internal/AWSCognitoSQLiteManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import 6 | 7 | @class AWSCognitoRecord; 8 | @class AWSCognitoDatasetMetadata; 9 | 10 | @interface AWSCognitoSQLiteManager : NSObject 11 | 12 | @property (nonatomic, strong) NSString *identityId; 13 | @property (nonatomic, strong) NSString *deviceId; 14 | 15 | 16 | - (instancetype)initWithIdentityId:(NSString *)identityId deviceId:(NSString *)deviceId; 17 | - (void)initializeDatasetTables:(NSString *) datasetName; 18 | - (void)deleteAllData; 19 | - (void)deleteSQLiteDatabase; 20 | 21 | - (NSArray *)getDatasets:(NSError **)error; 22 | - (void)loadDatasetMetadata:(AWSCognitoDatasetMetadata *)dataset error:(NSError **)error; 23 | - (BOOL)putDatasetMetadata:(NSArray *)datasets error:(NSError **)error; 24 | - (AWSCognitoRecord *)getRecordById:(NSString *)recordId datasetName:(NSString *)datasetName error:(NSError **)error; 25 | - (BOOL)putRecord:(AWSCognitoRecord *)record datasetName:(NSString *)datasetName error:(NSError **)error; 26 | - (BOOL)flagRecordAsDeletedById:(NSString *)recordId datasetName:(NSString *)datasetName error:(NSError **)error; 27 | - (BOOL)deleteRecordById:(NSString *)recordId datasetName:(NSString *)datasetName error:(NSError **)error; 28 | - (BOOL)deleteDataset:(NSString *)datasetName error:(NSError **)error; 29 | - (BOOL)deleteMetadata:(NSString *)datasetName error:(NSError **)error; 30 | - (BOOL)updateWithRemoteChanges:(NSString *)datasetName nonConflicts:(NSArray *)nonConflictRecords resolvedConflicts:(NSArray *)resolvedConflicts error:(NSError **)error; 31 | - (BOOL)updateLocalRecordMetadata:(NSString *)datasetName records:(NSArray *)updatedRecords error:(NSError **)error; 32 | - (BOOL)resetSyncCount:(NSString *)datasetName error:(NSError **)error; 33 | 34 | - (NSNumber *) numRecords:(NSString *)datasetName; 35 | 36 | - (NSArray *)getMergeDatasets:(NSString *)datasetName error:(NSError **)error; 37 | - (BOOL)reparentDatasets:(NSString *)oldId withNewId:(NSString *)newId error:(NSError **)error; 38 | 39 | - (NSArray *)allRecords:(NSString *)datasetName; 40 | - (NSDictionary *)recordsUpdatedAfterLastSync:(NSString *)datasetName error:(NSError **)error; 41 | 42 | - (NSNumber *)lastSyncCount:(NSString *)datasetName; 43 | - (void)updateLastSyncCount:(NSString *)datasetName syncCount:(NSNumber *)syncCount lastModifiedBy:(NSString *)lastModifiedBy; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Cognito/Internal/AWSCognitoUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import "AWSCognitoRecord.h" 6 | #import "AWSCognitoSyncModel.h" 7 | 8 | @interface AWSCognitoUtil : NSObject 9 | 10 | /** 11 | * Convert milliseconds since epoch to NSDate, with clock skew adjustment for the given date. 12 | * 13 | * @param millisSinceEpoch number of milliseconds since epoch 14 | * 15 | * @return NSDate 16 | */ 17 | + (NSDate *)millisSinceEpochToDate:(NSNumber *)millisSinceEpoch; 18 | 19 | /** 20 | * Convert seconds since epoch to NSDate, with clock skew adjustment for the given date. 21 | * 22 | * @param secondsSinceEpoch number of seconds since epoch 23 | * 24 | * @return NSDate 25 | */ 26 | + (NSDate *)secondsSinceEpochToDate:(NSNumber *)secondsSinceEpoch; 27 | 28 | 29 | /** 30 | * Get the epoch time in milliseconds, with clock skew adjustment for the given date. 31 | * 32 | * @param date The date to be converted to milliseconds 33 | * 34 | * @return The epoch time in milliseconds as a long long 35 | */ 36 | + (long long)getTimeMillisForDate:(NSDate *)date; 37 | 38 | + (NSError *)errorRemoteDataStorageFailed:(NSString *)failureReason; 39 | + (NSError *)errorInvalidDataValue:(NSString *)failureReason key:(NSString *)key value:(id)value; 40 | + (NSError *)errorUserDataSizeLimitExceeded:(NSString *)failureReason; 41 | + (NSError *)errorLocalDataStorageFailed:(NSString *)failureReason; 42 | + (NSError *)errorIllegalArgument:(NSString *)failureReason; 43 | 44 | + (id)retrieveValue:(AWSCognitoRecordValue *)value; 45 | 46 | + (BOOL)isValidRecordValueType:(AWSCognitoRecordValueType)type; 47 | 48 | /** 49 | * Get the push platform string for this build target 50 | */ 51 | + (NSString *) pushPlatformString:(AWSCognitoSyncPlatform) pushPlatform; 52 | 53 | /** 54 | * Get the push platform for this build target 55 | */ 56 | + (AWSCognitoSyncPlatform) pushPlatform; 57 | 58 | /** 59 | * Get the device id key for this push platform string 60 | */ 61 | + (NSString *) deviceIdKey:(AWSCognitoSyncPlatform) pushPlatformString; 62 | 63 | /** 64 | * Get the device identity key for this push platform string 65 | */ 66 | + (NSString *) deviceIdentityKey:(AWSCognitoSyncPlatform) pushPlatformString; 67 | @end 68 | -------------------------------------------------------------------------------- /Cognito/Internal/AWSCognitoUtil.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | 5 | #import "AWSCognitoService.h" 6 | #import "AWSCognitoUtil.h" 7 | 8 | #import 9 | #import "AWSCognitoConstants.h" 10 | #import "AWSCognitoRecord_Internal.h" 11 | 12 | @implementation AWSCognitoUtil 13 | 14 | +(NSDate *)millisSinceEpochToDate:(NSNumber *)millisSinceEpoch 15 | { 16 | return [NSDate dateWithTimeIntervalSince1970:([millisSinceEpoch doubleValue] / 1000)]; 17 | } 18 | 19 | +(NSDate *)secondsSinceEpochToDate:(NSNumber *)secondsSinceEpoch 20 | { 21 | return [NSDate dateWithTimeIntervalSince1970:([secondsSinceEpoch doubleValue])]; 22 | } 23 | 24 | 25 | + (long long)getTimeMillisForDate:(NSDate *)date 26 | { 27 | if (date == nil) 28 | { 29 | date = [NSDate date]; 30 | } 31 | NSTimeInterval epochSeconds = [date timeIntervalSince1970]; 32 | NSTimeInterval adjustedSeconds = [[AWSCognitoUtil secondsSinceEpochToDate:[NSNumber numberWithDouble:epochSeconds]] timeIntervalSince1970]; 33 | long long adjustedMilliseconds = round(adjustedSeconds * 1000); 34 | 35 | return adjustedMilliseconds; 36 | } 37 | 38 | + (NSString *)hexEncode:(NSString *)string 39 | { 40 | NSUInteger len = [string length]; 41 | unichar *chars = malloc(len * sizeof(unichar)); 42 | 43 | [string getCharacters:chars]; 44 | 45 | NSMutableString *hexString = [[NSMutableString alloc] init]; 46 | for (NSUInteger i = 0; i < len; i++) { 47 | if ((int)chars[i] < 16) { 48 | [hexString appendString:@"0"]; 49 | } 50 | [hexString appendString:[NSString stringWithFormat:@"%x", chars[i]]]; 51 | } 52 | free(chars); 53 | 54 | return hexString; 55 | } 56 | 57 | #pragma mark - Error object generations 58 | 59 | + (NSError *)errorRemoteDataStorageFailed:(NSString *)failureReason 60 | { 61 | NSDictionary *userInfo = nil; 62 | if(failureReason) 63 | { 64 | userInfo = @{NSLocalizedDescriptionKey : AWSCognitoErrorRemoteDataStorageFailedDescription, 65 | NSLocalizedFailureReasonErrorKey : failureReason, 66 | NSLocalizedRecoverySuggestionErrorKey : AWSCognitoErrorRemoteDataStorageFailedRecoverySuggestion}; 67 | } 68 | else 69 | { 70 | userInfo = @{NSLocalizedDescriptionKey : AWSCognitoErrorRemoteDataStorageFailedDescription, 71 | NSLocalizedRecoverySuggestionErrorKey : AWSCognitoErrorRemoteDataStorageFailedRecoverySuggestion}; 72 | } 73 | 74 | return [NSError errorWithDomain:AWSCognitoErrorDomain 75 | code:AWSCognitoErrorRemoteDataStorageFailed 76 | userInfo:userInfo]; 77 | } 78 | 79 | + (NSError *)errorInvalidDataValue:(NSString *)failureReason key:(NSString *)key value:(id)value 80 | { 81 | NSDictionary *userInfo = nil; 82 | if(failureReason) 83 | { 84 | userInfo = @{NSLocalizedDescriptionKey : AWSCognitoErrorInvalidDataValueDescription, 85 | NSLocalizedFailureReasonErrorKey : failureReason, 86 | NSLocalizedRecoverySuggestionErrorKey : AWSCognitoErrorInvalidDataValueRecoverySuggestion, 87 | @"key" : key, 88 | @"value" : value}; 89 | } 90 | else 91 | { 92 | userInfo = @{NSLocalizedDescriptionKey : AWSCognitoErrorInvalidDataValueDescription, 93 | NSLocalizedRecoverySuggestionErrorKey : AWSCognitoErrorInvalidDataValueRecoverySuggestion}; 94 | } 95 | 96 | return [NSError errorWithDomain:AWSCognitoErrorDomain 97 | code:AWSCognitoErrorInvalidDataValue 98 | userInfo:userInfo]; 99 | } 100 | 101 | + (NSError *)errorUserDataSizeLimitExceeded:(NSString *)failureReason 102 | { 103 | NSDictionary *userInfo = nil; 104 | if(failureReason) 105 | { 106 | userInfo = @{NSLocalizedDescriptionKey : AWSCognitoErrorUserDataSizeLimitExceededDescription, 107 | NSLocalizedFailureReasonErrorKey : failureReason, 108 | NSLocalizedRecoverySuggestionErrorKey : AWSCognitoErrorUserDataSizeLimitExceededRecoverySuggestion}; 109 | } 110 | else 111 | { 112 | userInfo = @{NSLocalizedDescriptionKey : AWSCognitoErrorUserDataSizeLimitExceededDescription, 113 | NSLocalizedRecoverySuggestionErrorKey : AWSCognitoErrorUserDataSizeLimitExceededRecoverySuggestion}; 114 | } 115 | 116 | return [NSError errorWithDomain:AWSCognitoErrorDomain 117 | code:AWSCognitoErrorUserDataSizeLimitExceeded 118 | userInfo:userInfo]; 119 | } 120 | 121 | + (NSError *)errorLocalDataStorageFailed:(NSString *)failureReason 122 | { 123 | NSDictionary *userInfo = nil; 124 | if(failureReason) 125 | { 126 | userInfo = @{NSLocalizedDescriptionKey : AWSCognitoErrorLocalDataStorageFailedDescription, 127 | NSLocalizedFailureReasonErrorKey : failureReason, 128 | NSLocalizedRecoverySuggestionErrorKey : AWSCognitoErrorLocalDataStorageFailedRecoverySuggestion}; 129 | } 130 | else 131 | { 132 | userInfo = @{NSLocalizedDescriptionKey : AWSCognitoErrorLocalDataStorageFailedDescription, 133 | NSLocalizedRecoverySuggestionErrorKey : AWSCognitoErrorLocalDataStorageFailedRecoverySuggestion}; 134 | } 135 | 136 | return [NSError errorWithDomain:AWSCognitoErrorDomain 137 | code:AWSCognitoErrorLocalDataStorageFailed 138 | userInfo:userInfo]; 139 | } 140 | 141 | + (NSError *)errorIllegalArgument:(NSString *)failureReason 142 | { 143 | NSDictionary *userInfo = nil; 144 | if(failureReason) 145 | { 146 | userInfo = @{NSLocalizedDescriptionKey : AWSCognitoErrorIllegalArgumentDescription, 147 | NSLocalizedFailureReasonErrorKey : failureReason, 148 | NSLocalizedRecoverySuggestionErrorKey : AWSCognitoErrorIllegalArgumentRecoverySuggestion}; 149 | } 150 | else 151 | { 152 | userInfo = @{NSLocalizedDescriptionKey : AWSCognitoErrorIllegalArgumentDescription, 153 | NSLocalizedRecoverySuggestionErrorKey : AWSCognitoErrorIllegalArgumentRecoverySuggestion}; 154 | } 155 | 156 | return [NSError errorWithDomain:AWSCognitoErrorDomain 157 | code:AWSCognitoErrorIllegalArgument 158 | userInfo:userInfo]; 159 | } 160 | 161 | #pragma mark - Sets and array conversion helpers 162 | 163 | + (id)retrieveValue:(AWSCognitoRecordValue *)value { 164 | if(value.type == AWSCognitoRecordValueTypeString) { 165 | return value.string; 166 | } 167 | 168 | return nil; 169 | } 170 | 171 | #pragma mark Type validation 172 | + (BOOL)isValidRecordValueType:(AWSCognitoRecordValueType)type { 173 | return type >= AWSCognitoRecordValueTypeUnknown && type <= AWSCognitoRecordValueTypeDeleted; 174 | } 175 | 176 | 177 | #pragma mark Push notifications 178 | + (NSString *) pushPlatformString: (AWSCognitoSyncPlatform) pushPlatform { 179 | return (AWSCognitoSyncPlatformApns == pushPlatform)? AWSCognitoSyncPushApns : AWSCognitoSyncPushApnsSandbox; 180 | } 181 | 182 | + (AWSCognitoSyncPlatform) pushPlatform { 183 | #ifdef DEBUG 184 | return AWSCognitoSyncPlatformApnsSandbox; 185 | #else 186 | return AWSCognitoSyncPlatformApns; 187 | #endif 188 | } 189 | 190 | + (NSString *) deviceIdKey:(AWSCognitoSyncPlatform) pushPlatform { 191 | return [NSString stringWithFormat:@"Cognito-%@-DeviceId", [AWSCognitoUtil pushPlatformString:pushPlatform]]; 192 | } 193 | 194 | + (NSString *) deviceIdentityKey:(AWSCognitoSyncPlatform) pushPlatform { 195 | return [NSString stringWithFormat:@"Cognito-%@-DeviceIdentity", [AWSCognitoUtil pushPlatformString:pushPlatform]]; 196 | } 197 | 198 | @end 199 | -------------------------------------------------------------------------------- /Cognito/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module AWSCognito { 2 | umbrella header "AWSCognito.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /CognitoSync/AWSCognitoSync.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import 17 | #import 18 | #import "AWSCognitoSyncService.h" 19 | -------------------------------------------------------------------------------- /CognitoSync/AWSCognitoSyncModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import "AWSCognitoSyncModel.h" 17 | #import 18 | 19 | NSString *const AWSCognitoSyncErrorDomain = @"com.amazonaws.AWSCognitoSyncErrorDomain"; 20 | 21 | @implementation AWSCognitoSyncBulkPublishRequest 22 | 23 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 24 | return @{ 25 | @"identityPoolId" : @"IdentityPoolId", 26 | }; 27 | } 28 | 29 | @end 30 | 31 | @implementation AWSCognitoSyncBulkPublishResponse 32 | 33 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 34 | return @{ 35 | @"identityPoolId" : @"IdentityPoolId", 36 | }; 37 | } 38 | 39 | @end 40 | 41 | @implementation AWSCognitoSyncCognitoStreams 42 | 43 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 44 | return @{ 45 | @"roleArn" : @"RoleArn", 46 | @"streamName" : @"StreamName", 47 | @"streamingStatus" : @"StreamingStatus", 48 | }; 49 | } 50 | 51 | + (NSValueTransformer *)streamingStatusJSONTransformer { 52 | return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^NSNumber *(NSString *value) { 53 | if ([value isEqualToString:@"ENABLED"]) { 54 | return @(AWSCognitoSyncStreamingStatusEnabled); 55 | } 56 | if ([value isEqualToString:@"DISABLED"]) { 57 | return @(AWSCognitoSyncStreamingStatusDisabled); 58 | } 59 | return @(AWSCognitoSyncStreamingStatusUnknown); 60 | } reverseBlock:^NSString *(NSNumber *value) { 61 | switch ([value integerValue]) { 62 | case AWSCognitoSyncStreamingStatusEnabled: 63 | return @"ENABLED"; 64 | case AWSCognitoSyncStreamingStatusDisabled: 65 | return @"DISABLED"; 66 | case AWSCognitoSyncStreamingStatusUnknown: 67 | default: 68 | return nil; 69 | } 70 | }]; 71 | } 72 | 73 | @end 74 | 75 | @implementation AWSCognitoSyncDataset 76 | 77 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 78 | return @{ 79 | @"creationDate" : @"CreationDate", 80 | @"dataStorage" : @"DataStorage", 81 | @"datasetName" : @"DatasetName", 82 | @"identityId" : @"IdentityId", 83 | @"lastModifiedBy" : @"LastModifiedBy", 84 | @"lastModifiedDate" : @"LastModifiedDate", 85 | @"numRecords" : @"NumRecords", 86 | }; 87 | } 88 | 89 | + (NSValueTransformer *)creationDateJSONTransformer { 90 | return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSNumber *number) { 91 | return [NSDate dateWithTimeIntervalSince1970:[number doubleValue]]; 92 | } reverseBlock:^id(NSDate *date) { 93 | return [NSString stringWithFormat:@"%f", [date timeIntervalSince1970]]; 94 | }]; 95 | } 96 | 97 | + (NSValueTransformer *)lastModifiedDateJSONTransformer { 98 | return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSNumber *number) { 99 | return [NSDate dateWithTimeIntervalSince1970:[number doubleValue]]; 100 | } reverseBlock:^id(NSDate *date) { 101 | return [NSString stringWithFormat:@"%f", [date timeIntervalSince1970]]; 102 | }]; 103 | } 104 | 105 | @end 106 | 107 | @implementation AWSCognitoSyncDeleteDatasetRequest 108 | 109 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 110 | return @{ 111 | @"datasetName" : @"DatasetName", 112 | @"identityId" : @"IdentityId", 113 | @"identityPoolId" : @"IdentityPoolId", 114 | }; 115 | } 116 | 117 | @end 118 | 119 | @implementation AWSCognitoSyncDeleteDatasetResponse 120 | 121 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 122 | return @{ 123 | @"dataset" : @"Dataset", 124 | }; 125 | } 126 | 127 | + (NSValueTransformer *)datasetJSONTransformer { 128 | return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSCognitoSyncDataset class]]; 129 | } 130 | 131 | @end 132 | 133 | @implementation AWSCognitoSyncDescribeDatasetRequest 134 | 135 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 136 | return @{ 137 | @"datasetName" : @"DatasetName", 138 | @"identityId" : @"IdentityId", 139 | @"identityPoolId" : @"IdentityPoolId", 140 | }; 141 | } 142 | 143 | @end 144 | 145 | @implementation AWSCognitoSyncDescribeDatasetResponse 146 | 147 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 148 | return @{ 149 | @"dataset" : @"Dataset", 150 | }; 151 | } 152 | 153 | + (NSValueTransformer *)datasetJSONTransformer { 154 | return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSCognitoSyncDataset class]]; 155 | } 156 | 157 | @end 158 | 159 | @implementation AWSCognitoSyncDescribeIdentityPoolUsageRequest 160 | 161 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 162 | return @{ 163 | @"identityPoolId" : @"IdentityPoolId", 164 | }; 165 | } 166 | 167 | @end 168 | 169 | @implementation AWSCognitoSyncDescribeIdentityPoolUsageResponse 170 | 171 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 172 | return @{ 173 | @"identityPoolUsage" : @"IdentityPoolUsage", 174 | }; 175 | } 176 | 177 | + (NSValueTransformer *)identityPoolUsageJSONTransformer { 178 | return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSCognitoSyncIdentityPoolUsage class]]; 179 | } 180 | 181 | @end 182 | 183 | @implementation AWSCognitoSyncDescribeIdentityUsageRequest 184 | 185 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 186 | return @{ 187 | @"identityId" : @"IdentityId", 188 | @"identityPoolId" : @"IdentityPoolId", 189 | }; 190 | } 191 | 192 | @end 193 | 194 | @implementation AWSCognitoSyncDescribeIdentityUsageResponse 195 | 196 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 197 | return @{ 198 | @"identityUsage" : @"IdentityUsage", 199 | }; 200 | } 201 | 202 | + (NSValueTransformer *)identityUsageJSONTransformer { 203 | return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSCognitoSyncIdentityUsage class]]; 204 | } 205 | 206 | @end 207 | 208 | @implementation AWSCognitoSyncGetBulkPublishDetailsRequest 209 | 210 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 211 | return @{ 212 | @"identityPoolId" : @"IdentityPoolId", 213 | }; 214 | } 215 | 216 | @end 217 | 218 | @implementation AWSCognitoSyncGetBulkPublishDetailsResponse 219 | 220 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 221 | return @{ 222 | @"bulkPublishCompleteTime" : @"BulkPublishCompleteTime", 223 | @"bulkPublishStartTime" : @"BulkPublishStartTime", 224 | @"bulkPublishStatus" : @"BulkPublishStatus", 225 | @"failureMessage" : @"FailureMessage", 226 | @"identityPoolId" : @"IdentityPoolId", 227 | }; 228 | } 229 | 230 | + (NSValueTransformer *)bulkPublishCompleteTimeJSONTransformer { 231 | return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSNumber *number) { 232 | return [NSDate dateWithTimeIntervalSince1970:[number doubleValue]]; 233 | } reverseBlock:^id(NSDate *date) { 234 | return [NSString stringWithFormat:@"%f", [date timeIntervalSince1970]]; 235 | }]; 236 | } 237 | 238 | + (NSValueTransformer *)bulkPublishStartTimeJSONTransformer { 239 | return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSNumber *number) { 240 | return [NSDate dateWithTimeIntervalSince1970:[number doubleValue]]; 241 | } reverseBlock:^id(NSDate *date) { 242 | return [NSString stringWithFormat:@"%f", [date timeIntervalSince1970]]; 243 | }]; 244 | } 245 | 246 | + (NSValueTransformer *)bulkPublishStatusJSONTransformer { 247 | return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^NSNumber *(NSString *value) { 248 | if ([value isEqualToString:@"NOT_STARTED"]) { 249 | return @(AWSCognitoSyncBulkPublishStatusNotStarted); 250 | } 251 | if ([value isEqualToString:@"IN_PROGRESS"]) { 252 | return @(AWSCognitoSyncBulkPublishStatusInProgress); 253 | } 254 | if ([value isEqualToString:@"FAILED"]) { 255 | return @(AWSCognitoSyncBulkPublishStatusFailed); 256 | } 257 | if ([value isEqualToString:@"SUCCEEDED"]) { 258 | return @(AWSCognitoSyncBulkPublishStatusSucceeded); 259 | } 260 | return @(AWSCognitoSyncBulkPublishStatusUnknown); 261 | } reverseBlock:^NSString *(NSNumber *value) { 262 | switch ([value integerValue]) { 263 | case AWSCognitoSyncBulkPublishStatusNotStarted: 264 | return @"NOT_STARTED"; 265 | case AWSCognitoSyncBulkPublishStatusInProgress: 266 | return @"IN_PROGRESS"; 267 | case AWSCognitoSyncBulkPublishStatusFailed: 268 | return @"FAILED"; 269 | case AWSCognitoSyncBulkPublishStatusSucceeded: 270 | return @"SUCCEEDED"; 271 | case AWSCognitoSyncBulkPublishStatusUnknown: 272 | default: 273 | return nil; 274 | } 275 | }]; 276 | } 277 | 278 | @end 279 | 280 | @implementation AWSCognitoSyncGetCognitoEventsRequest 281 | 282 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 283 | return @{ 284 | @"identityPoolId" : @"IdentityPoolId", 285 | }; 286 | } 287 | 288 | @end 289 | 290 | @implementation AWSCognitoSyncGetCognitoEventsResponse 291 | 292 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 293 | return @{ 294 | @"events" : @"Events", 295 | }; 296 | } 297 | 298 | @end 299 | 300 | @implementation AWSCognitoSyncGetIdentityPoolConfigurationRequest 301 | 302 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 303 | return @{ 304 | @"identityPoolId" : @"IdentityPoolId", 305 | }; 306 | } 307 | 308 | @end 309 | 310 | @implementation AWSCognitoSyncGetIdentityPoolConfigurationResponse 311 | 312 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 313 | return @{ 314 | @"cognitoStreams" : @"CognitoStreams", 315 | @"identityPoolId" : @"IdentityPoolId", 316 | @"pushSync" : @"PushSync", 317 | }; 318 | } 319 | 320 | + (NSValueTransformer *)cognitoStreamsJSONTransformer { 321 | return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSCognitoSyncCognitoStreams class]]; 322 | } 323 | 324 | + (NSValueTransformer *)pushSyncJSONTransformer { 325 | return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSCognitoSyncPushSync class]]; 326 | } 327 | 328 | @end 329 | 330 | @implementation AWSCognitoSyncIdentityPoolUsage 331 | 332 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 333 | return @{ 334 | @"dataStorage" : @"DataStorage", 335 | @"identityPoolId" : @"IdentityPoolId", 336 | @"lastModifiedDate" : @"LastModifiedDate", 337 | @"syncSessionsCount" : @"SyncSessionsCount", 338 | }; 339 | } 340 | 341 | + (NSValueTransformer *)lastModifiedDateJSONTransformer { 342 | return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSNumber *number) { 343 | return [NSDate dateWithTimeIntervalSince1970:[number doubleValue]]; 344 | } reverseBlock:^id(NSDate *date) { 345 | return [NSString stringWithFormat:@"%f", [date timeIntervalSince1970]]; 346 | }]; 347 | } 348 | 349 | @end 350 | 351 | @implementation AWSCognitoSyncIdentityUsage 352 | 353 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 354 | return @{ 355 | @"dataStorage" : @"DataStorage", 356 | @"datasetCount" : @"DatasetCount", 357 | @"identityId" : @"IdentityId", 358 | @"identityPoolId" : @"IdentityPoolId", 359 | @"lastModifiedDate" : @"LastModifiedDate", 360 | }; 361 | } 362 | 363 | + (NSValueTransformer *)lastModifiedDateJSONTransformer { 364 | return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSNumber *number) { 365 | return [NSDate dateWithTimeIntervalSince1970:[number doubleValue]]; 366 | } reverseBlock:^id(NSDate *date) { 367 | return [NSString stringWithFormat:@"%f", [date timeIntervalSince1970]]; 368 | }]; 369 | } 370 | 371 | @end 372 | 373 | @implementation AWSCognitoSyncListDatasetsRequest 374 | 375 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 376 | return @{ 377 | @"identityId" : @"IdentityId", 378 | @"identityPoolId" : @"IdentityPoolId", 379 | @"maxResults" : @"MaxResults", 380 | @"nextToken" : @"NextToken", 381 | }; 382 | } 383 | 384 | @end 385 | 386 | @implementation AWSCognitoSyncListDatasetsResponse 387 | 388 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 389 | return @{ 390 | @"count" : @"Count", 391 | @"datasets" : @"Datasets", 392 | @"nextToken" : @"NextToken", 393 | }; 394 | } 395 | 396 | + (NSValueTransformer *)datasetsJSONTransformer { 397 | return [NSValueTransformer awsmtl_JSONArrayTransformerWithModelClass:[AWSCognitoSyncDataset class]]; 398 | } 399 | 400 | @end 401 | 402 | @implementation AWSCognitoSyncListIdentityPoolUsageRequest 403 | 404 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 405 | return @{ 406 | @"maxResults" : @"MaxResults", 407 | @"nextToken" : @"NextToken", 408 | }; 409 | } 410 | 411 | @end 412 | 413 | @implementation AWSCognitoSyncListIdentityPoolUsageResponse 414 | 415 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 416 | return @{ 417 | @"count" : @"Count", 418 | @"identityPoolUsages" : @"IdentityPoolUsages", 419 | @"maxResults" : @"MaxResults", 420 | @"nextToken" : @"NextToken", 421 | }; 422 | } 423 | 424 | + (NSValueTransformer *)identityPoolUsagesJSONTransformer { 425 | return [NSValueTransformer awsmtl_JSONArrayTransformerWithModelClass:[AWSCognitoSyncIdentityPoolUsage class]]; 426 | } 427 | 428 | @end 429 | 430 | @implementation AWSCognitoSyncListRecordsRequest 431 | 432 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 433 | return @{ 434 | @"datasetName" : @"DatasetName", 435 | @"identityId" : @"IdentityId", 436 | @"identityPoolId" : @"IdentityPoolId", 437 | @"lastSyncCount" : @"LastSyncCount", 438 | @"maxResults" : @"MaxResults", 439 | @"nextToken" : @"NextToken", 440 | @"syncSessionToken" : @"SyncSessionToken", 441 | }; 442 | } 443 | 444 | @end 445 | 446 | @implementation AWSCognitoSyncListRecordsResponse 447 | 448 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 449 | return @{ 450 | @"count" : @"Count", 451 | @"datasetDeletedAfterRequestedSyncCount" : @"DatasetDeletedAfterRequestedSyncCount", 452 | @"datasetExists" : @"DatasetExists", 453 | @"datasetSyncCount" : @"DatasetSyncCount", 454 | @"lastModifiedBy" : @"LastModifiedBy", 455 | @"mergedDatasetNames" : @"MergedDatasetNames", 456 | @"nextToken" : @"NextToken", 457 | @"records" : @"Records", 458 | @"syncSessionToken" : @"SyncSessionToken", 459 | }; 460 | } 461 | 462 | + (NSValueTransformer *)recordsJSONTransformer { 463 | return [NSValueTransformer awsmtl_JSONArrayTransformerWithModelClass:[AWSCognitoSyncRecord class]]; 464 | } 465 | 466 | @end 467 | 468 | @implementation AWSCognitoSyncPushSync 469 | 470 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 471 | return @{ 472 | @"applicationArns" : @"ApplicationArns", 473 | @"roleArn" : @"RoleArn", 474 | }; 475 | } 476 | 477 | @end 478 | 479 | @implementation AWSCognitoSyncRecord 480 | 481 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 482 | return @{ 483 | @"deviceLastModifiedDate" : @"DeviceLastModifiedDate", 484 | @"key" : @"Key", 485 | @"lastModifiedBy" : @"LastModifiedBy", 486 | @"lastModifiedDate" : @"LastModifiedDate", 487 | @"syncCount" : @"SyncCount", 488 | @"value" : @"Value", 489 | }; 490 | } 491 | 492 | + (NSValueTransformer *)deviceLastModifiedDateJSONTransformer { 493 | return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSNumber *number) { 494 | return [NSDate dateWithTimeIntervalSince1970:[number doubleValue]]; 495 | } reverseBlock:^id(NSDate *date) { 496 | return [NSString stringWithFormat:@"%f", [date timeIntervalSince1970]]; 497 | }]; 498 | } 499 | 500 | + (NSValueTransformer *)lastModifiedDateJSONTransformer { 501 | return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSNumber *number) { 502 | return [NSDate dateWithTimeIntervalSince1970:[number doubleValue]]; 503 | } reverseBlock:^id(NSDate *date) { 504 | return [NSString stringWithFormat:@"%f", [date timeIntervalSince1970]]; 505 | }]; 506 | } 507 | 508 | @end 509 | 510 | @implementation AWSCognitoSyncRecordPatch 511 | 512 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 513 | return @{ 514 | @"deviceLastModifiedDate" : @"DeviceLastModifiedDate", 515 | @"key" : @"Key", 516 | @"op" : @"Op", 517 | @"syncCount" : @"SyncCount", 518 | @"value" : @"Value", 519 | }; 520 | } 521 | 522 | + (NSValueTransformer *)deviceLastModifiedDateJSONTransformer { 523 | return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSNumber *number) { 524 | return [NSDate dateWithTimeIntervalSince1970:[number doubleValue]]; 525 | } reverseBlock:^id(NSDate *date) { 526 | return [NSString stringWithFormat:@"%f", [date timeIntervalSince1970]]; 527 | }]; 528 | } 529 | 530 | + (NSValueTransformer *)opJSONTransformer { 531 | return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^NSNumber *(NSString *value) { 532 | if ([value isEqualToString:@"replace"]) { 533 | return @(AWSCognitoSyncOperationReplace); 534 | } 535 | if ([value isEqualToString:@"remove"]) { 536 | return @(AWSCognitoSyncOperationRemove); 537 | } 538 | return @(AWSCognitoSyncOperationUnknown); 539 | } reverseBlock:^NSString *(NSNumber *value) { 540 | switch ([value integerValue]) { 541 | case AWSCognitoSyncOperationReplace: 542 | return @"replace"; 543 | case AWSCognitoSyncOperationRemove: 544 | return @"remove"; 545 | case AWSCognitoSyncOperationUnknown: 546 | default: 547 | return nil; 548 | } 549 | }]; 550 | } 551 | 552 | @end 553 | 554 | @implementation AWSCognitoSyncRegisterDeviceRequest 555 | 556 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 557 | return @{ 558 | @"identityId" : @"IdentityId", 559 | @"identityPoolId" : @"IdentityPoolId", 560 | @"platform" : @"Platform", 561 | @"token" : @"Token", 562 | }; 563 | } 564 | 565 | + (NSValueTransformer *)platformJSONTransformer { 566 | return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^NSNumber *(NSString *value) { 567 | if ([value isEqualToString:@"APNS"]) { 568 | return @(AWSCognitoSyncPlatformApns); 569 | } 570 | if ([value isEqualToString:@"APNS_SANDBOX"]) { 571 | return @(AWSCognitoSyncPlatformApnsSandbox); 572 | } 573 | if ([value isEqualToString:@"GCM"]) { 574 | return @(AWSCognitoSyncPlatformGcm); 575 | } 576 | if ([value isEqualToString:@"ADM"]) { 577 | return @(AWSCognitoSyncPlatformAdm); 578 | } 579 | return @(AWSCognitoSyncPlatformUnknown); 580 | } reverseBlock:^NSString *(NSNumber *value) { 581 | switch ([value integerValue]) { 582 | case AWSCognitoSyncPlatformApns: 583 | return @"APNS"; 584 | case AWSCognitoSyncPlatformApnsSandbox: 585 | return @"APNS_SANDBOX"; 586 | case AWSCognitoSyncPlatformGcm: 587 | return @"GCM"; 588 | case AWSCognitoSyncPlatformAdm: 589 | return @"ADM"; 590 | case AWSCognitoSyncPlatformUnknown: 591 | default: 592 | return nil; 593 | } 594 | }]; 595 | } 596 | 597 | @end 598 | 599 | @implementation AWSCognitoSyncRegisterDeviceResponse 600 | 601 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 602 | return @{ 603 | @"deviceId" : @"DeviceId", 604 | }; 605 | } 606 | 607 | @end 608 | 609 | @implementation AWSCognitoSyncSetCognitoEventsRequest 610 | 611 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 612 | return @{ 613 | @"events" : @"Events", 614 | @"identityPoolId" : @"IdentityPoolId", 615 | }; 616 | } 617 | 618 | @end 619 | 620 | @implementation AWSCognitoSyncSetIdentityPoolConfigurationRequest 621 | 622 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 623 | return @{ 624 | @"cognitoStreams" : @"CognitoStreams", 625 | @"identityPoolId" : @"IdentityPoolId", 626 | @"pushSync" : @"PushSync", 627 | }; 628 | } 629 | 630 | + (NSValueTransformer *)cognitoStreamsJSONTransformer { 631 | return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSCognitoSyncCognitoStreams class]]; 632 | } 633 | 634 | + (NSValueTransformer *)pushSyncJSONTransformer { 635 | return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSCognitoSyncPushSync class]]; 636 | } 637 | 638 | @end 639 | 640 | @implementation AWSCognitoSyncSetIdentityPoolConfigurationResponse 641 | 642 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 643 | return @{ 644 | @"cognitoStreams" : @"CognitoStreams", 645 | @"identityPoolId" : @"IdentityPoolId", 646 | @"pushSync" : @"PushSync", 647 | }; 648 | } 649 | 650 | + (NSValueTransformer *)cognitoStreamsJSONTransformer { 651 | return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSCognitoSyncCognitoStreams class]]; 652 | } 653 | 654 | + (NSValueTransformer *)pushSyncJSONTransformer { 655 | return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSCognitoSyncPushSync class]]; 656 | } 657 | 658 | @end 659 | 660 | @implementation AWSCognitoSyncSubscribeToDatasetRequest 661 | 662 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 663 | return @{ 664 | @"datasetName" : @"DatasetName", 665 | @"deviceId" : @"DeviceId", 666 | @"identityId" : @"IdentityId", 667 | @"identityPoolId" : @"IdentityPoolId", 668 | }; 669 | } 670 | 671 | @end 672 | 673 | @implementation AWSCognitoSyncSubscribeToDatasetResponse 674 | 675 | @end 676 | 677 | @implementation AWSCognitoSyncUnsubscribeFromDatasetRequest 678 | 679 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 680 | return @{ 681 | @"datasetName" : @"DatasetName", 682 | @"deviceId" : @"DeviceId", 683 | @"identityId" : @"IdentityId", 684 | @"identityPoolId" : @"IdentityPoolId", 685 | }; 686 | } 687 | 688 | @end 689 | 690 | @implementation AWSCognitoSyncUnsubscribeFromDatasetResponse 691 | 692 | @end 693 | 694 | @implementation AWSCognitoSyncUpdateRecordsRequest 695 | 696 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 697 | return @{ 698 | @"clientContext" : @"ClientContext", 699 | @"datasetName" : @"DatasetName", 700 | @"deviceId" : @"DeviceId", 701 | @"identityId" : @"IdentityId", 702 | @"identityPoolId" : @"IdentityPoolId", 703 | @"recordPatches" : @"RecordPatches", 704 | @"syncSessionToken" : @"SyncSessionToken", 705 | }; 706 | } 707 | 708 | + (NSValueTransformer *)recordPatchesJSONTransformer { 709 | return [NSValueTransformer awsmtl_JSONArrayTransformerWithModelClass:[AWSCognitoSyncRecordPatch class]]; 710 | } 711 | 712 | @end 713 | 714 | @implementation AWSCognitoSyncUpdateRecordsResponse 715 | 716 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 717 | return @{ 718 | @"records" : @"Records", 719 | }; 720 | } 721 | 722 | + (NSValueTransformer *)recordsJSONTransformer { 723 | return [NSValueTransformer awsmtl_JSONArrayTransformerWithModelClass:[AWSCognitoSyncRecord class]]; 724 | } 725 | 726 | @end 727 | -------------------------------------------------------------------------------- /CognitoSync/AWSCognitoSyncResources.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import 17 | 18 | @interface AWSCognitoSyncResources : NSObject 19 | 20 | + (instancetype)sharedInstance; 21 | 22 | - (NSDictionary *)JSONObject; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /CognitoSync/AWSCognitoSyncService.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import 17 | #import 18 | #import "AWSCognitoSyncModel.h" 19 | 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | /** 23 | Amazon Cognito Sync

Amazon Cognito Sync provides an AWS service and client library that enable cross-device syncing of application-related user data. High-level client libraries are available for both iOS and Android. You can use these libraries to persist data locally so that it's available even if the device is offline. Developer credentials don't need to be stored on the mobile device to access the service. You can use Amazon Cognito to obtain a normalized user ID and credentials. User data is persisted in a dataset that can store up to 1 MB of key-value pairs, and you can have up to 20 datasets per user identity.

With Amazon Cognito Sync, the data stored for each identity is accessible only to credentials assigned to that identity. In order to use the Cognito Sync service, you need to make API calls using credentials retrieved with Amazon Cognito Identity service.

If you want to use Cognito Sync in an Android or iOS application, you will probably want to make API calls via the AWS Mobile SDK. To learn more, see the Developer Guide for Android and the Developer Guide for iOS.

24 | */ 25 | @interface AWSCognitoSync : AWSService 26 | 27 | /** 28 | The service configuration used to instantiate this service client. 29 | 30 | @warning Once the client is instantiated, do not modify the configuration object. It may cause unspecified behaviors. 31 | */ 32 | @property (nonatomic, strong, readonly) AWSServiceConfiguration *configuration; 33 | 34 | /** 35 | Returns the singleton service client. If the singleton object does not exist, the SDK instantiates the default service client with `defaultServiceConfiguration` from `[AWSServiceManager defaultServiceManager]`. The reference to this object is maintained by the SDK, and you do not need to retain it manually. 36 | 37 | For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` 38 | 39 | *Swift* 40 | 41 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 42 | let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") 43 | let configuration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: credentialProvider) 44 | AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration 45 | 46 | return true 47 | } 48 | 49 | *Objective-C* 50 | 51 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 52 | AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 53 | identityPoolId:@"YourIdentityPoolId"]; 54 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 55 | credentialsProvider:credentialsProvider]; 56 | [AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration; 57 | 58 | return YES; 59 | } 60 | 61 | Then call the following to get the default service client: 62 | 63 | *Swift* 64 | 65 | let CognitoSync = AWSCognitoSync.defaultCognitoSync() 66 | 67 | *Objective-C* 68 | 69 | AWSCognitoSync *CognitoSync = [AWSCognitoSync defaultCognitoSync]; 70 | 71 | @return The default service client. 72 | */ 73 | + (instancetype)defaultCognitoSync; 74 | 75 | /** 76 | Creates a service client with the given service configuration and registers it for the key. 77 | 78 | For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` 79 | 80 | *Swift* 81 | 82 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 83 | let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") 84 | let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialProvider) 85 | AWSCognitoSync.registerCognitoSyncWithConfiguration(configuration, forKey: "USWest2CognitoSync") 86 | 87 | return true 88 | } 89 | 90 | *Objective-C* 91 | 92 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 93 | AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 94 | identityPoolId:@"YourIdentityPoolId"]; 95 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSWest2 96 | credentialsProvider:credentialsProvider]; 97 | 98 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:@"USWest2CognitoSync"]; 99 | 100 | return YES; 101 | } 102 | 103 | Then call the following to get the service client: 104 | 105 | *Swift* 106 | 107 | let CognitoSync = AWSCognitoSync(forKey: "USWest2CognitoSync") 108 | 109 | *Objective-C* 110 | 111 | AWSCognitoSync *CognitoSync = [AWSCognitoSync CognitoSyncForKey:@"USWest2CognitoSync"]; 112 | 113 | @warning After calling this method, do not modify the configuration object. It may cause unspecified behaviors. 114 | 115 | @param configuration A service configuration object. 116 | @param key A string to identify the service client. 117 | */ 118 | + (void)registerCognitoSyncWithConfiguration:(AWSServiceConfiguration *)configuration forKey:(NSString *)key; 119 | 120 | /** 121 | Retrieves the service client associated with the key. You need to call `+ registerCognitoSyncWithConfiguration:forKey:` before invoking this method. 122 | 123 | For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` 124 | 125 | *Swift* 126 | 127 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 128 | let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") 129 | let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialProvider) 130 | AWSCognitoSync.registerCognitoSyncWithConfiguration(configuration, forKey: "USWest2CognitoSync") 131 | 132 | return true 133 | } 134 | 135 | *Objective-C* 136 | 137 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 138 | AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 139 | identityPoolId:@"YourIdentityPoolId"]; 140 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSWest2 141 | credentialsProvider:credentialsProvider]; 142 | 143 | [AWSCognitoSync registerCognitoSyncWithConfiguration:configuration forKey:@"USWest2CognitoSync"]; 144 | 145 | return YES; 146 | } 147 | 148 | Then call the following to get the service client: 149 | 150 | *Swift* 151 | 152 | let CognitoSync = AWSCognitoSync(forKey: "USWest2CognitoSync") 153 | 154 | *Objective-C* 155 | 156 | AWSCognitoSync *CognitoSync = [AWSCognitoSync CognitoSyncForKey:@"USWest2CognitoSync"]; 157 | 158 | @param key A string to identify the service client. 159 | 160 | @return An instance of the service client. 161 | */ 162 | + (instancetype)CognitoSyncForKey:(NSString *)key; 163 | 164 | /** 165 | Removes the service client associated with the key and release it. 166 | 167 | @warning Before calling this method, make sure no method is running on this client. 168 | 169 | @param key A string to identify the service client. 170 | */ 171 | + (void)removeCognitoSyncForKey:(NSString *)key; 172 | 173 | /** 174 | Instantiates the service client with the given service configuration. 175 | 176 | @warning This method has been deprecated. Use `+ registerCognitoSyncWithConfiguration:forKey:` and `+ CognitoSyncForKey:` instead. 177 | 178 | @warning Once the client is instantiated, do not modify the configuration object. It may cause unspecified behaviors. 179 | 180 | @warning Unlike the singleton method, you are responsible for maintaining a strong reference to this object. If the service client is released before completing a service request, the request may fail with unspecified errors. 181 | 182 | @param configuration The service configuration object. 183 | 184 | @return An instance of the service client. 185 | */ 186 | - (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration __attribute__ ((deprecated("Use '+ registerCognitoSyncWithConfiguration:forKey:' and '+ CognitoSyncForKey:' instead."))); 187 | 188 | /** 189 |

Initiates a bulk publish of all existing datasets for an Identity Pool to the configured stream. Customers are limited to one successful bulk publish per 24 hours. Bulk publish is an asynchronous request, customers can see the status of the request via the GetBulkPublishDetails operation.

This API can only be called with developer credentials. You cannot call this API with the temporary user credentials provided by Cognito Identity.

190 | 191 | @param request A container for the necessary parameters to execute the BulkPublish service method. 192 | 193 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncBulkPublishResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorResourceNotFound`, `AWSCognitoSyncErrorInternalError`, `AWSCognitoSyncErrorDuplicateRequest`, `AWSCognitoSyncErrorAlreadyStreamed`. 194 | 195 | @see AWSCognitoSyncBulkPublishRequest 196 | @see AWSCognitoSyncBulkPublishResponse 197 | */ 198 | - (AWSTask *)bulkPublish:(AWSCognitoSyncBulkPublishRequest *)request; 199 | 200 | /** 201 |

Deletes the specific dataset. The dataset will be deleted permanently, and the action can't be undone. Datasets that this dataset was merged with will no longer report the merge. Any subsequent operation on this dataset will result in a ResourceNotFoundException.

This API can be called with temporary user credentials provided by Cognito Identity or with developer credentials.

202 | 203 | @param request A container for the necessary parameters to execute the DeleteDataset service method. 204 | 205 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncDeleteDatasetResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorResourceNotFound`, `AWSCognitoSyncErrorInternalError`, `AWSCognitoSyncErrorTooManyRequests`, `AWSCognitoSyncErrorResourceConflict`. 206 | 207 | @see AWSCognitoSyncDeleteDatasetRequest 208 | @see AWSCognitoSyncDeleteDatasetResponse 209 | */ 210 | - (AWSTask *)deleteDataset:(AWSCognitoSyncDeleteDatasetRequest *)request; 211 | 212 | /** 213 |

Gets meta data about a dataset by identity and dataset name. With Amazon Cognito Sync, each identity has access only to its own data. Thus, the credentials used to make this API call need to have access to the identity data.

This API can be called with temporary user credentials provided by Cognito Identity or with developer credentials. You should use Cognito Identity credentials to make this API call.

214 | 215 | @param request A container for the necessary parameters to execute the DescribeDataset service method. 216 | 217 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncDescribeDatasetResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorResourceNotFound`, `AWSCognitoSyncErrorInternalError`, `AWSCognitoSyncErrorTooManyRequests`. 218 | 219 | @see AWSCognitoSyncDescribeDatasetRequest 220 | @see AWSCognitoSyncDescribeDatasetResponse 221 | */ 222 | - (AWSTask *)describeDataset:(AWSCognitoSyncDescribeDatasetRequest *)request; 223 | 224 | /** 225 |

Gets usage details (for example, data storage) about a particular identity pool.

This API can only be called with developer credentials. You cannot call this API with the temporary user credentials provided by Cognito Identity.

226 | 227 | @param request A container for the necessary parameters to execute the DescribeIdentityPoolUsage service method. 228 | 229 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncDescribeIdentityPoolUsageResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorResourceNotFound`, `AWSCognitoSyncErrorInternalError`, `AWSCognitoSyncErrorTooManyRequests`. 230 | 231 | @see AWSCognitoSyncDescribeIdentityPoolUsageRequest 232 | @see AWSCognitoSyncDescribeIdentityPoolUsageResponse 233 | */ 234 | - (AWSTask *)describeIdentityPoolUsage:(AWSCognitoSyncDescribeIdentityPoolUsageRequest *)request; 235 | 236 | /** 237 |

Gets usage information for an identity, including number of datasets and data usage.

This API can be called with temporary user credentials provided by Cognito Identity or with developer credentials.

238 | 239 | @param request A container for the necessary parameters to execute the DescribeIdentityUsage service method. 240 | 241 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncDescribeIdentityUsageResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorResourceNotFound`, `AWSCognitoSyncErrorInternalError`, `AWSCognitoSyncErrorTooManyRequests`. 242 | 243 | @see AWSCognitoSyncDescribeIdentityUsageRequest 244 | @see AWSCognitoSyncDescribeIdentityUsageResponse 245 | */ 246 | - (AWSTask *)describeIdentityUsage:(AWSCognitoSyncDescribeIdentityUsageRequest *)request; 247 | 248 | /** 249 |

Get the status of the last BulkPublish operation for an identity pool.

This API can only be called with developer credentials. You cannot call this API with the temporary user credentials provided by Cognito Identity.

250 | 251 | @param request A container for the necessary parameters to execute the GetBulkPublishDetails service method. 252 | 253 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncGetBulkPublishDetailsResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorResourceNotFound`, `AWSCognitoSyncErrorInternalError`. 254 | 255 | @see AWSCognitoSyncGetBulkPublishDetailsRequest 256 | @see AWSCognitoSyncGetBulkPublishDetailsResponse 257 | */ 258 | - (AWSTask *)getBulkPublishDetails:(AWSCognitoSyncGetBulkPublishDetailsRequest *)request; 259 | 260 | /** 261 |

Gets the events and the corresponding Lambda functions associated with an identity pool.

This API can only be called with developer credentials. You cannot call this API with the temporary user credentials provided by Cognito Identity.

262 | 263 | @param request A container for the necessary parameters to execute the GetCognitoEvents service method. 264 | 265 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncGetCognitoEventsResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorResourceNotFound`, `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInternalError`, `AWSCognitoSyncErrorTooManyRequests`. 266 | 267 | @see AWSCognitoSyncGetCognitoEventsRequest 268 | @see AWSCognitoSyncGetCognitoEventsResponse 269 | */ 270 | - (AWSTask *)getCognitoEvents:(AWSCognitoSyncGetCognitoEventsRequest *)request; 271 | 272 | /** 273 |

Gets the configuration settings of an identity pool.

This API can only be called with developer credentials. You cannot call this API with the temporary user credentials provided by Cognito Identity.

274 | 275 | @param request A container for the necessary parameters to execute the GetIdentityPoolConfiguration service method. 276 | 277 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncGetIdentityPoolConfigurationResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorResourceNotFound`, `AWSCognitoSyncErrorInternalError`, `AWSCognitoSyncErrorTooManyRequests`. 278 | 279 | @see AWSCognitoSyncGetIdentityPoolConfigurationRequest 280 | @see AWSCognitoSyncGetIdentityPoolConfigurationResponse 281 | */ 282 | - (AWSTask *)getIdentityPoolConfiguration:(AWSCognitoSyncGetIdentityPoolConfigurationRequest *)request; 283 | 284 | /** 285 |

Lists datasets for an identity. With Amazon Cognito Sync, each identity has access only to its own data. Thus, the credentials used to make this API call need to have access to the identity data.

ListDatasets can be called with temporary user credentials provided by Cognito Identity or with developer credentials. You should use the Cognito Identity credentials to make this API call.

286 | 287 | @param request A container for the necessary parameters to execute the ListDatasets service method. 288 | 289 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncListDatasetsResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorInternalError`, `AWSCognitoSyncErrorTooManyRequests`. 290 | 291 | @see AWSCognitoSyncListDatasetsRequest 292 | @see AWSCognitoSyncListDatasetsResponse 293 | */ 294 | - (AWSTask *)listDatasets:(AWSCognitoSyncListDatasetsRequest *)request; 295 | 296 | /** 297 |

Gets a list of identity pools registered with Cognito.

ListIdentityPoolUsage can only be called with developer credentials. You cannot make this API call with the temporary user credentials provided by Cognito Identity.

298 | 299 | @param request A container for the necessary parameters to execute the ListIdentityPoolUsage service method. 300 | 301 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncListIdentityPoolUsageResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorInternalError`, `AWSCognitoSyncErrorTooManyRequests`. 302 | 303 | @see AWSCognitoSyncListIdentityPoolUsageRequest 304 | @see AWSCognitoSyncListIdentityPoolUsageResponse 305 | */ 306 | - (AWSTask *)listIdentityPoolUsage:(AWSCognitoSyncListIdentityPoolUsageRequest *)request; 307 | 308 | /** 309 |

Gets paginated records, optionally changed after a particular sync count for a dataset and identity. With Amazon Cognito Sync, each identity has access only to its own data. Thus, the credentials used to make this API call need to have access to the identity data.

ListRecords can be called with temporary user credentials provided by Cognito Identity or with developer credentials. You should use Cognito Identity credentials to make this API call.

310 | 311 | @param request A container for the necessary parameters to execute the ListRecords service method. 312 | 313 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncListRecordsResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorTooManyRequests`, `AWSCognitoSyncErrorInternalError`. 314 | 315 | @see AWSCognitoSyncListRecordsRequest 316 | @see AWSCognitoSyncListRecordsResponse 317 | */ 318 | - (AWSTask *)listRecords:(AWSCognitoSyncListRecordsRequest *)request; 319 | 320 | /** 321 |

Registers a device to receive push sync notifications.

This API can only be called with temporary credentials provided by Cognito Identity. You cannot call this API with developer credentials.

322 | 323 | @param request A container for the necessary parameters to execute the RegisterDevice service method. 324 | 325 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncRegisterDeviceResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorResourceNotFound`, `AWSCognitoSyncErrorInternalError`, `AWSCognitoSyncErrorInvalidConfiguration`, `AWSCognitoSyncErrorTooManyRequests`. 326 | 327 | @see AWSCognitoSyncRegisterDeviceRequest 328 | @see AWSCognitoSyncRegisterDeviceResponse 329 | */ 330 | - (AWSTask *)registerDevice:(AWSCognitoSyncRegisterDeviceRequest *)request; 331 | 332 | /** 333 |

Sets the AWS Lambda function for a given event type for an identity pool. This request only updates the key/value pair specified. Other key/values pairs are not updated. To remove a key value pair, pass a empty value for the particular key.

This API can only be called with developer credentials. You cannot call this API with the temporary user credentials provided by Cognito Identity.

334 | 335 | @param request A container for the necessary parameters to execute the SetCognitoEvents service method. 336 | 337 | @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorResourceNotFound`, `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInternalError`, `AWSCognitoSyncErrorTooManyRequests`. 338 | 339 | @see AWSCognitoSyncSetCognitoEventsRequest 340 | */ 341 | - (AWSTask *)setCognitoEvents:(AWSCognitoSyncSetCognitoEventsRequest *)request; 342 | 343 | /** 344 |

Sets the necessary configuration for push sync.

This API can only be called with developer credentials. You cannot call this API with the temporary user credentials provided by Cognito Identity.

345 | 346 | @param request A container for the necessary parameters to execute the SetIdentityPoolConfiguration service method. 347 | 348 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncSetIdentityPoolConfigurationResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorResourceNotFound`, `AWSCognitoSyncErrorInternalError`, `AWSCognitoSyncErrorTooManyRequests`, `AWSCognitoSyncErrorLimitExceeded`. 349 | 350 | @see AWSCognitoSyncSetIdentityPoolConfigurationRequest 351 | @see AWSCognitoSyncSetIdentityPoolConfigurationResponse 352 | */ 353 | - (AWSTask *)setIdentityPoolConfiguration:(AWSCognitoSyncSetIdentityPoolConfigurationRequest *)request; 354 | 355 | /** 356 |

Subscribes to receive notifications when a dataset is modified by another device.

This API can only be called with temporary credentials provided by Cognito Identity. You cannot call this API with developer credentials.

357 | 358 | @param request A container for the necessary parameters to execute the SubscribeToDataset service method. 359 | 360 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncSubscribeToDatasetResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorResourceNotFound`, `AWSCognitoSyncErrorInternalError`, `AWSCognitoSyncErrorInvalidConfiguration`, `AWSCognitoSyncErrorTooManyRequests`. 361 | 362 | @see AWSCognitoSyncSubscribeToDatasetRequest 363 | @see AWSCognitoSyncSubscribeToDatasetResponse 364 | */ 365 | - (AWSTask *)subscribeToDataset:(AWSCognitoSyncSubscribeToDatasetRequest *)request; 366 | 367 | /** 368 |

Unsubscribes from receiving notifications when a dataset is modified by another device.

This API can only be called with temporary credentials provided by Cognito Identity. You cannot call this API with developer credentials.

369 | 370 | @param request A container for the necessary parameters to execute the UnsubscribeFromDataset service method. 371 | 372 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncUnsubscribeFromDatasetResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorResourceNotFound`, `AWSCognitoSyncErrorInternalError`, `AWSCognitoSyncErrorInvalidConfiguration`, `AWSCognitoSyncErrorTooManyRequests`. 373 | 374 | @see AWSCognitoSyncUnsubscribeFromDatasetRequest 375 | @see AWSCognitoSyncUnsubscribeFromDatasetResponse 376 | */ 377 | - (AWSTask *)unsubscribeFromDataset:(AWSCognitoSyncUnsubscribeFromDatasetRequest *)request; 378 | 379 | /** 380 |

Posts updates to records and adds and deletes records for a dataset and user.

The sync count in the record patch is your last known sync count for that record. The server will reject an UpdateRecords request with a ResourceConflictException if you try to patch a record with a new value but a stale sync count.

For example, if the sync count on the server is 5 for a key called highScore and you try and submit a new highScore with sync count of 4, the request will be rejected. To obtain the current sync count for a record, call ListRecords. On a successful update of the record, the response returns the new sync count for that record. You should present that sync count the next time you try to update that same record. When the record does not exist, specify the sync count as 0.

This API can be called with temporary user credentials provided by Cognito Identity or with developer credentials.

381 | 382 | @param request A container for the necessary parameters to execute the UpdateRecords service method. 383 | 384 | @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSCognitoSyncUpdateRecordsResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSCognitoSyncErrorDomain` domain and the following error code: `AWSCognitoSyncErrorInvalidParameter`, `AWSCognitoSyncErrorLimitExceeded`, `AWSCognitoSyncErrorNotAuthorized`, `AWSCognitoSyncErrorResourceNotFound`, `AWSCognitoSyncErrorResourceConflict`, `AWSCognitoSyncErrorInvalidLambdaFunctionOutput`, `AWSCognitoSyncErrorLambdaThrottled`, `AWSCognitoSyncErrorTooManyRequests`, `AWSCognitoSyncErrorInternalError`. 385 | 386 | @see AWSCognitoSyncUpdateRecordsRequest 387 | @see AWSCognitoSyncUpdateRecordsResponse 388 | */ 389 | - (AWSTask *)updateRecords:(AWSCognitoSyncUpdateRecordsRequest *)request; 390 | 391 | @end 392 | 393 | NS_ASSUME_NONNULL_END 394 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Amazon Software License 2 | This Amazon Software License (“License”) governs your use, reproduction, and distribution of the accompanying software as specified below. 3 | 1. Definitions 4 | “Licensor” means any person or entity that distributes its Work. 5 | 6 | “Software” means the original work of authorship made available under this License. 7 | 8 | “Work” means the Software and any additions to or derivative works of the Software that are made available under this License. 9 | 10 | The terms “reproduce,” “reproduction,” “derivative works,” and “distribution” have the meaning as provided under U.S. copyright law; provided, however, that for the purposes of this License, derivative works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work. 11 | 12 | Works, including the Software, are “made available” under this License by including in or with the Work either (a) a copyright notice referencing the applicability of this License to the Work, or (b) a copy of this License. 13 | 2. License Grants 14 | 2.1 Copyright Grant. Subject to the terms and conditions of this License, each Licensor grants to you a perpetual, worldwide, non-exclusive, royalty-free, copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense and distribute its Work and any resulting derivative works in any form. 15 | 2.2 Patent Grant. Subject to the terms and conditions of this License, each Licensor grants to you a perpetual, worldwide, non-exclusive, royalty-free patent license to make, have made, use, sell, offer for sale, import, and otherwise transfer its Work, in whole or in part. The foregoing license applies only to the patent claims licensable by Licensor that would be infringed by Licensor’s Work (or portion thereof) individually and excluding any combinations with any other materials or technology. 16 | 3. Limitations 17 | 3.1 Redistribution. You may reproduce or distribute the Work only if (a) you do so under this License, (b) you include a complete copy of this License with your distribution, and (c) you retain without modification any copyright, patent, trademark, or attribution notices that are present in the Work. 18 | 3.2 Derivative Works. You may specify that additional or different terms apply to the use, reproduction, and distribution of your derivative works of the Work (“Your Terms”) only if (a) Your Terms provide that the use limitation in Section 3.3 applies to your derivative works, and (b) you identify the specific derivative works that are subject to Your Terms. Notwithstanding Your Terms, this License (including the redistribution requirements in Section 3.1) will continue to apply to the Work itself. 19 | 3.3 Use Limitation. The Work and any derivative works thereof only may be used or intended for use with the web services, computing platforms or applications provided by Amazon.com, Inc. or its affiliates, including Amazon Web Services, Inc. 20 | 3.4 Patent Claims. If you bring or threaten to bring a patent claim against any Licensor (including any claim, cross-claim or counterclaim in a lawsuit) to enforce any patents that you allege are infringed by any Work, then your rights under this License from such Licensor (including the grants in Sections 2.1 and 2.2) will terminate immediately. 21 | 3.5 Trademarks. This License does not grant any rights to use any Licensor’s or its affiliates’ names, logos, or trademarks, except as necessary to reproduce the notices described in this License. 22 | 3.6 Termination. If you violate any term of this License, then your rights under this License (including the grants in Sections 2.1 and 2.2) will terminate immediately. 23 | 4. Disclaimer of Warranty. 24 | THE WORK IS PROVIDED “AS IS” WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WARRANTIES OR CONDITIONS OF M ERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR NON-INFRINGEMENT. YOU BEAR THE RISK OF UNDERTAKING ANY ACTIVITIES UNDER THIS LICENSE. SOME STATES’ CONSUMER LAWS DO NOT ALLOW EXCLUSION OF AN IMPLIED WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO YOU. 25 | 5. Limitation of Liability. 26 | EXCEPT AS PROHIBITED BY APPLICABLE LAW, IN NO EVENT AND UNDER NO LEGAL THEORY, WHETHER IN TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE SHALL ANY LICENSOR BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATED TO THIS LICENSE, THE USE OR INABILITY TO USE THE WORK (INCLUDING BUT NOT LIMITED TO LOSS OF GOODWILL, BUSINESS INTERRUPTION, LOST PROFITS OR DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY OTHER COMM ERCIAL DAMAGES OR LOSSES), EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 27 | Effective Date – April 18, 2008 © 2008 Amazon.com, Inc. or its affiliates. All rights reserved. -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Amazon Cognito Sync 2 | 3 | Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | 5 | This product includes software developed by Amazon Technologies, Inc (http://www.amazon.com/). 6 | 7 | Licensed under Amazon Software License 8 | 9 | See the License for the specific language governing permissions and limitations under the License. 10 | 11 | ********************** 12 | THIRD PARTY COMPONENTS 13 | ********************** 14 | 15 | This software includes third party software subject to the following copyrights: 16 | - Bolts-iOS - Copyright (c) 2013, Facebook, Inc. - BSD License 17 | - Mantle - Copyright (c) 2012 - 2014, GitHub, Inc. All rights reserved, copyright (c) 2012, Bitswift, Inc. All rights reserved - MIT license 18 | 19 | The licenses for these third party components are included in the License file. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [MOVED] AWS SDK for iOS (Amazon Cognito) 2 | This repository has been merged into AWS SDK for iOS. All the code is moved under aws-sdk-iOS/AWSCognito. Amazon Cognito Sync will continue to be developed and maintained in the master repo. Any future issues regarding Amazon Cognito should be posted at aws-sdk-ios/issues. This repo will be inactive and is pending removal if necessary. 3 | 4 | # Version 2 of the AWS SDK for iOS (Amazon Cognito) 5 | 6 | ## Requirements 7 | 8 | * iOS 7 and later 9 | * Xcode 5 and later 10 | 11 | ## Building 12 | 1. Open `AWSCognito.xcodeproj` file 13 | 2. Select embeded project: `AWSCore.xcodeproj` in Project Navigator Panel. 14 | 3. Locate `Location` under **Identity and Type** in File Inspector Panel. 15 | 4. Click `Folder` button on the right and choose the location of `AWSCore.xcodeproj` on your computer. 16 | 5. You can now build this framework. 17 | 18 | ## Installation 19 | 20 | To start using the AWS SDK for iOS, follow the instructions at [Setup the SDK for iOS](http://docs.aws.amazon.com/mobile/sdkforios/developerguide/setup.html). 21 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | desc "Runs the specs [EMPTY]" 2 | task :spec do 3 | # Provide your own implementation 4 | end 5 | 6 | task :version do 7 | git_remotes = `git remote`.strip.split("\n") 8 | 9 | if git_remotes.count > 0 10 | puts "-- fetching version number from github" 11 | sh 'git fetch' 12 | 13 | remote_version = remote_spec_version 14 | end 15 | 16 | if remote_version.nil? 17 | puts "There is no current released version. You're about to release a new Pod." 18 | version = "0.0.1" 19 | else 20 | puts "The current released version of your pod is " + 21 | remote_spec_version.to_s() 22 | version = suggested_version_number 23 | end 24 | 25 | puts "Enter the version you want to release (" + version + ") " 26 | new_version_number = $stdin.gets.strip 27 | if new_version_number == "" 28 | new_version_number = version 29 | end 30 | 31 | replace_version_number(new_version_number) 32 | end 33 | 34 | desc "Release a new version of the Pod (append repo=name to push to a private spec repo)" 35 | task :release do 36 | # Allow override of spec repo name using `repo=private` after task name 37 | repo = ENV["repo"] || "master" 38 | 39 | puts "* Running version" 40 | sh "rake version" 41 | 42 | unless ENV['SKIP_CHECKS'] 43 | if `git symbolic-ref HEAD 2>/dev/null`.strip.split('/').last != 'master' 44 | $stderr.puts "[!] You need to be on the `master' branch in order to be able to do a release." 45 | exit 1 46 | end 47 | 48 | if `git tag`.strip.split("\n").include?(spec_version) 49 | $stderr.puts "[!] A tag for version `#{spec_version}' already exists. Change the version in the podspec" 50 | exit 1 51 | end 52 | 53 | puts "You are about to release `#{spec_version}`, is that correct? [y/n]" 54 | exit if $stdin.gets.strip.downcase != 'y' 55 | end 56 | 57 | puts "* Running specs" 58 | sh "rake spec" 59 | 60 | puts "* Linting the podspec" 61 | sh "pod lib lint" 62 | 63 | # Then release 64 | sh "git commit #{podspec_path} CHANGELOG.md -m 'Release #{spec_version}' --allow-empty" 65 | sh "git tag -a #{spec_version} -m 'Release #{spec_version}'" 66 | sh "git push origin master" 67 | sh "git push origin --tags" 68 | sh "pod push #{repo} #{podspec_path}" 69 | end 70 | 71 | # @return [Pod::Version] The version as reported by the Podspec. 72 | # 73 | def spec_version 74 | require 'cocoapods' 75 | spec = Pod::Specification.from_file(podspec_path) 76 | spec.version 77 | end 78 | 79 | # @return [Pod::Version] The version as reported by the Podspec from remote. 80 | # 81 | def remote_spec_version 82 | require 'cocoapods-core' 83 | 84 | if spec_file_exist_on_remote? 85 | remote_spec = eval(`git show origin/master:#{podspec_path}`) 86 | remote_spec.version 87 | else 88 | nil 89 | end 90 | end 91 | 92 | # @return [Bool] If the remote repository has a copy of the podpesc file or not. 93 | # 94 | def spec_file_exist_on_remote? 95 | test_condition = `if git rev-parse --verify --quiet origin/master:#{podspec_path} >/dev/null; 96 | then 97 | echo 'true' 98 | else 99 | echo 'false' 100 | fi` 101 | 102 | 'true' == test_condition.strip 103 | end 104 | 105 | # @return [String] The relative path of the Podspec. 106 | # 107 | def podspec_path 108 | podspecs = Dir.glob('*.podspec') 109 | if podspecs.count == 1 110 | podspecs.first 111 | else 112 | raise "Could not select a podspec" 113 | end 114 | end 115 | 116 | # @return [String] The suggested version number based on the local and remote 117 | # version numbers. 118 | # 119 | def suggested_version_number 120 | if spec_version != remote_spec_version 121 | spec_version.to_s() 122 | else 123 | next_version(spec_version).to_s() 124 | end 125 | end 126 | 127 | # @param [Pod::Version] version 128 | # the version for which you need the next version 129 | # 130 | # @note It is computed by bumping the last component of 131 | # the version string by 1. 132 | # 133 | # @return [Pod::Version] The version that comes next after 134 | # the version supplied. 135 | # 136 | def next_version(version) 137 | version_components = version.to_s().split("."); 138 | last = (version_components.last.to_i() + 1).to_s 139 | version_components[-1] = last 140 | Pod::Version.new(version_components.join(".")) 141 | end 142 | 143 | # @param [String] new_version_number 144 | # the new version number 145 | # 146 | # @note This methods replaces the version number in the podspec file 147 | # with a new version number. 148 | # 149 | # @return void 150 | # 151 | def replace_version_number(new_version_number) 152 | text = File.read(podspec_path) 153 | text.gsub!(/(s.version( )*= ")#{spec_version}(")/, 154 | "\\1#{new_version_number}\\3") 155 | File.open(podspec_path, "w") { |file| file.puts text } 156 | end 157 | --------------------------------------------------------------------------------