diff --git a/.flake8 b/.flake8 index 7584aa6..eb84764 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] max-line-length = 100 -ignore = E251, E265, E261, E302 +ignore = E251, E265, E261, E302, W503 per-file-ignores = __init__.py:F401 -exclude = server/tests/conftest.py \ No newline at end of file +exclude = server/tests/conftest.py diff --git a/server/npg/porch/models/permission.py b/server/npg/porch/models/permission.py new file mode 100644 index 0000000..f4d1cd9 --- /dev/null +++ b/server/npg/porch/models/permission.py @@ -0,0 +1,50 @@ +# Copyright (C) 2021, 2022 Genome Research Ltd. +# +# Author: Kieron Taylor kt19@sanger.ac.uk +# Author: Marina Gourtovaia mg8@sanger.ac.uk +# +# This file is part of npg_porch +# +# npg_porch is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see . + +from enum import Enum +from pydantic import BaseModel, Field, validator +from typing import Optional + +from npg.porch.models.pipeline import Pipeline + +class RolesEnum(str, Enum): + POWER_USER = 'power_user' + REGULAR_USER = 'regular_user' + +class Permission(BaseModel): + pipeline: Optional[Pipeline] = Field( + None, + title = 'An optional pipeline object', + description = 'The scope is limited to this pipeline if undefined' + ) + requestor_id: int = Field( + title = 'ID that corresponds to the presented credentials', + description = 'A validated internal ID that corresponds to the presented credentials' + ) + role: RolesEnum = Field( + title = 'A role associated with the presented credentials', + ) + + @validator('role') + def no_pipeline4special_users(cls, v, values): + if (v == RolesEnum.POWER_USER + and ('pipeline' in values and values['pipeline'] is not None)): + raise ValueError('Power user cannot be associated with a pipeline') + return v diff --git a/server/tests/model_permission_test.py b/server/tests/model_permission_test.py new file mode 100644 index 0000000..ff103e5 --- /dev/null +++ b/server/tests/model_permission_test.py @@ -0,0 +1,46 @@ +import pytest + +from npg.porch.models.pipeline import Pipeline +from npg.porch.models.permission import Permission +from pydantic.error_wrappers import ValidationError + +def test_model_create(): + '''' + Test objects can be created. + ''' + + p = Permission(requestor_id = 3, role = 'power_user') + assert type(p) is Permission + p = Permission( + requestor_id = 1, + role = 'regular_user', + pipeline = Pipeline(name='number one') + ) + assert type(p) is Permission + +def test_xvalidation_role_pipeline(): + ''' + Test cross validation for the role and pipeline fields. + ''' + + with pytest.raises( + ValidationError, + match = r'Power user cannot be associated with a pipeline'): + Permission( + requestor_id = 3, + role = 'power_user', + pipeline = Pipeline(name='number one') + ) + +def test_error_with_insufficient_args(): + + with pytest.raises(ValidationError, match=r'requestor_id\s+field required'): + Permission( + role = 'regular_user', + pipeline = Pipeline(name='number one') + ) + with pytest.raises(ValidationError, match=r'role\s+field required'): + Permission( + requestor_id = 1, + pipeline = Pipeline(name='number one') + )