Invenio module providing management APIs for users and roles/groups.
TODO: Please provide feature overview of module
Further documentation is available on https://invenio-users-resources.readthedocs.io/
Management APIs for users and roles/groups.
Home Page: https://invenio-users-resources.readthedocs.io
License: MIT License
Invenio module providing management APIs for users and roles/groups.
TODO: Please provide feature overview of module
Further documentation is available on https://invenio-users-resources.readthedocs.io/
In this issue, we need to add a locking mechanism on user moderation actions (e.g. block, approve, restore) to avoid concurrent moderation actions on the same user.
The main concern about these requests is that we could end up with an inconsistent user state. For example:
If we are not careful, the previous example could into a situation where the user appears to be restored (e.g. not blocked) but the records were not restored yet since they were being deleted when the second request was received.
See the discussion notes for more information on the issue
When a user is moderated (e.g. blocked), some actions might need to be triggered. E.g:
In this issue we should come up with a mechanism to register these "after actions" and execute them.
There are some concerns to be taken into consideration:
Package version (if known): version
related to
supplying unrecognized group-id to Get a group endpoint will result to 500 Internal server error response
quit gracefully with an error message
Traceback (most recent call last):
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask/app.py", line 2095, in __call__
return self.wsgi_app(environ, start_response)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/werkzeug/middleware/proxy_fix.py", line 187, in __call__
return self.app(environ, start_response)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/werkzeug/middleware/dispatcher.py", line 78, in __call__
return app(environ, start_response)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask/app.py", line 2095, in __call__
return self.wsgi_app(environ, start_response)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/werkzeug/middleware/proxy_fix.py", line 187, in __call__
return self.app(environ, start_response)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask/app.py", line 2080, in wsgi_app
response = self.handle_exception(e)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask/app.py", line 2077, in wsgi_app
response = self.full_dispatch_request()
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask/app.py", line 1525, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask/app.py", line 1523, in full_dispatch_request
rv = self.dispatch_request()
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask/app.py", line 1509, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask_resources/resources.py", line 65, in view
return view_meth()
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask_resources/content_negotiation.py", line 116, in inner_content_negotiation
return f(*args, **kwargs)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask_resources/parsers/decorators.py", line 51, in inner
return f(self, *args, **kwargs)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask_resources/responses.py", line 39, in inner
res = f(*args, **kwargs)
File "/home/samk13/dev/v9/invenio-users-resources/invenio_users_resources/resources/groups/resource.py", line 58, in read
item = self.service.read(
File "/home/samk13/dev/v9/invenio-users-resources/invenio_users_resources/services/groups/service.py", line 28, in read
raise LookupError(f"No group with id '{id_}'.")
LookupError: No group with id 'adminX'.
name
, title
, description
.Goal of this task is to implement the avatars for users and groups.
Overall, we'll add two new API endpoints:
GET /api/users/:id/avatar.svg
GET /api/groups/:id/avatar.svg
GET /api/users/:id/avatar.svg
and GET /api/groups/:id/avatar.svg
avatar()
to the resource (ensure correct content type is sent back).avatar()
in the service.Service method:
The colors should be injected from the config:
config.py
(see e.g. Indico's list)Later tasks:
Indico implementation see:
Note, later once we can extend the user profile, we'll look into having users choose their own color, as well as potentially uploading an image.
The search query is currently "statically" set to check for active:true AND confirmed:true
.
This can be an issue for instances that want to configure only a subset of users to be searchable (e.g. exclude "light-weight accounts" or user with specific roles) or even loosen-up the query (e.g. include unconfirmed users).
This change can be introduced via a service config variable, and possibly with the use of the FromConfig
utility become configurable via usual Invenio config (e.g. USERS_RESOURCES_DEFAULT_SEARCH_FILTER
or similar).
Requires #1
Implement the service's search method using just the database layer (i.e. the datastore implemented in Invenio-accounts).
Service:
Resource:
Both /api/users and /api/groups should require an authenticated user to access.
The method is supposed to be rewritten once we're able to index users and groups in Elasticsearch, so no parameter parsing is needed.
Package version (if known):
/api/users
should not allow ?sort=newest/oldest
but only sort=bestmatch
./api/users
should not allow empty queries (i.e. /api/users
or /api/users?q=
)/api/groups/admin
Traceback (most recent call last):
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1819, in _execute_context
self.dialect.do_execute(
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 732, in do_execute
cursor.execute(statement, parameters)
psycopg2.errors.InvalidTextRepresentation: invalid input syntax for type integer: "admin"
LINE 3: WHERE accounts_role.id = 'admin'
^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask/app.py", line 2095, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/werkzeug/middleware/proxy_fix.py", line 187, in __call__
return self.app(environ, start_response)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/werkzeug/middleware/dispatcher.py", line 78, in __call__
return app(environ, start_response)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask/app.py", line 2095, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/werkzeug/middleware/proxy_fix.py", line 187, in __call__
return self.app(environ, start_response)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask/app.py", line 2080, in wsgi_app
response = self.handle_exception(e)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask/app.py", line 2077, in wsgi_app
response = self.full_dispatch_request()
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask/app.py", line 1525, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask/app.py", line 1523, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask/app.py", line 1509, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask_resources/resources.py", line 65, in view
return view_meth()
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask_resources/content_negotiation.py", line 116, in inner_content_negotiation
return f(*args, **kwargs)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask_resources/parsers/decorators.py", line 51, in inner
return f(self, *args, **kwargs)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask_resources/responses.py", line 39, in inner
res = f(*args, **kwargs)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/invenio_users_resources/resources/groups/resource.py", line 55, in read
item = self.service.read(
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/invenio_users_resources/services/groups/service.py", line 26, in read
group = GroupAggregate.get_record(id_)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/invenio_users_resources/records/api.py", line 239, in get_record
role = current_datastore.role_model.query.get(id_)
File "<string>", line 2, in get
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/util/deprecations.py", line 401, in warned
return fn(*args, **kwargs)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/orm/query.py", line 943, in get
return self._get_impl(ident, loading.load_on_pk_identity)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/orm/query.py", line 947, in _get_impl
return self.session._get_impl(
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 2896, in _get_impl
return db_load_fn(
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/orm/loading.py", line 530, in load_on_pk_identity
session.execute(
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 1696, in execute
result = conn._execute_20(statement, params or {}, execution_options)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1631, in _execute_20
return meth(self, args_10style, kwargs_10style, execution_options)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/sql/elements.py", line 325, in _execute_on_connection
return connection._execute_clauseelement(
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1498, in _execute_clauseelement
ret = self._execute_context(
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1862, in _execute_context
self._handle_dbapi_exception(
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 2043, in _handle_dbapi_exception
util.raise_(
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
raise exception
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1819, in _execute_context
self.dialect.do_execute(
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 732, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input syntax for type integer: "admin"
LINE 3: WHERE accounts_role.id = 'admin'
^
[SQL: SELECT accounts_role.created AS accounts_role_created, accounts_role.updated AS accounts_role_updated, accounts_role.id AS accounts_role_id, accounts_role.name AS accounts_role_name, accounts_role.description AS accounts_role_description, accounts_role.version_id AS accounts_role_version_id
FROM accounts_role
WHERE accounts_role.id = %(pk_1)s]
[parameters: {'pk_1': 'admin'}]
(Background on this error at: https://sqlalche.me/e/14/9h9h)
Bootstrap a new module that will provide a REST API for users and groups needed for the communities members support.
The communities member support needs at a very high-level to:
The new module should provide two basic REST APIs:
/api/users
/api/groups
In order to bootstrap the new module fast we should simply return static JSON documents on the two API endpoints initially. Subsequent tasks will add proper implementations of the API.
Draft RFC
Groups should have an visibility parameter to allow certain groups to be hidden from the searches similar to how users are implemented.
Package version (if known): 0.1.1
When running code that does a commit , this https://github.com/inveniosoftware/invenio-users-resources/blob/master/invenio_users_resources/ext.py#L96 tries to to access session._model_changes.values()
but _model_changes
is not defined on SignallingSession (or Session https://github.com/sqlalchemy/sqlalchemy/blob/rel_1_4_35/lib/sqlalchemy/orm/session.py): I am getting AttributeError: 'SignallingSession' object has no attribute '_model_changes'
.
And since this runs on every commit, it's not great. What am I missing here (otherwise others would have encountered it and I wouldn't be the only one with failing CI tests on their modules)?
An external system should be able to create and manage users and groups via the REST API so a sync mechanism can be setup.
Review current permissions to understand the following questions:
Package version: b9416
Related to 46
following the docs. Using Postman:
Providing invalid user id will results to 500 internal server error
Quit gracefully with an error message
Traceback (most recent call last):
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask/app.py", line 2095, in __call__
return self.wsgi_app(environ, start_response)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/werkzeug/middleware/proxy_fix.py", line 187, in __call__
return self.app(environ, start_response)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/werkzeug/middleware/dispatcher.py", line 78, in __call__
return app(environ, start_response)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask/app.py", line 2095, in __call__
return self.wsgi_app(environ, start_response)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/werkzeug/middleware/proxy_fix.py", line 187, in __call__
return self.app(environ, start_response)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask/app.py", line 2080, in wsgi_app
response = self.handle_exception(e)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask/app.py", line 2077, in wsgi_app
response = self.full_dispatch_request()
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask/app.py", line 1525, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask/app.py", line 1523, in full_dispatch_request
rv = self.dispatch_request()
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask/app.py", line 1509, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask_resources/resources.py", line 65, in view
return view_meth()
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask_resources/content_negotiation.py", line 116, in inner_content_negotiation
return f(*args, **kwargs)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask_resources/parsers/decorators.py", line 51, in inner
return f(self, *args, **kwargs)
File "/home/samk13/.virtualenvs/my-site-master-venv/lib/python3.9/site-packages/flask_resources/responses.py", line 39, in inner
res = f(*args, **kwargs)
File "/home/samk13/dev/v9/invenio-users-resources/invenio_users_resources/resources/users/resource.py", line 59, in read
item = self.service.read(
File "/home/samk13/dev/v9/invenio-users-resources/invenio_users_resources/services/users/service.py", line 77, in read
raise LookupError(f"No user with id '{id_}'.")
LookupError: No user with id 'userudapsikd'.
I would like to know if we should merge this issue with 46 or keep them separate?
A user that's not found should report 403 instead of 500.
A 403 Error:
{"status": 403, "message": "Permission denied."}
Traceback (most recent call last):
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask/app.py", line 2095, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/werkzeug/middleware/proxy_fix.py", line 187, in __call__
return self.app(environ, start_response)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/werkzeug/middleware/dispatcher.py", line 78, in __call__
return app(environ, start_response)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask/app.py", line 2095, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/werkzeug/middleware/proxy_fix.py", line 187, in __call__
return self.app(environ, start_response)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask/app.py", line 2080, in wsgi_app
response = self.handle_exception(e)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask/app.py", line 2077, in wsgi_app
response = self.full_dispatch_request()
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask/app.py", line 1525, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask/app.py", line 1523, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask/app.py", line 1509, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask_resources/resources.py", line 65, in view
return view_meth()
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask_resources/content_negotiation.py", line 116, in inner_content_negotiation
return f(*args, **kwargs)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask_resources/parsers/decorators.py", line 51, in inner
return f(self, *args, **kwargs)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/flask_resources/responses.py", line 39, in inner
res = f(*args, **kwargs)
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/invenio_users_resources/resources/users/resource.py", line 59, in read
item = self.service.read(
File "/Users/lnielsen/.virtualenvs/my-site-ZNC6mTtx/lib/python3.8/site-packages/invenio_users_resources/services/users/service.py", line 77, in read
raise LookupError(f"No user with id '{id_}'.")
LookupError: No user with id '5'.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.