CognitoIDP: update_group, global_sign_out, update_user_attributes (#5086)
This commit is contained in:
		
							parent
							
								
									3b68be55d3
								
							
						
					
					
						commit
						1d87b90e75
					
				@ -578,6 +578,14 @@ class CognitoIdpUserPool(BaseModel):
 | 
				
			|||||||
                    extra_data.update({attribute[0]["Name"]: attribute[0]["Value"]})
 | 
					                    extra_data.update({attribute[0]["Name"]: attribute[0]["Value"]})
 | 
				
			||||||
        return extra_data
 | 
					        return extra_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def sign_out(self, username):
 | 
				
			||||||
 | 
					        for token, token_tuple in list(self.refresh_tokens.items()):
 | 
				
			||||||
 | 
					            if token_tuple is None:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            _, logged_in_user = token_tuple
 | 
				
			||||||
 | 
					            if username == logged_in_user:
 | 
				
			||||||
 | 
					                self.refresh_tokens[token] = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CognitoIdpUserPoolDomain(BaseModel):
 | 
					class CognitoIdpUserPoolDomain(BaseModel):
 | 
				
			||||||
    def __init__(self, user_pool_id, domain, custom_domain_config=None):
 | 
					    def __init__(self, user_pool_id, domain, custom_domain_config=None):
 | 
				
			||||||
@ -679,6 +687,15 @@ class CognitoIdpGroup(BaseModel):
 | 
				
			|||||||
        # Note that these links are bidirectional.
 | 
					        # Note that these links are bidirectional.
 | 
				
			||||||
        self.users = set()
 | 
					        self.users = set()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update(self, description, role_arn, precedence):
 | 
				
			||||||
 | 
					        if description is not None:
 | 
				
			||||||
 | 
					            self.description = description
 | 
				
			||||||
 | 
					        if role_arn is not None:
 | 
				
			||||||
 | 
					            self.role_arn = role_arn
 | 
				
			||||||
 | 
					        if precedence is not None:
 | 
				
			||||||
 | 
					            self.precedence = precedence
 | 
				
			||||||
 | 
					        self.last_modified_date = datetime.datetime.now()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def to_json(self):
 | 
					    def to_json(self):
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
            "GroupName": self.group_name,
 | 
					            "GroupName": self.group_name,
 | 
				
			||||||
@ -1014,6 +1031,13 @@ class CognitoIdpBackend(BaseBackend):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        del user_pool.groups[group_name]
 | 
					        del user_pool.groups[group_name]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_group(self, user_pool_id, group_name, description, role_arn, precedence):
 | 
				
			||||||
 | 
					        group = self.get_group(user_pool_id, group_name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        group.update(description, role_arn, precedence)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return group
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def admin_add_user_to_group(self, user_pool_id, group_name, username):
 | 
					    def admin_add_user_to_group(self, user_pool_id, group_name, username):
 | 
				
			||||||
        group = self.get_group(user_pool_id, group_name)
 | 
					        group = self.get_group(user_pool_id, group_name)
 | 
				
			||||||
        user = self.admin_get_user(user_pool_id, username)
 | 
					        user = self.admin_get_user(user_pool_id, username)
 | 
				
			||||||
@ -1441,12 +1465,16 @@ class CognitoIdpBackend(BaseBackend):
 | 
				
			|||||||
        user_pool = self.describe_user_pool(user_pool_id)
 | 
					        user_pool = self.describe_user_pool(user_pool_id)
 | 
				
			||||||
        self.admin_get_user(user_pool_id, username)
 | 
					        self.admin_get_user(user_pool_id, username)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for token, token_tuple in list(user_pool.refresh_tokens.items()):
 | 
					        user_pool.sign_out(username)
 | 
				
			||||||
            if token_tuple is None:
 | 
					
 | 
				
			||||||
                continue
 | 
					    def global_sign_out(self, access_token):
 | 
				
			||||||
            _, username = token_tuple
 | 
					        for user_pool in self.user_pools.values():
 | 
				
			||||||
            if username == username:
 | 
					            if access_token in user_pool.access_tokens:
 | 
				
			||||||
                user_pool.refresh_tokens[token] = None
 | 
					                _, username = user_pool.access_tokens[access_token]
 | 
				
			||||||
 | 
					                user_pool.sign_out(username)
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        raise NotAuthorizedError(access_token)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def create_resource_server(self, user_pool_id, identifier, name, scopes):
 | 
					    def create_resource_server(self, user_pool_id, identifier, name, scopes):
 | 
				
			||||||
        user_pool = self.describe_user_pool(user_pool_id)
 | 
					        user_pool = self.describe_user_pool(user_pool_id)
 | 
				
			||||||
@ -1752,6 +1780,20 @@ class CognitoIdpBackend(BaseBackend):
 | 
				
			|||||||
        user_pool = self.describe_user_pool(user_pool_id)
 | 
					        user_pool = self.describe_user_pool(user_pool_id)
 | 
				
			||||||
        user_pool.add_custom_attributes(custom_attributes)
 | 
					        user_pool.add_custom_attributes(custom_attributes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_user_attributes(self, access_token, attributes):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        The parameter ClientMetadata has not yet been implemented. No CodeDeliveryDetails are returned.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        for user_pool in self.user_pools.values():
 | 
				
			||||||
 | 
					            if access_token in user_pool.access_tokens:
 | 
				
			||||||
 | 
					                _, username = user_pool.access_tokens[access_token]
 | 
				
			||||||
 | 
					                user = self.admin_get_user(user_pool.id, username)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                user.update_attributes(attributes)
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        raise NotAuthorizedError(access_token)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GlobalCognitoIdpBackend(CognitoIdpBackend):
 | 
					class GlobalCognitoIdpBackend(CognitoIdpBackend):
 | 
				
			||||||
    # Some operations are unauthenticated
 | 
					    # Some operations are unauthenticated
 | 
				
			||||||
 | 
				
			|||||||
@ -256,6 +256,19 @@ class CognitoIdpResponse(BaseResponse):
 | 
				
			|||||||
        cognitoidp_backends[self.region].delete_group(user_pool_id, group_name)
 | 
					        cognitoidp_backends[self.region].delete_group(user_pool_id, group_name)
 | 
				
			||||||
        return ""
 | 
					        return ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_group(self):
 | 
				
			||||||
 | 
					        group_name = self._get_param("GroupName")
 | 
				
			||||||
 | 
					        user_pool_id = self._get_param("UserPoolId")
 | 
				
			||||||
 | 
					        description = self._get_param("Description")
 | 
				
			||||||
 | 
					        role_arn = self._get_param("RoleArn")
 | 
				
			||||||
 | 
					        precedence = self._get_param("Precedence")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        group = cognitoidp_backends[self.region].update_group(
 | 
				
			||||||
 | 
					            user_pool_id, group_name, description, role_arn, precedence
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return json.dumps({"Group": group.to_json()})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def admin_add_user_to_group(self):
 | 
					    def admin_add_user_to_group(self):
 | 
				
			||||||
        user_pool_id = self._get_param("UserPoolId")
 | 
					        user_pool_id = self._get_param("UserPoolId")
 | 
				
			||||||
        username = self._get_param("Username")
 | 
					        username = self._get_param("Username")
 | 
				
			||||||
@ -501,6 +514,11 @@ class CognitoIdpResponse(BaseResponse):
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
        return ""
 | 
					        return ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def global_sign_out(self):
 | 
				
			||||||
 | 
					        access_token = self._get_param("AccessToken")
 | 
				
			||||||
 | 
					        cognitoidp_backends[self.region].global_sign_out(access_token)
 | 
				
			||||||
 | 
					        return ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Resource Server
 | 
					    # Resource Server
 | 
				
			||||||
    def create_resource_server(self):
 | 
					    def create_resource_server(self):
 | 
				
			||||||
        user_pool_id = self._get_param("UserPoolId")
 | 
					        user_pool_id = self._get_param("UserPoolId")
 | 
				
			||||||
@ -595,6 +613,14 @@ class CognitoIdpResponse(BaseResponse):
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
        return ""
 | 
					        return ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_user_attributes(self):
 | 
				
			||||||
 | 
					        access_token = self._get_param("AccessToken")
 | 
				
			||||||
 | 
					        attributes = self._get_param("UserAttributes")
 | 
				
			||||||
 | 
					        cognitoidp_backends[self.region].update_user_attributes(
 | 
				
			||||||
 | 
					            access_token, attributes
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return json.dumps({})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CognitoIdpJsonWebKeyResponse(BaseResponse):
 | 
					class CognitoIdpJsonWebKeyResponse(BaseResponse):
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
 | 
				
			|||||||
@ -24,6 +24,7 @@ cloudwatch:
 | 
				
			|||||||
  - TestAccCloudWatchLogsGroupDataSource
 | 
					  - TestAccCloudWatchLogsGroupDataSource
 | 
				
			||||||
cognitoidp:
 | 
					cognitoidp:
 | 
				
			||||||
  - TestAccCognitoIDPIdentityProvider
 | 
					  - TestAccCognitoIDPIdentityProvider
 | 
				
			||||||
 | 
					  - TestAccCognitoIDPUserGroup_
 | 
				
			||||||
  - TestAccCognitoIDPUserPool_
 | 
					  - TestAccCognitoIDPUserPool_
 | 
				
			||||||
  - TestAccCognitoUser_
 | 
					  - TestAccCognitoUser_
 | 
				
			||||||
  - TestAccCognitoUserInGroup_
 | 
					  - TestAccCognitoUserInGroup_
 | 
				
			||||||
 | 
				
			|||||||
@ -1316,6 +1316,44 @@ def test_create_group():
 | 
				
			|||||||
    result["Group"]["CreationDate"].should.be.a("datetime.datetime")
 | 
					    result["Group"]["CreationDate"].should.be.a("datetime.datetime")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@mock_cognitoidp
 | 
				
			||||||
 | 
					def test_update_group():
 | 
				
			||||||
 | 
					    conn = boto3.client("cognito-idp", "us-west-2")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    user_pool_id = conn.create_user_pool(PoolName=str(uuid.uuid4()))["UserPool"]["Id"]
 | 
				
			||||||
 | 
					    group_name = str(uuid.uuid4())
 | 
				
			||||||
 | 
					    description = str(uuid.uuid4())
 | 
				
			||||||
 | 
					    description2 = str(uuid.uuid4())
 | 
				
			||||||
 | 
					    role_arn = "arn:aws:iam:::role/my-iam-role"
 | 
				
			||||||
 | 
					    role_arn2 = "arn:aws:iam:::role/my-iam-role2"
 | 
				
			||||||
 | 
					    precedence = random.randint(0, 100000)
 | 
				
			||||||
 | 
					    precedence2 = random.randint(0, 100000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    conn.create_group(
 | 
				
			||||||
 | 
					        GroupName=group_name,
 | 
				
			||||||
 | 
					        UserPoolId=user_pool_id,
 | 
				
			||||||
 | 
					        Description=description,
 | 
				
			||||||
 | 
					        RoleArn=role_arn,
 | 
				
			||||||
 | 
					        Precedence=precedence,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result = conn.update_group(
 | 
				
			||||||
 | 
					        GroupName=group_name,
 | 
				
			||||||
 | 
					        UserPoolId=user_pool_id,
 | 
				
			||||||
 | 
					        Description=description2,
 | 
				
			||||||
 | 
					        RoleArn=role_arn2,
 | 
				
			||||||
 | 
					        Precedence=precedence2,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result["Group"]["GroupName"].should.equal(group_name)
 | 
				
			||||||
 | 
					    result["Group"]["UserPoolId"].should.equal(user_pool_id)
 | 
				
			||||||
 | 
					    result["Group"]["Description"].should.equal(description2)
 | 
				
			||||||
 | 
					    result["Group"]["RoleArn"].should.equal(role_arn2)
 | 
				
			||||||
 | 
					    result["Group"]["Precedence"].should.equal(precedence2)
 | 
				
			||||||
 | 
					    result["Group"]["LastModifiedDate"].should.be.a("datetime.datetime")
 | 
				
			||||||
 | 
					    result["Group"]["CreationDate"].should.be.a("datetime.datetime")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@mock_cognitoidp
 | 
					@mock_cognitoidp
 | 
				
			||||||
def test_group_in_access_token():
 | 
					def test_group_in_access_token():
 | 
				
			||||||
    conn = boto3.client("cognito-idp", "us-west-2")
 | 
					    conn = boto3.client("cognito-idp", "us-west-2")
 | 
				
			||||||
@ -2990,6 +3028,36 @@ def test_admin_user_global_sign_out_unknown_user():
 | 
				
			|||||||
    err["Message"].should.equal("User does not exist.")
 | 
					    err["Message"].should.equal("User does not exist.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@mock_cognitoidp
 | 
				
			||||||
 | 
					def test_global_sign_out():
 | 
				
			||||||
 | 
					    conn = boto3.client("cognito-idp", "us-west-2")
 | 
				
			||||||
 | 
					    result = user_authentication_flow(conn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    conn.global_sign_out(AccessToken=result["access_token"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with pytest.raises(ClientError) as ex:
 | 
				
			||||||
 | 
					        conn.initiate_auth(
 | 
				
			||||||
 | 
					            ClientId=result["client_id"],
 | 
				
			||||||
 | 
					            AuthFlow="REFRESH_TOKEN",
 | 
				
			||||||
 | 
					            AuthParameters={
 | 
				
			||||||
 | 
					                "REFRESH_TOKEN": result["refresh_token"],
 | 
				
			||||||
 | 
					                "SECRET_HASH": result["secret_hash"],
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    err = ex.value.response["Error"]
 | 
				
			||||||
 | 
					    err["Code"].should.equal("NotAuthorizedException")
 | 
				
			||||||
 | 
					    err["Message"].should.equal("Refresh Token has been revoked")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@mock_cognitoidp
 | 
				
			||||||
 | 
					def test_global_sign_out_unknown_accesstoken():
 | 
				
			||||||
 | 
					    conn = boto3.client("cognito-idp", "us-east-2")
 | 
				
			||||||
 | 
					    with pytest.raises(ClientError) as ex:
 | 
				
			||||||
 | 
					        conn.global_sign_out(AccessToken="n/a")
 | 
				
			||||||
 | 
					    err = ex.value.response["Error"]
 | 
				
			||||||
 | 
					    err["Code"].should.equal("NotAuthorizedException")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@mock_cognitoidp
 | 
					@mock_cognitoidp
 | 
				
			||||||
def test_admin_update_user_attributes():
 | 
					def test_admin_update_user_attributes():
 | 
				
			||||||
    conn = boto3.client("cognito-idp", "us-west-2")
 | 
					    conn = boto3.client("cognito-idp", "us-west-2")
 | 
				
			||||||
@ -3146,6 +3214,41 @@ def test_admin_delete_user_attributes_non_existing_pool():
 | 
				
			|||||||
    err["Message"].should.equal(f"User pool {user_pool_id} does not exist.")
 | 
					    err["Message"].should.equal(f"User pool {user_pool_id} does not exist.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@mock_cognitoidp
 | 
				
			||||||
 | 
					def test_update_user_attributes():
 | 
				
			||||||
 | 
					    conn = boto3.client("cognito-idp", "us-west-2")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result = authentication_flow(conn, auth_flow="ADMIN_USER_PASSWORD_AUTH")
 | 
				
			||||||
 | 
					    access_token = result["access_token"]
 | 
				
			||||||
 | 
					    username = result["username"]
 | 
				
			||||||
 | 
					    user_pool_id = result["user_pool_id"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    conn.update_user_attributes(
 | 
				
			||||||
 | 
					        AccessToken=access_token,
 | 
				
			||||||
 | 
					        UserAttributes=[
 | 
				
			||||||
 | 
					            {"Name": "family_name", "Value": "Doe"},
 | 
				
			||||||
 | 
					            {"Name": "given_name", "Value": "Jane"},
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    user = conn.admin_get_user(UserPoolId=user_pool_id, Username=username)
 | 
				
			||||||
 | 
					    attributes = user["UserAttributes"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    attributes.should.contain({"Name": "family_name", "Value": "Doe"})
 | 
				
			||||||
 | 
					    attributes.should.contain({"Name": "given_name", "Value": "Jane"})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@mock_cognitoidp
 | 
				
			||||||
 | 
					def test_update_user_attributes_unknown_accesstoken():
 | 
				
			||||||
 | 
					    conn = boto3.client("cognito-idp", "us-east-2")
 | 
				
			||||||
 | 
					    with pytest.raises(ClientError) as ex:
 | 
				
			||||||
 | 
					        conn.update_user_attributes(
 | 
				
			||||||
 | 
					            AccessToken="n/a", UserAttributes=[{"Name": "a", "Value": "b"}]
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    err = ex.value.response["Error"]
 | 
				
			||||||
 | 
					    err["Code"].should.equal("NotAuthorizedException")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@mock_cognitoidp
 | 
					@mock_cognitoidp
 | 
				
			||||||
def test_resource_server():
 | 
					def test_resource_server():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user