Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Stephan Huber 2018-10-24 11:27:49 +02:00
commit 4fdc8f8136
11 changed files with 153 additions and 16 deletions

View File

@ -835,8 +835,8 @@
- [ ] admin_delete_user
- [ ] admin_delete_user_attributes
- [ ] admin_disable_provider_for_user
- [ ] admin_disable_user
- [ ] admin_enable_user
- [X] admin_disable_user
- [X] admin_enable_user
- [ ] admin_forget_device
- [ ] admin_get_device
- [ ] admin_get_user

View File

@ -606,8 +606,15 @@ class APIGatewayBackend(BaseBackend):
self.usage_plans[plan['id']] = plan
return plan
def get_usage_plans(self):
return list(self.usage_plans.values())
def get_usage_plans(self, api_key_id=None):
plans = list(self.usage_plans.values())
if api_key_id is not None:
plans = [
plan
for plan in plans
if self.usage_plan_keys.get(plan['id'], {}).get(api_key_id, False)
]
return plans
def get_usage_plan(self, usage_plan_id):
return self.usage_plans[usage_plan_id]

View File

@ -255,7 +255,8 @@ class APIGatewayResponse(BaseResponse):
if self.method == 'POST':
usage_plan_response = self.backend.create_usage_plan(json.loads(self.body))
elif self.method == 'GET':
usage_plans_response = self.backend.get_usage_plans()
api_key_id = self.querystring.get("keyId", [None])[0]
usage_plans_response = self.backend.get_usage_plans(api_key_id=api_key_id)
return 200, {}, json.dumps({"item": usage_plans_response})
return 200, {}, json.dumps(usage_plan_response)

View File

@ -383,7 +383,7 @@ class CognitoIdpBackend(BaseBackend):
raise ResourceNotFoundError(user_pool_id)
if username not in user_pool.users:
raise ResourceNotFoundError(username)
raise UserNotFoundError(username)
return user_pool.users[username]
@ -394,13 +394,21 @@ class CognitoIdpBackend(BaseBackend):
return user_pool.users.values()
def admin_disable_user(self, user_pool_id, username):
user = self.admin_get_user(user_pool_id, username)
user.enabled = False
def admin_enable_user(self, user_pool_id, username):
user = self.admin_get_user(user_pool_id, username)
user.enabled = True
def admin_delete_user(self, user_pool_id, username):
user_pool = self.user_pools.get(user_pool_id)
if not user_pool:
raise ResourceNotFoundError(user_pool_id)
if username not in user_pool.users:
raise ResourceNotFoundError(username)
raise UserNotFoundError(username)
del user_pool.users[username]

View File

@ -160,6 +160,18 @@ class CognitoIdpResponse(BaseResponse):
"Users": [user.to_json(extended=True) for user in users]
})
def admin_disable_user(self):
user_pool_id = self._get_param("UserPoolId")
username = self._get_param("Username")
cognitoidp_backends[self.region].admin_disable_user(user_pool_id, username)
return ""
def admin_enable_user(self):
user_pool_id = self._get_param("UserPoolId")
username = self._get_param("Username")
cognitoidp_backends[self.region].admin_enable_user(user_pool_id, username)
return ""
def admin_delete_user(self):
user_pool_id = self._get_param("UserPoolId")
username = self._get_param("Username")

View File

@ -265,9 +265,9 @@ class Item(BaseModel):
self.attrs[attribute_name] = DynamoType({"SS": new_value})
elif isinstance(new_value, dict):
self.attrs[attribute_name] = DynamoType({"M": new_value})
elif update_action['Value'].keys() == ['N']:
elif set(update_action['Value'].keys()) == set(['N']):
self.attrs[attribute_name] = DynamoType({"N": new_value})
elif update_action['Value'].keys() == ['NULL']:
elif set(update_action['Value'].keys()) == set(['NULL']):
if attribute_name in self.attrs:
del self.attrs[attribute_name]
else:

View File

@ -255,7 +255,15 @@ class Group(BaseModel):
@property
def arn(self):
return "arn:aws:iam::{0}:group/{1}".format(ACCOUNT_ID, self.path)
if self.path == '/':
return "arn:aws:iam::{0}:group/{1}".format(ACCOUNT_ID, self.name)
else:
return "arn:aws:iam::{0}:group/{1}/{2}".format(ACCOUNT_ID, self.path, self.name)
@property
def create_date(self):
return self.created
def get_policy(self, policy_name):
try:

View File

@ -285,7 +285,7 @@ class IamResponse(BaseResponse):
def create_group(self):
group_name = self._get_param('GroupName')
path = self._get_param('Path')
path = self._get_param('Path', '/')
group = iam_backend.create_group(group_name, path)
template = self.response_template(CREATE_GROUP_TEMPLATE)
@ -1007,6 +1007,7 @@ CREATE_GROUP_TEMPLATE = """<CreateGroupResponse>
<GroupName>{{ group.name }}</GroupName>
<GroupId>{{ group.id }}</GroupId>
<Arn>{{ group.arn }}</Arn>
<CreateDate>{{ group.create_date }}</CreateDate>
</Group>
</CreateGroupResult>
<ResponseMetadata>
@ -1021,6 +1022,7 @@ GET_GROUP_TEMPLATE = """<GetGroupResponse>
<GroupName>{{ group.name }}</GroupName>
<GroupId>{{ group.id }}</GroupId>
<Arn>{{ group.arn }}</Arn>
<CreateDate>{{ group.create_date }}</CreateDate>
</Group>
<Users>
{% for user in group.users %}
@ -1384,10 +1386,6 @@ GET_ACCOUNT_AUTHORIZATION_DETAILS_TEMPLATE = """<GetAccountAuthorizationDetailsR
</member>
{% endfor %}
</UserDetailList>
<Marker>
EXAMPLEkakv9BCuUNFDtxWSyfzetYwEx2ADc8dnzfvERF5S6YMvXKx41t6gCl/eeaCX3Jo94/
bKqezEAg8TEVS99EKFLxm3jtbpl25FDWEXAMPLE
</Marker>
<GroupDetailList>
{% for group in groups %}
<member>

View File

@ -1084,3 +1084,36 @@ def test_create_usage_plan_key_non_existent_api_key():
# Attempt to create a usage plan key for a API key that doesn't exists
payload = {'usagePlanId': usage_plan_id, 'keyId': 'non-existent', 'keyType': 'API_KEY' }
client.create_usage_plan_key.when.called_with(**payload).should.throw(ClientError)
@mock_apigateway
def test_get_usage_plans_using_key_id():
region_name = 'us-west-2'
client = boto3.client('apigateway', region_name=region_name)
# Create 2 Usage Plans
# one will be attached to an API Key, the other will remain unattached
attached_plan = client.create_usage_plan(name='Attached')
unattached_plan = client.create_usage_plan(name='Unattached')
# Create an API key
# to attach to the usage plan
key_name = 'test-api-key'
response = client.create_api_key(name=key_name)
key_id = response["id"]
# Create a Usage Plan Key
# Attached the Usage Plan and API Key
key_type = 'API_KEY'
payload = {'usagePlanId': attached_plan['id'], 'keyId': key_id, 'keyType': key_type}
response = client.create_usage_plan_key(**payload)
# All usage plans should be returned when keyId is not included
all_plans = client.get_usage_plans()
len(all_plans['items']).should.equal(2)
# Only the usage plan attached to the given api key are included
only_plans_with_key = client.get_usage_plans(keyId=key_id)
len(only_plans_with_key['items']).should.equal(1)
only_plans_with_key['items'][0]['name'].should.equal(attached_plan['name'])
only_plans_with_key['items'][0]['id'].should.equal(attached_plan['id'])

View File

@ -343,6 +343,7 @@ def test_admin_create_user():
result["User"]["Attributes"].should.have.length_of(1)
result["User"]["Attributes"][0]["Name"].should.equal("thing")
result["User"]["Attributes"][0]["Value"].should.equal(value)
result["User"]["Enabled"].should.equal(True)
@mock_cognitoidp
@ -367,6 +368,22 @@ def test_admin_get_user():
result["UserAttributes"][0]["Value"].should.equal(value)
@mock_cognitoidp
def test_admin_get_missing_user():
conn = boto3.client("cognito-idp", "us-west-2")
username = str(uuid.uuid4())
user_pool_id = conn.create_user_pool(PoolName=str(uuid.uuid4()))["UserPool"]["Id"]
caught = False
try:
conn.admin_get_user(UserPoolId=user_pool_id, Username=username)
except conn.exceptions.UserNotFoundException:
caught = True
caught.should.be.true
@mock_cognitoidp
def test_list_users():
conn = boto3.client("cognito-idp", "us-west-2")
@ -379,6 +396,37 @@ def test_list_users():
result["Users"][0]["Username"].should.equal(username)
@mock_cognitoidp
def test_admin_disable_user():
conn = boto3.client("cognito-idp", "us-west-2")
username = str(uuid.uuid4())
user_pool_id = conn.create_user_pool(PoolName=str(uuid.uuid4()))["UserPool"]["Id"]
conn.admin_create_user(UserPoolId=user_pool_id, Username=username)
result = conn.admin_disable_user(UserPoolId=user_pool_id, Username=username)
list(result.keys()).should.equal(["ResponseMetadata"]) # No response expected
conn.admin_get_user(UserPoolId=user_pool_id, Username=username) \
["Enabled"].should.equal(False)
@mock_cognitoidp
def test_admin_enable_user():
conn = boto3.client("cognito-idp", "us-west-2")
username = str(uuid.uuid4())
user_pool_id = conn.create_user_pool(PoolName=str(uuid.uuid4()))["UserPool"]["Id"]
conn.admin_create_user(UserPoolId=user_pool_id, Username=username)
conn.admin_disable_user(UserPoolId=user_pool_id, Username=username)
result = conn.admin_enable_user(UserPoolId=user_pool_id, Username=username)
list(result.keys()).should.equal(["ResponseMetadata"]) # No response expected
conn.admin_get_user(UserPoolId=user_pool_id, Username=username) \
["Enabled"].should.equal(True)
@mock_cognitoidp
def test_admin_delete_user():
conn = boto3.client("cognito-idp", "us-west-2")
@ -391,7 +439,7 @@ def test_admin_delete_user():
caught = False
try:
conn.admin_get_user(UserPoolId=user_pool_id, Username=username)
except conn.exceptions.ResourceNotFoundException:
except conn.exceptions.UserNotFoundException:
caught = True
caught.should.be.true

View File

@ -1,4 +1,7 @@
from __future__ import unicode_literals
from datetime import datetime
import boto
import boto3
import sure # noqa
@ -25,6 +28,25 @@ def test_get_group():
conn.get_group('not-group')
@mock_iam()
def test_get_group_current():
conn = boto3.client('iam', region_name='us-east-1')
conn.create_group(GroupName='my-group')
result = conn.get_group(GroupName='my-group')
assert result['Group']['Path'] == '/'
assert result['Group']['GroupName'] == 'my-group'
assert isinstance(result['Group']['CreateDate'], datetime)
assert result['Group']['GroupId']
assert result['Group']['Arn'] == 'arn:aws:iam::123456789012:group/my-group'
assert not result['Users']
# Make a group with a different path:
other_group = conn.create_group(GroupName='my-other-group', Path='some/location')
assert other_group['Group']['Path'] == 'some/location'
assert other_group['Group']['Arn'] == 'arn:aws:iam::123456789012:group/some/location/my-other-group'
@mock_iam_deprecated()
def test_get_all_groups():
conn = boto.connect_iam()