Skip to content

Commit

Permalink
Expanding to support remote user mappings
Browse files Browse the repository at this point in the history
  • Loading branch information
TheBurchLog committed Feb 20, 2024
1 parent 504d423 commit 7705412
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 52 deletions.
19 changes: 13 additions & 6 deletions brewtils/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1607,15 +1607,17 @@ def __init__(
username,
password=None,
roles=None,
assigned_roles=None,
remote_roles=None,
is_remote=False,
remote_user_mapping=None,
metadata=None,
):
self.username = username
self.password = password
self.roles = roles or []
self.assigned_roles = assigned_roles or []
self.remote_roles = remote_roles or []
self.is_remote = is_remote
self.remote_user_mapping = remote_user_mapping or []
self.metadata = metadata

def __str__(self):
Expand Down Expand Up @@ -1643,7 +1645,6 @@ def __init__(
permission=None,
description=None,
id=None,
is_remote=False,
scope_gardens=None,
scope_namespaces=None,
scope_systems=None,
Expand All @@ -1655,7 +1656,6 @@ def __init__(
self.description = description
self.id = id
self.name = name
self.is_remote = is_remote
self.scope_gardens = scope_gardens or []
self.scope_namespaces = scope_namespaces or []
self.scope_systems = scope_systems or []
Expand All @@ -1668,18 +1668,25 @@ def __str__(self):

def __repr__(self):
return (
"<Role: id=%s, name=%s, permission=%s, is_remote=%s, scope_garden=%s, "
"<Role: id=%s, name=%s, permission=%s, scope_garden=%s, "
"scope_namespaces=%s, scope_systems=%s, scope_instances=%s, "
"scope_versions=%s, scope_commands=%s>"
) % (
self.id,
self.name,
self.permission,
self.is_remote,
self.scope_gardens,
self.scope_namespaces,
self.scope_systems,
self.scope_instances,
self.scope_verisons,
self.scope_commands,
)


class RemoteUserMap(BaseModel):
schema = "RemoteUserMapSchema"

def __init__(self, target_garden, username):
self.target_garden = target_garden
self.username = username
40 changes: 40 additions & 0 deletions brewtils/schema_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class SchemaParser(object):
"ResolvableSchema": brewtils.models.Resolvable,
"RoleSchema": brewtils.models.Role,
"UserSchema": brewtils.models.User,
"RemoteUserMapSchema": brewtils.models.RemoteUserMap,
}

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -280,6 +281,25 @@ def parse_role(cls, role, from_string=False, **kwargs):
"""
return cls.parse(role, brewtils.models.Role, from_string=from_string, **kwargs)

@classmethod
def parse_remote_user_map(cls, remote_user_map, from_string=False, **kwargs):
"""Convert raw JSON string or dictionary to a RemoteUserMap model object
Args:
role: The raw input
from_string: True if input is a JSON string, False if a dictionary
**kwargs: Additional parameters to be passed to the Schema (e.g. many=True)
Returns:
A RemoteUserMap object
"""
return cls.parse(
remote_user_map,
brewtils.models.RemoteUserMap,
from_string=from_string,
**kwargs
)

@classmethod
def parse_refresh_token(cls, refresh_token, from_string=False, **kwargs):
"""Convert raw JSON string or dictionary to a refresh token object
Expand Down Expand Up @@ -703,6 +723,26 @@ def serialize_role(cls, role, to_string=True, **kwargs):
role, to_string=to_string, schema_name=brewtils.models.Role.schema, **kwargs
)

@classmethod
def serialize_remote_user_map(cls, remote_user_map, to_string=True, **kwargs):
"""Convert a RemoteUserMap model into serialized form
Args:
RemoteUserMap: The RemoteUserMap object(s) to be serialized
to_string: True to generate a JSON-formatted string, False to generate a
dictionary
**kwargs: Additional parameters to be passed to the Schema (e.g. many=True)
Returns:
Serialized representation
"""
return cls.serialize(
remote_user_map,
to_string=to_string,
schema_name=brewtils.models.RemoteUserMap.schema,
**kwargs
)

@classmethod
def serialize_refresh_token(cls, refresh_token, to_string=True, **kwargs):
"""Convert a role model into serialized form
Expand Down
46 changes: 9 additions & 37 deletions brewtils/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
"OperationSchema",
"UserSchema",
"RoleSchema",
"GardenDomainIdentifierSchema",
"SystemDomainIdentifierSchema",
"RemoteUserMapSchema",
]

# This will be updated after all the schema classes are defined
Expand Down Expand Up @@ -68,26 +67,6 @@ def _deserialize_model(_, data, type_field=None, allowed_types=None):
return model_schema_map.get(data[type_field])()


def _domain_identifier_schema_selector(_, role_assignment_domain):
scope_schema_map = {
"Garden": GardenDomainIdentifierSchema,
"System": SystemDomainIdentifierSchema,
"Global": Schema,
}

if isinstance(role_assignment_domain, dict):
scope = role_assignment_domain.get("scope")
else:
scope = role_assignment_domain.scope

schema = scope_schema_map.get(scope)

if schema is None:
raise TypeError("Invalid scope: %s" % scope)

return schema()


class ModelField(PolyField):
"""Field representing a Brewtils model
Expand Down Expand Up @@ -495,10 +474,6 @@ class GardenSchema(BaseSchema):
metadata = fields.Dict(allow_none=True)


class GardenDomainIdentifierSchema(BaseSchema):
name = fields.Str(required=True)


class JobSchema(BaseSchema):
id = fields.Str(allow_none=True)
name = fields.Str(allow_none=True)
Expand Down Expand Up @@ -585,7 +560,6 @@ class RoleSchema(BaseSchema):
name = fields.Str()
description = fields.Str(allow_none=True)
permission = fields.Str()
is_remote = fields.Boolean(allow_none=True)
scope_gardens = fields.List(fields.Str(), allow_none=True)
scope_namespaces = fields.List(fields.Str(), allow_none=True)
scope_systems = fields.List(fields.Str(), allow_none=True)
Expand All @@ -594,25 +568,22 @@ class RoleSchema(BaseSchema):
scope_commands = fields.List(fields.Str(), allow_none=True)


class RemoteUserMapSchema(BaseSchema):
target_garden = fields.Str()
username = fields.Str()


class UserSchema(BaseSchema):
id = fields.Str(allow_none=True)
username = fields.Str()
password = fields.Str()
roles = fields.List(fields.Str(), allow_none=True)
assigned_roles = fields.List(fields.Nested(RoleSchema()))
remote_roles = fields.List(fields.Nested(RoleSchema()))
remote_user_mapping = fields.List(fields.Nested(RemoteUserMapSchema()))
is_remote = fields.Boolean(allow_none=True)
metadata = fields.Dict(allow_none=True)


# class UserCreateSchema(BaseSchema):
# username = fields.Str(required=True)
# password = fields.Str(required=True, load_only=True)


# class UserListSchema(BaseSchema):
# users = fields.List(fields.Nested(UserSchema()))


model_schema_map.update(
{
"Choices": ChoicesSchema,
Expand Down Expand Up @@ -644,6 +615,7 @@ class UserSchema(BaseSchema):
"Resolvable": ResolvableSchema,
"Role": RoleSchema,
"User": UserSchema,
"RemoteUserMap": RemoteUserMapSchema,
# Compatibility for the Job trigger types
"interval": IntervalTriggerSchema,
"date": DateTriggerSchema,
Expand Down
8 changes: 7 additions & 1 deletion brewtils/test/comparable.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
PatchOperation,
User,
Queue,
RemoteUserMap,
Request,
RequestFile,
RequestTemplate,
Expand All @@ -51,6 +52,7 @@
"assert_command_equal",
"assert_parameter_equal",
"assert_user_equal",
"assert_remote_user_map_equal",
"assert_request_equal",
"assert_role_equal",
"assert_system_equal",
Expand Down Expand Up @@ -193,6 +195,7 @@ def _assert_wrapper(obj1, obj2, expected_type=None, do_raise=False, **kwargs):
assert_runner_equal = partial(_assert_wrapper, expected_type=Runner)
assert_resolvable_equal = partial(_assert_wrapper, expected_type=Resolvable)
assert_connection_equal = partial(_assert_wrapper, expected_type=Connection)
assert_remote_user_map_equal = partial(_assert_wrapper, expected_type=RemoteUserMap)


def assert_command_equal(obj1, obj2, do_raise=False):
Expand Down Expand Up @@ -241,7 +244,10 @@ def assert_user_equal(obj1, obj2, do_raise=False):
obj1,
obj2,
expected_type=User,
deep_fields={"assigned_roles": partial(assert_role_equal, do_raise=True)},
deep_fields={
"remote_roles": partial(assert_role_equal, do_raise=True),
"remote_user_mapping": partial(assert_remote_user_map_equal, do_raise=True),
},
do_raise=do_raise,
)

Expand Down
25 changes: 20 additions & 5 deletions brewtils/test/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
Parameter,
PatchOperation,
Queue,
RemoteUserMap,
Request,
RequestFile,
RequestTemplate,
Expand Down Expand Up @@ -527,14 +528,26 @@ def bg_queue(queue_dict):
return Queue(**queue_dict)


@pytest.fixture
def remote_user_map_dict():
return {
"target_garden": "test",
"username": "user",
}


@pytest.fixture
def bg_remote_user_map(remote_user_map_dict):
return RemoteUserMap(**remote_user_map_dict)


@pytest.fixture
def role_dict():
return {
"permission": "ADMIN",
"description": "ADMIN ROLE",
"id": "1",
"name": "ADMIN_ROLE",
"is_remote": False,
"scope_gardens": ["FOO"],
"scope_namespaces": [],
"scope_systems": [],
Expand All @@ -550,21 +563,23 @@ def bg_role(role_dict):


@pytest.fixture
def user_dict(role_dict):
def user_dict(role_dict, remote_user_map_dict):
return {
"username": "USERNAME",
"password": "HASH",
"roles": ["ADMIN_ROLE"],
"assigned_roles": [role_dict],
"remote_roles": [role_dict],
"remote_user_mapping": [remote_user_map_dict],
"is_remote": False,
"metadata": {},
}


@pytest.fixture
def bg_user(user_dict, bg_role):
def bg_user(user_dict, bg_role, bg_remote_user_map):
dict_copy = copy.deepcopy(user_dict)
dict_copy["assigned_roles"] = [bg_role]
dict_copy["remote_roles"] = [bg_role]
dict_copy["remote_user_mapping"] = [bg_remote_user_map]
return User(**dict_copy)


Expand Down
6 changes: 3 additions & 3 deletions test/models_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ def user(self):
return User(
username="admin",
roles=["bg-admin"],
assigned_roles=[Role(name="foo", permission="ADMIN")],
remote_roles=[Role(name="foo", permission="ADMIN")],
)

def test_str(self, user):
Expand All @@ -556,8 +556,8 @@ def test_str(self, role):
def test_repr(self, role):
assert repr(role) == (
"<Role: id=None, name=bg-admin, permission=ADMIN, "
"is_remote=False, scope_garden=[], scope_namespaces=[], "
"scope_systems=[], scope_instances=[], scope_versions=[], scope_commands=[]>"
"scope_garden=[], scope_namespaces=[], scope_systems=[], "
"scope_instances=[], scope_versions=[], scope_commands=[]>"
)


Expand Down
Loading

0 comments on commit 7705412

Please sign in to comment.