diff --git a/invenio_users_resources/ext.py b/invenio_users_resources/ext.py index 9de0689..4ab6409 100644 --- a/invenio_users_resources/ext.py +++ b/invenio_users_resources/ext.py @@ -85,4 +85,4 @@ def _after_rollback(session): # rollbacked. In a case (e.g. nested transactions) when an # exception is caught and then the session is commited, # the sets might not reflect all the users that were changed. - current_db_change_history._clear_dirty_sets(session) + current_db_change_history.clear_dirty_sets(session) diff --git a/invenio_users_resources/records/api.py b/invenio_users_resources/records/api.py index 5947b86..43add44 100644 --- a/invenio_users_resources/records/api.py +++ b/invenio_users_resources/records/api.py @@ -53,9 +53,10 @@ def parse_user_data(user): def parse_role_data(role): """Parse the role's information into a dictionary.""" data = { - "id": role.name, # due to flask security exposing user id - "name": role.description, - "is_managed": True, # TODO + "id": role.id, + "name": role.name, + "description": role.description, + "is_managed": role.is_managed, } return data @@ -189,6 +190,9 @@ class GroupAggregate(Record): name = DictField("name") """The group's name.""" + description = DictField("description") + """The group's description.""" + is_managed = DictField("is_managed") """If the group is managed manually.""" diff --git a/invenio_users_resources/records/hooks.py b/invenio_users_resources/records/hooks.py index 615d742..bcfd20a 100644 --- a/invenio_users_resources/records/hooks.py +++ b/invenio_users_resources/records/hooks.py @@ -21,8 +21,8 @@ def pre_commit(sender, session): # it seems that the {dirty,new,deleted} sets aren't populated # in after_commit anymore, that's why we need to collect the # information here. - # session is a scoped_session and does not have _model_changes - # so we have rely only on .dirty + # session is a scoped_session and does not have _model_changes, + # so we have to rely only on .dirty updated = session.dirty.union(session.new) deleted = session.deleted sid = id(session) @@ -31,19 +31,17 @@ def pre_commit(sender, session): # users need to be reindexed if their user model was updated, or # their profile was changed (or even possibly deleted) - current_db_change_history.updated_users[sid].extend( - [u.id for u in updated if isinstance(u, User)] - ) - current_db_change_history.updated_roles[sid].extend( - [r.id for r in updated if isinstance(r, Role)] - ) + for item in updated: + if isinstance(item, User): + current_db_change_history.add_updated_user(sid, item.id) + if isinstance(item, Role): + current_db_change_history.add_updated_role(sid, item.id) - current_db_change_history.deleted_users[sid].extend( - [u.id for u in deleted if isinstance(u, User)] - ) - current_db_change_history.deleted_roles[sid].extend( - [r.id for r in deleted if isinstance(r, Role)] - ) + for item in deleted: + if isinstance(item, User): + current_db_change_history.add_deleted_user(sid, item.id) + if isinstance(item, Role): + current_db_change_history.add_deleted_role(sid, item.id) def post_commit(sender, session): @@ -52,15 +50,15 @@ def post_commit(sender, session): # DB operations are allowed here, not even lazy-loading of # properties! sid = id(session) - for user_id in current_db_change_history.updated_users[sid]: - reindex_user.delay(user_id) + if current_db_change_history.sessions.get(sid): + for user_id in current_db_change_history.sessions[sid].updated_users: + reindex_user.delay(user_id) - for role_id in current_db_change_history.updated_roles[sid]: - reindex_group.delay(role_id) + for role_id in current_db_change_history.sessions[sid].updated_roles: + reindex_group.delay(role_id) - for user_id in current_db_change_history.deleted_users[sid]: - unindex_user.delay(user_id) - for role_id in current_db_change_history.deleted_roles[sid]: - unindex_group.delay(role_id) + for user_id in current_db_change_history.sessions[sid].deleted_users: + unindex_user.delay(user_id) - current_db_change_history._clear_dirty_sets(session) + for role_id in current_db_change_history.sessions[sid].deleted_roles: + unindex_group.delay(role_id) diff --git a/invenio_users_resources/records/mappings/os-v1/groups/group-v1.0.0.json b/invenio_users_resources/records/mappings/os-v1/groups/group-v1.0.0.json index b3ef440..7b1acc8 100644 --- a/invenio_users_resources/records/mappings/os-v1/groups/group-v1.0.0.json +++ b/invenio_users_resources/records/mappings/os-v1/groups/group-v1.0.0.json @@ -28,6 +28,9 @@ } } }, + "description": { + "type": "text" + }, "provider": { "type": "text" }, diff --git a/invenio_users_resources/records/mappings/os-v2/groups/group-v1.0.0.json b/invenio_users_resources/records/mappings/os-v2/groups/group-v1.0.0.json index b3ef440..7b1acc8 100644 --- a/invenio_users_resources/records/mappings/os-v2/groups/group-v1.0.0.json +++ b/invenio_users_resources/records/mappings/os-v2/groups/group-v1.0.0.json @@ -28,6 +28,9 @@ } } }, + "description": { + "type": "text" + }, "provider": { "type": "text" }, diff --git a/invenio_users_resources/records/mappings/v7/groups/group-v1.0.0.json b/invenio_users_resources/records/mappings/v7/groups/group-v1.0.0.json index b3ef440..7b1acc8 100644 --- a/invenio_users_resources/records/mappings/v7/groups/group-v1.0.0.json +++ b/invenio_users_resources/records/mappings/v7/groups/group-v1.0.0.json @@ -28,6 +28,9 @@ } } }, + "description": { + "type": "text" + }, "provider": { "type": "text" }, diff --git a/run-tests.sh b/run-tests.sh index 7dd4e9d..537d00b 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -19,6 +19,23 @@ set -o errexit # Quit on unbound symbols set -o nounset +keep_services=0 +pytest_args=() +for arg in $@; do + # from the CLI args, filter out some known values and forward the rest to "pytest" + # note: we don't use "getopts" here b/c of some limitations (e.g. long options), + # which means that we can't combine short options (e.g. "./run-tests -Kk pattern") + case ${arg} in + -K|--keep-services) + keep_services=1 + ;; + *) + pytest_args+=( ${arg} ) + ;; + esac +done + + # Always bring down docker services function cleanup() { eval "$(docker-services-cli down --env)" @@ -29,6 +46,6 @@ python -m check_manifest python -m setup extract_messages --output-file /dev/null python -m sphinx.cmd.build -qnNW docs docs/_build/html eval "$(docker-services-cli up --db ${DB:-postgresql} --search ${SEARCH:-opensearch} --cache ${CACHE:-redis} --mq ${MQ:-rabbitmq} --env)" -python -m pytest +python -m pytest ${pytest_args[@]+"${pytest_args[@]}"} tests_exit_code=$? exit "$tests_exit_code" diff --git a/setup.cfg b/setup.cfg index 280decb..b6e09cc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,11 +27,11 @@ packages = find: python_requires = >=3.7 zip_safe = False install_requires = - invenio-accounts>=2.2.0,<3.0.0 + invenio-accounts>=3.0.0,<4.0.0 invenio-i18n>=2.0.0 invenio-notifications>=0.1.0,<1.0.0 - invenio-oauthclient>=2.2.0,<3.0.0 - invenio-records-resources>=4.0.0,<5.0.0 + invenio-oauthclient>=3.0.0,<4.0.0 + invenio-records-resources>=4.3.0,<5.0.0 [options.extras_require] tests = diff --git a/tests/conftest.py b/tests/conftest.py index eca4183..f01eeca 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -213,9 +213,11 @@ def users(UserFixture, app, database, users_data): return users -def _create_group(name, description, database): +def _create_group(id, name, description, is_managed, database): """Creates a Role/Group.""" - r = current_datastore.create_role(name=name, description=description) + r = current_datastore.create_role( + id=id, name=name, description=description, is_managed=is_managed + ) current_datastore.commit() return r @@ -224,20 +226,38 @@ def _create_group(name, description, database): @pytest.fixture(scope="module") def group(database): """A single group.""" - r = _create_group(name="it-dep", description="IT Department", database=database) + r = _create_group( + id="it-dep", + name="it-dep", + description="IT Department", + is_managed=True, + database=database, + ) GroupAggregate.index.refresh() return r @pytest.fixture(scope="module") -def groups(database, group): +def group2(database): """A single group.""" - roles = [group] # it-dep - roles.append( - _create_group(name="hr-dep", description="HR Department", database=database) + r = _create_group( + id="hr-dep", + name="hr-dep", + description="HR Department", + is_managed=True, + database=database, ) + GroupAggregate.index.refresh() + return r + + +@pytest.fixture(scope="module") +def groups(database, group, group2): + """A single group.""" + roles = [group, group2] + GroupAggregate.index.refresh() return roles