api: add HTTP auth support to card models endpoint (#83967)

This commit is contained in:
Frédéric Péters 2024-01-06 09:25:05 +01:00
parent 2b4555564f
commit 8dd2436885
3 changed files with 47 additions and 6 deletions

View File

@ -975,6 +975,42 @@ def test_cards_http_auth_access(pub, local_user):
assert resp.json['err_desc'] == 'unsufficient roles'
def test_card_models_http_auth_access(pub, local_user):
pub.role_class.wipe()
role = pub.role_class(name='test')
role.store()
CardDef.wipe()
carddef = CardDef()
carddef.name = 'test'
carddef.store()
ApiAccess.wipe()
access = ApiAccess()
access.name = 'test'
access.access_identifier = 'test'
access.access_key = '12345'
access.store()
app = get_app(pub)
app.set_authorization(('Basic', ('test', '12345')))
# no role, no access
app.get('/api/cards/@list', status=403)
# restricted to role, but with no permissions
access.roles = [role]
access.store()
app.get('/api/cards/@list', status=403)
# permissions
pub.cfg['admin-permissions'] = {'cards': [role.id]}
pub.write_cfg()
resp = app.get('/api/cards/@list', status=200)
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['id'] == 'test'
def test_post_invalid_json(pub, local_user):
resp = get_app(pub).post(
'/api/cards/test/submit', params='not a json payload', content_type='application/json', status=400

View File

@ -581,8 +581,10 @@ class ApiCardsDirectory(Directory):
return custom_views
get_response().set_content_type('application/json')
if not (is_url_signed() or (get_request().user and get_request().user.can_go_in_admin())):
raise AccessForbiddenError('unsigned request or user is not admin')
if not is_url_signed():
user = get_user_from_api_query_string() or get_request().user
if not get_publisher().get_backoffice_root().is_global_accessible('cards', user=user):
raise AccessForbiddenError('unsigned request or API user has no access to cards')
carddefs = CardDef.select(order_by='name', ignore_errors=True, lightweight=True)
data = [
{

View File

@ -109,12 +109,15 @@ class RootDirectory(AccessControlled, Directory):
return cls.is_global_accessible(subdirectory)
@classmethod
def is_global_accessible(cls, subdirectory):
def is_global_accessible(cls, subdirectory, user=Ellipsis):
if cls.check_admin_for_all():
return True
if not get_request().user:
if user is Ellipsis:
# default to user from request
user = get_request().user
if not user:
return False
user_roles = set(get_request().user.get_roles())
user_roles = set(user.get_roles())
authorised_roles = set(get_cfg('admin-permissions', {}).get(subdirectory) or [])
if authorised_roles:
# access is governed by roles set in the settings panel
@ -122,7 +125,7 @@ class RootDirectory(AccessControlled, Directory):
# as a last resort, for the other directories, the user needs to be
# marked as admin
return get_request().user.can_go_in_admin()
return user.can_go_in_admin()
@classmethod
def check_admin_for_all(cls):