diff --git a/sonar/groups.py b/sonar/groups.py index 703966d4..506a9029 100644 --- a/sonar/groups.py +++ b/sonar/groups.py @@ -200,7 +200,6 @@ def members(self, use_cache: bool = True) -> list[users.User]: if self.__members is None or not use_cache: if self.endpoint.version() >= (10, 4, 0): data = json.loads(self.get(MEMBERSHIP_API, params={"groupId": self.id}).text)["groupMemberships"] - log.debug("MEMBER DATA = %s", util.json_dump(data)) self.__members = [users.User.get_object_by_id(self.endpoint, d["userId"]) for d in data] else: data = self.endpoint.get_paginated("api/user_groups/users", return_field="users", params={"name": self.name}) @@ -305,9 +304,8 @@ def to_json(self, full_specs: bool = False) -> types.ObjectJsonRepr: def set_description(self, description: str) -> bool: """Set a group description - :param str description: The new group description + :param description: The new group description :return: Whether the new description was successfully set - :rtype: bool """ if description is None or description == self.description: log.debug("No description to update for %s", str(self)) @@ -324,13 +322,12 @@ def set_description(self, description: str) -> bool: def set_name(self, name: str) -> bool: """Set a group name - :param str name: The new group name + :param name: The new group name :return: Whether the new description was successfully set - :rtype: bool """ if name is None or name == self.name: log.debug("No name to update for %s", str(self)) - return True + return False log.debug("Updating %s with name = %s", str(self), name) if self.endpoint.version() >= (10, 4, 0): r = self.patch(f"{Group.API[c.UPDATE]}/{self.id}", params={"name": name}) @@ -349,7 +346,6 @@ def search(endpoint: pf.Platform, params: types.ApiParams = None) -> dict[str, G :params Platform endpoint: Reference to the SonarQube platform :return: dict of groups with group name as key - :rtype: dict{name: Group} """ return sq.search_objects(endpoint=endpoint, object_class=Group, params=params, api_version=2) @@ -461,7 +457,7 @@ def exists(endpoint: pf.Platform, name: str) -> bool: :param group_name: group name to check :return: whether the group exists """ - return Group.get_object(name=name, endpoint=endpoint) is not None + return Group.get_object(endpoint=endpoint, name=name) is not None def convert_for_yaml(original_json: types.ObjectJsonRepr) -> types.ObjectJsonRepr: diff --git a/sonar/users.py b/sonar/users.py index c58c0485..dd8f0682 100644 --- a/sonar/users.py +++ b/sonar/users.py @@ -200,7 +200,7 @@ def __load(self, data: types.ApiPayload) -> None: self.nb_tokens = data.get("tokenCount", None) #: Nbr of tokens - read-only else: dt1 = util.string_to_date(data.get("sonarQubeLastConnectionDate", None)) - dt2 = util.string_to_date(data.get("sonarQubeLastConnectionDate", None)) + dt2 = util.string_to_date(data.get("sonarLintLastConnectionDate", None)) if not dt1: self.last_login = dt2 elif not dt2: @@ -263,24 +263,19 @@ def tokens(self, **kwargs) -> list[tokens.UserToken]: def update(self, **kwargs) -> User: """Updates a user with name, email, login, SCM accounts, group memberships - :param name: New name of the user - :type name: str, optional - :param email: New email of the user - :type email: str, optional - :param login: New login of the user - :type login: str, optional - :param KeyList groups: List of groups to add membership - :param scm_accounts: List of SCM accounts - :type scm_accounts: list[str], optional + :param str name: Optional, New name of the user + :param str email: Optional, New email of the user + :param str login: Optional, New login of the user + :param list[str] groups: Optional, List of groups to add membership + :param list[str] scmAccounts: Optional, List of SCM accounts :return: self - :rtype: User """ log.debug("Updating %s with %s", str(self), str(kwargs)) params = self.api_params(c.UPDATE) my_data = vars(self) if self.is_local: params.update({k: kwargs[k] for k in ("name", "email") if k in kwargs and kwargs[k] != my_data[k]}) - if len(params) > 1: + if len(params) >= 1: self.post(User.API[c.UPDATE], params=params) if "scmAccounts" in kwargs: self.set_scm_accounts(kwargs["scmAccounts"]) @@ -571,3 +566,12 @@ def import_config(endpoint: pf.Platform, config_data: types.ObjectJsonRepr, key_ def convert_for_yaml(original_json: types.ObjectJsonRepr) -> types.ObjectJsonRepr: """Convert the original JSON defined for JSON export into a JSON format more adapted for YAML export""" return util.dict_to_list(original_json, "login") + + +def exists(endpoint: pf.Platform, login: str) -> bool: + """ + :param endpoint: reference to the SonarQube platform + :param login: user login to check + :return: whether the group exists + """ + return User.get_object(endpoint=endpoint, login=login) is not None diff --git a/test/test_groups.py b/test/test_groups.py index a6cd29eb..ec974c3f 100644 --- a/test/test_groups.py +++ b/test/test_groups.py @@ -147,3 +147,20 @@ def test_convert_yaml() -> None: yaml_list = groups.convert_for_yaml(data) assert len(yaml_list) == len(data) assert len(yaml_list[0]) == 2 + + +def test_set_name(get_test_group: Generator[groups.Group]) -> None: + gr = get_test_group + assert gr.name == util.TEMP_KEY + assert not gr.set_name(gr.name) + assert not gr.set_name(None) + assert gr.name == util.TEMP_KEY + gr.set_name("FOOBAR") + assert gr.name == "FOOBAR" + + +def test_create_or_update(get_test_group: Generator[groups.Group]) -> None: + gr = get_test_group + gr2 = groups.create_or_update(util.SQ, gr.name, "Some new group description") + assert gr2 is gr + assert gr.description == "Some new group description" diff --git a/test/test_users.py b/test/test_users.py index a21addef..6f44d0ac 100644 --- a/test/test_users.py +++ b/test/test_users.py @@ -89,8 +89,8 @@ def test_remove_from_group(get_test_user: Generator[users.User]) -> None: user.remove_from_group("non-existing-group") -def test_set_groups(get_test_user: Generator[users.User]) -> None: - """test_set_groups""" +def test_set_groups_2(get_test_user: Generator[users.User]) -> None: + """test_set_groups_2""" user = get_test_user # TODO(@okorach): Pick groups that exist in SonarQube groups = ["quality-managers", "tech-leads"] @@ -118,10 +118,6 @@ def test_scm_accounts(get_test_user: Generator[users.User]) -> None: assert sorted(user.scm_accounts) == sorted(list(set(scm_1) | set(scm_2))) -def test_double_match(get_test_user: Generator[users.User]) -> None: - """test_scm_accounts""" - - def test_audit_user() -> None: """audit_user""" logging.set_logger(util.TEST_LOGFILE) @@ -169,3 +165,66 @@ def test_more_than_50_users(get_60_users: Generator[list[users.User]]) -> None: new_user_list = users.get_list(util.SQ) assert len(new_user_list) > 60 assert set(new_user_list.keys()) > set(u.name for u in user_list) + + +def test_update(get_test_user: Generator[users.User]) -> None: + # test_update + user = get_test_user + assert user.groups() == ["sonar-users"] + assert user.login == util.TEMP_KEY + assert user.name == f"User name {util.TEMP_KEY}" + + user.update(groups=["sonar-administrators"]) + assert sorted(user.groups()) == ["sonar-administrators", "sonar-users"] + + assert user.scm_accounts is None + + user.update(scmAccounts=["foo@gmail.com", "bar@gmail.com", "foo", "bar"]) + assert sorted(user.scm_accounts) == sorted(["foo@gmail.com", "bar@gmail.com", "foo", "bar"]) + + user.update(login="johndoe") + assert user.login == "johndoe" + + user.update(name="John Doe", email="john@doe.com") + assert user.name == "John Doe" + assert user.email == "john@doe.com" + + user.update(login="jdoe", email="john@doe.com") + assert user.login == "jdoe" + + +def test_set_groups(get_test_user: Generator[users.User]) -> None: + user = get_test_user + user.set_groups(["sonar-administrators", "language-experts"]) + assert sorted(user.groups()) == sorted(["sonar-administrators", "language-experts"]) + + user.set_groups(["language-experts", "security-auditors", "developers"]) + assert sorted(user.groups()) == sorted(["language-experts", "security-auditors", "developers"]) + + +def test_import() -> None: + data = {} + users.import_config(util.SQ, data) + data = { + "users": { + "TEMP": {"local": True, "name": "User name TEMP", "scmAccounts": "temp@acme.com, temp@gmail.com"}, + "TEMP_ADMIN": { + "email": "admin@acme.com", + "groups": "sonar-administrators", + "local": True, + "name": "User name TEMP_ADMIN", + "scmAccounts": "admin-acme, administrator-acme", + }, + } + } + users.import_config(util.SQ, data) + for uname in "TEMP", "TEMP_ADMIN": + assert users.exists(endpoint=util.SQ, login=uname) + o_g = users.User.get_object(endpoint=util.SQ, login=uname) + assert o_g.description == f"User name {uname}" + o_g.delete() + + +def test_deactivate(get_test_user: Generator[users.User]) -> None: + user = get_test_user + assert user.deactivate()