From 6f599baaa2a3b79bbd9798c290b656e0a54497ef Mon Sep 17 00:00:00 2001 From: kyleknap Date: Wed, 10 Sep 2014 15:55:18 -0700 Subject: Added support for Amazon Cognito. Includes support for both Amazon Cognito Sync and Amazon Cognito Identity. --- README.rst | 2 + boto/__init__.py | 46 +++ boto/cognito/__init__.py | 21 ++ boto/cognito/identity/__init__.py | 42 +++ boto/cognito/identity/exceptions.py | 40 +++ boto/cognito/identity/layer1.py | 303 ++++++++++++++++++++ boto/cognito/sync/__init__.py | 41 +++ boto/cognito/sync/exceptions.py | 50 ++++ boto/cognito/sync/layer1.py | 307 +++++++++++++++++++++ boto/endpoints.json | 6 + docs/source/index.rst | 2 + docs/source/ref/cognito-identity.rst | 26 ++ docs/source/ref/cognito-sync.rst | 26 ++ setup.py | 3 +- tests/integration/cognito/__init__.py | 41 +++ tests/integration/cognito/identity/__init__.py | 21 ++ .../cognito/identity/test_cognito_identity.py | 52 ++++ tests/integration/cognito/sync/__init__.py | 21 ++ .../integration/cognito/sync/test_cognito_sync.py | 46 +++ 19 files changed, 1095 insertions(+), 1 deletion(-) create mode 100644 boto/cognito/__init__.py create mode 100644 boto/cognito/identity/__init__.py create mode 100644 boto/cognito/identity/exceptions.py create mode 100644 boto/cognito/identity/layer1.py create mode 100644 boto/cognito/sync/__init__.py create mode 100644 boto/cognito/sync/exceptions.py create mode 100644 boto/cognito/sync/layer1.py create mode 100644 docs/source/ref/cognito-identity.rst create mode 100644 docs/source/ref/cognito-sync.rst create mode 100644 tests/integration/cognito/__init__.py create mode 100644 tests/integration/cognito/identity/__init__.py create mode 100644 tests/integration/cognito/identity/test_cognito_identity.py create mode 100644 tests/integration/cognito/sync/__init__.py create mode 100644 tests/integration/cognito/sync/test_cognito_sync.py diff --git a/README.rst b/README.rst index e78a0ad4..92c5c949 100644 --- a/README.rst +++ b/README.rst @@ -67,6 +67,8 @@ At the moment, boto supports: * Amazon Simple Queue Service (SQS) (Python 3) * Amazon Simple Notification Server (SNS) (Python 3) * Amazon Simple Email Service (SES) (Python 3) + * Amazon Cognito Identity (Python 3) + * Amazon Cognito Sync (Python 3) * Monitoring diff --git a/boto/__init__.py b/boto/__init__.py index d76b67cc..1737f45c 100644 --- a/boto/__init__.py +++ b/boto/__init__.py @@ -882,6 +882,52 @@ def connect_route53domains(aws_access_key_id=None, ) +def connect_cognito_identity(aws_access_key_id=None, + aws_secret_access_key=None, + **kwargs): + """ + Connect to Amazon Cognito Identity + + :type aws_access_key_id: string + :param aws_access_key_id: Your AWS Access Key ID + + :type aws_secret_access_key: string + :param aws_secret_access_key: Your AWS Secret Access Key + + rtype: :class:`boto.cognito.identity.layer1.CognitoIdentityConnection` + :return: A connection to the Amazon Cognito Identity service + """ + from boto.cognito.identity.layer1 import CognitoIdentityConnection + return CognitoIdentityConnection( + aws_access_key_id=aws_access_key_id, + aws_secret_access_key=aws_secret_access_key, + **kwargs + ) + + +def connect_cognito_sync(aws_access_key_id=None, + aws_secret_access_key=None, + **kwargs): + """ + Connect to Amazon Cognito Sync + + :type aws_access_key_id: string + :param aws_access_key_id: Your AWS Access Key ID + + :type aws_secret_access_key: string + :param aws_secret_access_key: Your AWS Secret Access Key + + rtype: :class:`boto.cognito.sync.layer1.CognitoSyncConnection` + :return: A connection to the Amazon Cognito Sync service + """ + from boto.cognito.sync.layer1 import CognitoSyncConnection + return CognitoSyncConnection( + aws_access_key_id=aws_access_key_id, + aws_secret_access_key=aws_secret_access_key, + **kwargs + ) + + def storage_uri(uri_str, default_scheme='file', debug=0, validate=True, bucket_storage_uri_class=BucketStorageUri, suppress_consec_slashes=True, is_latest=False): diff --git a/boto/cognito/__init__.py b/boto/cognito/__init__.py new file mode 100644 index 00000000..70cc23fe --- /dev/null +++ b/boto/cognito/__init__.py @@ -0,0 +1,21 @@ +# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, dis- +# tribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the fol- +# lowing conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# diff --git a/boto/cognito/identity/__init__.py b/boto/cognito/identity/__init__.py new file mode 100644 index 00000000..e58b480b --- /dev/null +++ b/boto/cognito/identity/__init__.py @@ -0,0 +1,42 @@ +# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. +# All Rights Reserved +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, dis- +# tribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the fol- +# lowing conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +from boto.regioninfo import RegionInfo, get_regions + + +def regions(): + """ + Get all available regions for the Amazon Cognito Identity service. + + :rtype: list + :return: A list of :class:`boto.regioninfo.RegionInfo` + """ + from boto.cognito.identity.layer1 import CognitoIdentityConnection + return get_regions('cognito-identity', + connection_cls=CognitoIdentityConnection) + + +def connect_to_region(region_name, **kw_params): + for region in regions(): + if region.name == region_name: + return region.connect(**kw_params) + return None diff --git a/boto/cognito/identity/exceptions.py b/boto/cognito/identity/exceptions.py new file mode 100644 index 00000000..179089df --- /dev/null +++ b/boto/cognito/identity/exceptions.py @@ -0,0 +1,40 @@ +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +from boto.exception import BotoServerError + + +class LimitExceededException(BotoServerError): + pass + + +class ResourceConflictException(BotoServerError): + pass + + +class TooManyRequestsException(BotoServerError): + pass + + +class InvalidParameterException(BotoServerError): + pass + + +class ResourceNotFoundException(BotoServerError): + pass + + +class InternalErrorException(BotoServerError): + pass + + +class NotAuthorizedException(BotoServerError): + pass diff --git a/boto/cognito/identity/layer1.py b/boto/cognito/identity/layer1.py new file mode 100644 index 00000000..0a9c8e4e --- /dev/null +++ b/boto/cognito/identity/layer1.py @@ -0,0 +1,303 @@ +# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, dis- +# tribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the fol- +# lowing conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# + +import boto +from boto.compat import json +from boto.connection import AWSQueryConnection +from boto.regioninfo import RegionInfo +from boto.exception import JSONResponseError +from boto.cognito.identity import exceptions + + +class CognitoIdentityConnection(AWSQueryConnection): + """ + Amazon Cognito + Amazon Cognito is a web service that facilitates the delivery of + scoped, temporary credentials to mobile devices or other untrusted + environments. Amazon Cognito uniquely identifies a device or user + and supplies the user with a consistent identity throughout the + lifetime of an application. + + Amazon Cognito lets users authenticate with third-party identity + providers (Facebook, Google, or Login with Amazon). As a + developer, you decide which identity providers to trust. You can + also choose to support unauthenticated access from your + application. Your users are provided with Cognito tokens that + uniquely identify their device and any information provided about + third-party logins. + """ + APIVersion = "2014-06-30" + DefaultRegionName = "us-east-1" + DefaultRegionEndpoint = "cognito-identity.us-east-1.amazonaws.com" + ServiceName = "CognitoIdentity" + TargetPrefix = "AWSCognitoIdentityService" + ResponseError = JSONResponseError + + _faults = { + "LimitExceededException": exceptions.LimitExceededException, + "ResourceConflictException": exceptions.ResourceConflictException, + "TooManyRequestsException": exceptions.TooManyRequestsException, + "InvalidParameterException": exceptions.InvalidParameterException, + "ResourceNotFoundException": exceptions.ResourceNotFoundException, + "InternalErrorException": exceptions.InternalErrorException, + "NotAuthorizedException": exceptions.NotAuthorizedException, + } + + + def __init__(self, **kwargs): + region = kwargs.pop('region', None) + if not region: + region = RegionInfo(self, self.DefaultRegionName, + self.DefaultRegionEndpoint) + + if 'host' not in kwargs or kwargs['host'] is None: + kwargs['host'] = region.endpoint + + super(CognitoIdentityConnection, self).__init__(**kwargs) + self.region = region + + def _required_auth_capability(self): + return ['hmac-v4'] + + def create_identity_pool(self, identity_pool_name, + allow_unauthenticated_identities, + supported_login_providers=None): + """ + Creates a new identity pool. The identity pool is a store of + user identity information that is specific to your AWS + account. + + :type identity_pool_name: string + :param identity_pool_name: A string that you provide. + + :type allow_unauthenticated_identities: boolean + :param allow_unauthenticated_identities: TRUE if the identity pool + supports unauthenticated logins. + + :type supported_login_providers: map + :param supported_login_providers: Optional key:value pairs mapping + provider names to provider app IDs. + + """ + params = { + 'IdentityPoolName': identity_pool_name, + 'AllowUnauthenticatedIdentities': allow_unauthenticated_identities, + } + if supported_login_providers is not None: + params['SupportedLoginProviders'] = supported_login_providers + return self.make_request(action='CreateIdentityPool', + body=json.dumps(params)) + + def delete_identity_pool(self, identity_pool_id): + """ + Deletes a user pool. Once a pool is deleted, users will not be + able to authenticate with the pool. + + :type identity_pool_id: string + :param identity_pool_id: An identity pool ID in the format REGION:GUID. + + """ + params = {'IdentityPoolId': identity_pool_id, } + return self.make_request(action='DeleteIdentityPool', + body=json.dumps(params)) + + def describe_identity_pool(self, identity_pool_id): + """ + Gets details about a particular identity pool, including the + pool name, ID description, creation date, and current number + of users. + + :type identity_pool_id: string + :param identity_pool_id: An identity pool ID in the format REGION:GUID. + + """ + params = {'IdentityPoolId': identity_pool_id, } + return self.make_request(action='DescribeIdentityPool', + body=json.dumps(params)) + + def get_id(self, account_id, identity_pool_id, logins=None): + """ + Generates (or retrieves) a Cognito ID. Supplying multiple + logins will create an implicit linked account. + + :type account_id: string + :param account_id: A standard AWS account ID (9+ digits). + + :type identity_pool_id: string + :param identity_pool_id: An identity pool ID in the format REGION:GUID. + + :type logins: map + :param logins: A set of optional name/value pairs that map provider + names to provider tokens. + + """ + params = { + 'AccountId': account_id, + 'IdentityPoolId': identity_pool_id, + } + if logins is not None: + params['Logins'] = logins + return self.make_request(action='GetId', + body=json.dumps(params)) + + def get_open_id_token(self, identity_id, logins=None): + """ + Gets an OpenID token, using a known Cognito ID. This known + Cognito ID is returned from GetId. You can optionally add + additional logins for the identity. Supplying multiple logins + creates an implicit link. + + :type identity_id: string + :param identity_id: A unique identifier in the format REGION:GUID. + + :type logins: map + :param logins: A set of optional name/value pairs that map provider + names to provider tokens. + + """ + params = {'IdentityId': identity_id, } + if logins is not None: + params['Logins'] = logins + return self.make_request(action='GetOpenIdToken', + body=json.dumps(params)) + + def list_identities(self, identity_pool_id, max_results, next_token=None): + """ + Lists the identities in a pool. + + :type identity_pool_id: string + :param identity_pool_id: An identity pool ID in the format REGION:GUID. + + :type max_results: integer + :param max_results: The maximum number of identities to return. + + :type next_token: string + :param next_token: A pagination token. + + """ + params = { + 'IdentityPoolId': identity_pool_id, + 'MaxResults': max_results, + } + if next_token is not None: + params['NextToken'] = next_token + return self.make_request(action='ListIdentities', + body=json.dumps(params)) + + def list_identity_pools(self, max_results, next_token=None): + """ + Lists all of the Cognito identity pools registered for your + account. + + :type max_results: integer + :param max_results: The maximum number of identities to return. + + :type next_token: string + :param next_token: A pagination token. + + """ + params = {'MaxResults': max_results, } + if next_token is not None: + params['NextToken'] = next_token + return self.make_request(action='ListIdentityPools', + body=json.dumps(params)) + + def unlink_identity(self, identity_id, logins, logins_to_remove): + """ + Unlinks a federated identity from an existing account. + Unlinked logins will be considered new identities next time + they are seen. Removing the last linked login will make this + identity inaccessible. + + :type identity_id: string + :param identity_id: A unique identifier in the format REGION:GUID. + + :type logins: map + :param logins: A set of optional name/value pairs that map provider + names to provider tokens. + + :type logins_to_remove: list + :param logins_to_remove: Provider names to unlink from this identity. + + """ + params = { + 'IdentityId': identity_id, + 'Logins': logins, + 'LoginsToRemove': logins_to_remove, + } + return self.make_request(action='UnlinkIdentity', + body=json.dumps(params)) + + def update_identity_pool(self, identity_pool_id, identity_pool_name, + allow_unauthenticated_identities, + supported_login_providers=None): + """ + Updates a user pool. + + :type identity_pool_id: string + :param identity_pool_id: An identity pool ID in the format REGION:GUID. + + :type identity_pool_name: string + :param identity_pool_name: A string that you provide. + + :type allow_unauthenticated_identities: boolean + :param allow_unauthenticated_identities: TRUE if the identity pool + supports unauthenticated logins. + + :type supported_login_providers: map + :param supported_login_providers: Optional key:value pairs mapping + provider names to provider app IDs. + + """ + params = { + 'IdentityPoolId': identity_pool_id, + 'IdentityPoolName': identity_pool_name, + 'AllowUnauthenticatedIdentities': allow_unauthenticated_identities, + } + if supported_login_providers is not None: + params['SupportedLoginProviders'] = supported_login_providers + return self.make_request(action='UpdateIdentityPool', + body=json.dumps(params)) + + def make_request(self, action, body): + headers = { + 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), + 'Host': self.region.endpoint, + 'Content-Type': 'application/x-amz-json-1.1', + 'Content-Length': str(len(body)), + } + http_request = self.build_base_http_request( + method='POST', path='/', auth_path='/', params={}, + headers=headers, data=body) + response = self._mexe(http_request, sender=None, + override_num_retries=10) + response_body = response.read().decode('utf-8') + boto.log.debug(response_body) + if response.status == 200: + if response_body: + return json.loads(response_body) + else: + json_body = json.loads(response_body) + fault_name = json_body.get('__type', None) + exception_class = self._faults.get(fault_name, self.ResponseError) + raise exception_class(response.status, response.reason, + body=json_body) diff --git a/boto/cognito/sync/__init__.py b/boto/cognito/sync/__init__.py new file mode 100644 index 00000000..3d48bd18 --- /dev/null +++ b/boto/cognito/sync/__init__.py @@ -0,0 +1,41 @@ +# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. +# All Rights Reserved +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, dis- +# tribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the fol- +# lowing conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +from boto.regioninfo import RegionInfo, get_regions + + +def regions(): + """ + Get all available regions for the Amazon Cognito Sync service. + + :rtype: list + :return: A list of :class:`boto.regioninfo.RegionInfo` + """ + from boto.cognito.sync.layer1 import CognitoSyncConnection + return get_regions('cognito-sync', connection_cls=CognitoSyncConnection) + + +def connect_to_region(region_name, **kw_params): + for region in regions(): + if region.name == region_name: + return region.connect(**kw_params) + return None diff --git a/boto/cognito/sync/exceptions.py b/boto/cognito/sync/exceptions.py new file mode 100644 index 00000000..d64fb278 --- /dev/null +++ b/boto/cognito/sync/exceptions.py @@ -0,0 +1,50 @@ +# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, dis- +# tribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the fol- +# lowing conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +from boto.exception import BotoServerError + + +class LimitExceededException(BotoServerError): + pass + + +class ResourceConflictException(BotoServerError): + pass + + +class TooManyRequestsException(BotoServerError): + pass + + +class InvalidParameterException(BotoServerError): + pass + + +class ResourceNotFoundException(BotoServerError): + pass + + +class InternalErrorException(BotoServerError): + pass + + +class NotAuthorizedException(BotoServerError): + pass diff --git a/boto/cognito/sync/layer1.py b/boto/cognito/sync/layer1.py new file mode 100644 index 00000000..545af5eb --- /dev/null +++ b/boto/cognito/sync/layer1.py @@ -0,0 +1,307 @@ +# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, dis- +# tribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the fol- +# lowing conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +from boto.compat import json +from boto.exception import JSONResponseError +from boto.connection import AWSAuthConnection +from boto.regioninfo import RegionInfo +from boto.cognito.sync import exceptions + + +class CognitoSyncConnection(AWSAuthConnection): + """ + 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. + """ + APIVersion = "2014-06-30" + DefaultRegionName = "us-east-1" + DefaultRegionEndpoint = "cognito-sync.us-east-1.amazonaws.com" + ResponseError = JSONResponseError + + _faults = { + "LimitExceededException": exceptions.LimitExceededException, + "ResourceConflictException": exceptions.ResourceConflictException, + "TooManyRequestsException": exceptions.TooManyRequestsException, + "InvalidParameterException": exceptions.InvalidParameterException, + "ResourceNotFoundException": exceptions.ResourceNotFoundException, + "InternalErrorException": exceptions.InternalErrorException, + "NotAuthorizedException": exceptions.NotAuthorizedException, + } + + + def __init__(self, **kwargs): + region = kwargs.get('region') + if not region: + region = RegionInfo(self, self.DefaultRegionName, + self.DefaultRegionEndpoint) + else: + del kwargs['region'] + kwargs['host'] = region.endpoint + super(CognitoSyncConnection, self).__init__(**kwargs) + self.region = region + + def _required_auth_capability(self): + return ['hmac-v4'] + + def delete_dataset(self, identity_pool_id, identity_id, dataset_name): + """ + 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 consequent operation on this dataset will result in a + ResourceNotFoundException. + + :type identity_pool_id: string + :param identity_pool_id: A name-spaced GUID (for example, us- + east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon + Cognito. GUID generation is unique within a region. + + :type identity_id: string + :param identity_id: A name-spaced GUID (for example, us- + east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon + Cognito. GUID generation is unique within a region. + + :type dataset_name: string + :param dataset_name: A string of up to 128 characters. Allowed + characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.' + (dot). + + """ + uri = '/identitypools/{0}/identities/{1}/datasets/{2}'.format( + identity_pool_id, identity_id, dataset_name) + return self.make_request('DELETE', uri, expected_status=200) + + def describe_dataset(self, identity_pool_id, identity_id, dataset_name): + """ + Gets metadata about a dataset by identity and dataset name. + + :type identity_pool_id: string + :param identity_pool_id: A name-spaced GUID (for example, us- + east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon + Cognito. GUID generation is unique within a region. + + :type identity_id: string + :param identity_id: A name-spaced GUID (for example, us- + east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon + Cognito. GUID generation is unique within a region. + + :type dataset_name: string + :param dataset_name: A string of up to 128 characters. Allowed + characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.' + (dot). + + """ + uri = '/identitypools/{0}/identities/{1}/datasets/{2}'.format( + identity_pool_id, identity_id, dataset_name) + return self.make_request('GET', uri, expected_status=200) + + def describe_identity_pool_usage(self, identity_pool_id): + """ + Gets usage details (for example, data storage) about a + particular identity pool. + + :type identity_pool_id: string + :param identity_pool_id: A name-spaced GUID (for example, us- + east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon + Cognito. GUID generation is unique within a region. + + """ + uri = '/identitypools/{0}'.format(identity_pool_id) + return self.make_request('GET', uri, expected_status=200) + + def describe_identity_usage(self, identity_pool_id, identity_id): + """ + Gets usage information for an identity, including number of + datasets and data usage. + + :type identity_pool_id: string + :param identity_pool_id: A name-spaced GUID (for example, us- + east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon + Cognito. GUID generation is unique within a region. + + :type identity_id: string + :param identity_id: A name-spaced GUID (for example, us- + east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon + Cognito. GUID generation is unique within a region. + + """ + uri = '/identitypools/{0}/identities/{1}'.format( + identity_pool_id, identity_id) + return self.make_request('GET', uri, expected_status=200) + + def list_datasets(self, identity_pool_id, identity_id, next_token=None, + max_results=None): + """ + Lists datasets for an identity. + + :type identity_pool_id: string + :param identity_pool_id: A name-spaced GUID (for example, us- + east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon + Cognito. GUID generation is unique within a region. + + :type identity_id: string + :param identity_id: A name-spaced GUID (for example, us- + east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon + Cognito. GUID generation is unique within a region. + + :type next_token: string + :param next_token: A pagination token for obtaining the next page of + results. + + :type max_results: integer + :param max_results: The maximum number of results to be returned. + + """ + uri = '/identitypools/{0}/identities/{1}/datasets'.format( + identity_pool_id, identity_id) + params = {} + headers = {} + return self.make_request('GET', uri, expected_status=200, + data=json.dumps(params), headers=headers) + + def list_identity_pool_usage(self, next_token=None, max_results=None): + """ + Gets a list of identity pools registered with Cognito. + + :type next_token: string + :param next_token: A pagination token for obtaining the next page of + results. + + :type max_results: integer + :param max_results: The maximum number of results to be returned. + + """ + uri = '/identitypools' + params = {} + headers = {} + return self.make_request('GET', uri, expected_status=200, + data=json.dumps(params), headers=headers) + + def list_records(self, identity_pool_id, identity_id, dataset_name, + last_sync_count=None, next_token=None, max_results=None, + sync_session_token=None): + """ + Gets paginated records, optionally changed after a particular + sync count for a dataset and identity. + + :type identity_pool_id: string + :param identity_pool_id: A name-spaced GUID (for example, us- + east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon + Cognito. GUID generation is unique within a region. + + :type identity_id: string + :param identity_id: A name-spaced GUID (for example, us- + east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon + Cognito. GUID generation is unique within a region. + + :type dataset_name: string + :param dataset_name: A string of up to 128 characters. Allowed + characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.' + (dot). + + :type last_sync_count: long + :param last_sync_count: The last server sync count for this record. + + :type next_token: string + :param next_token: A pagination token for obtaining the next page of + results. + + :type max_results: integer + :param max_results: The maximum number of results to be returned. + + :type sync_session_token: string + :param sync_session_token: A token containing a session ID, identity + ID, and expiration. + + """ + uri = '/identitypools/{0}/identities/{1}/datasets/{2}/records'.format( + identity_pool_id, identity_id, dataset_name) + params = {} + headers = {} + return self.make_request('GET', uri, expected_status=200, + data=json.dumps(params), headers=headers) + + def update_records(self, identity_pool_id, identity_id, dataset_name, + sync_session_token, record_patches=None, + client_context=None): + """ + Posts updates to records and add and delete records for a + dataset and user. + + :type identity_pool_id: string + :param identity_pool_id: A name-spaced GUID (for example, us- + east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon + Cognito. GUID generation is unique within a region. + + :type identity_id: string + :param identity_id: A name-spaced GUID (for example, us- + east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon + Cognito. GUID generation is unique within a region. + + :type dataset_name: string + :param dataset_name: A string of up to 128 characters. Allowed + characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.' + (dot). + + :type record_patches: list + :param record_patches: + + :type sync_session_token: string + :param sync_session_token: The SyncSessionToken returned by a previous + call to ListRecords for this dataset and identity. + + :type client_context: string + :param client_context: + + """ + uri = '/identitypools/{0}/identities/{1}/datasets/{2}'.format( + identity_pool_id, identity_id, dataset_name) + params = {'SyncSessionToken': sync_session_token, } + headers = {} + if record_patches is not None: + params['RecordPatches'] = record_patches + if client_context is not None: + headers['x-amz-Client-Context'] = client_context + return self.make_request('POST', uri, expected_status=200, + data=json.dumps(params), headers=headers) + + def make_request(self, verb, resource, headers=None, data='', + expected_status=None, params=None): + if headers is None: + headers = {} + response = AWSAuthConnection.make_request( + self, verb, resource, headers=headers, data=data, params=params) + body = json.loads(response.read().decode('utf-8')) + if response.status == expected_status: + return body + else: + error_type = response.getheader('x-amzn-ErrorType').split(':')[0] + error_class = self._faults.get(error_type, self.ResponseError) + raise error_class(response.status, response.reason, body) diff --git a/boto/endpoints.json b/boto/endpoints.json index 5c95b5ca..db7c6446 100644 --- a/boto/endpoints.json +++ b/boto/endpoints.json @@ -62,6 +62,12 @@ "us-west-1": "monitoring.us-west-1.amazonaws.com", "us-west-2": "monitoring.us-west-2.amazonaws.com" }, + "cognito-identity": { + "us-east-1": "cognito-identity.us-east-1.amazonaws.com" + }, + "cognito-sync": { + "us-east-1": "cognito-sync.us-east-1.amazonaws.com" + }, "datapipeline": { "us-east-1": "datapipeline.us-east-1.amazonaws.com", "us-west-2": "datapipeline.us-west-2.amazonaws.com", diff --git a/docs/source/index.rst b/docs/source/index.rst index 00f26417..914c5328 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -73,6 +73,8 @@ Currently Supported Services * :doc:`Simple Queue Service (SQS) ` -- (:doc:`API Reference `) (Python 3) * Simple Notification Service (SNS) -- (:doc:`API Reference `) (Python 3) * :doc:`Simple Email Service (SES) ` -- (:doc:`API Reference `) (Python 3) + * Amazon Cognito Identity -- (:doc:`API Reference