Skip to content

Commit

Permalink
Allow avoiding inclusion of other permissions
Browse files Browse the repository at this point in the history
Permission mapping items can have optional field "testcases_ignore" with
list of patterns to avoid matching specific test case names that are
otherwise matched by "testcases".

JIRA: RHELWF-10228
  • Loading branch information
hluk committed Nov 30, 2023
1 parent 4dc5a76 commit 397135b
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 15 deletions.
29 changes: 28 additions & 1 deletion tests/test_api_v10.py
Original file line number Diff line number Diff line change
Expand Up @@ -886,7 +886,7 @@ def test_permissions_endpoint(client):
"maintainers": ["alice@example.com"],
"_testcase_regex_pattern": "^kernel-qe",
"groups": ["devel", "qa"],
"users": ["alice@example.com"],
"users": ["alice"],
},
{
"name": "Greenwave Tests",
Expand Down Expand Up @@ -928,6 +928,33 @@ def test_permissions_endpoint(client):
assert f"<td>{config['PERMISSIONS'][1]['name']}</td>" in r.text


def test_permissions_endpoint_include_following(client):
config = {
'PERMISSIONS': [
{
"name": "Security",
"testcases": ["security.*"],
"groups": ["security"],
},
{
"name": "Development",
"testcases": ["*"],
"groups": ["devel"],
"testcases_ignore": ["security.*"],
}
]
}

with patch.dict(client.application.config, config):
r = client.get('/api/v1.0/permissions?testcase=security.test1')
assert r.status_code == 200, r.text
assert r.json == config['PERMISSIONS'][0:1]

r = client.get('/api/v1.0/permissions?testcase=security-not.test1')
assert r.status_code == 200, r.text
assert r.json == config['PERMISSIONS'][1:]


def test_config_endpoint_superusers(client):
config = {
'SUPERUSERS': ['alice', 'bob']
Expand Down
15 changes: 14 additions & 1 deletion waiverdb/api_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,18 @@ def get(self):
"""
Returns the waiver permissions.
Each entry has "testcases" (list of glob patterns for matching test
case name) and "users" or "groups".
Optional "testcases_ignore" (similar to "testcases") allows to ignore a
permission entry on a matching test case name.
The full list of users and groups permitted to waive given test case is
constructed by iterating the permissions in order and adding "users"
and "groups" from each permission entry which has at least one pattern
in "testcases" matching the test case name and no matching pattern in
"testcases_ignore".
**Sample response**:
.. sourcecode:: none
Expand All @@ -696,8 +708,9 @@ def get(self):
"name": "kernel-qe",
"maintainers": ["alice@example.com"],
"testcases": ["kernel-qe.*"],
"testcases_ignore": ["kernel-qe.unwaivable.*"],
"groups": ["devel", "qa"],
"users": ["alice@example.com"]
"users": ["alice@example.com"],
},
{
"name": "Greenwave Tests",
Expand Down
12 changes: 8 additions & 4 deletions waiverdb/authorization.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,17 @@ def get_group_membership(ldap, user, con, ldap_search):
raise Unauthorized('Some error occurred initializing the LDAP connection.')


def match_testcase(testcase: str, patterns: dict[str, Any]):
return any(fnmatch(testcase, pattern) for pattern in patterns)


def match_testcase_permissions(testcase: str, permissions: list[dict[str, Any]]):
for permission in permissions:
if match_testcase(testcase, permission.get("testcases_ignore", [])):
continue

if "testcases" in permission:
testcase_match = any(
fnmatch(testcase, testcase_pattern)
for testcase_pattern in permission["testcases"]
)
testcase_match = match_testcase(testcase, permission["testcases"])
elif "_testcase_regex_pattern" in permission:
testcase_match = re.search(
permission["_testcase_regex_pattern"], testcase)
Expand Down
4 changes: 4 additions & 0 deletions waiverdb/templates/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
{% block scripts %}
{% endblock %}

<style>
tr ul { padding-left: 1rem; }
</style>
</head>

<body>
Expand Down
22 changes: 13 additions & 9 deletions waiverdb/templates/permissions.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,23 @@
{% for p in permissions -%}
<tr>
<td>{{ p["name"] }}</td>
<td>{{ p["maintainers"] | map("urlize") | join(" ") | safe }}</td>
<td>{{ p["testcases"] | join("<br />") | replace('-', '&#8209;') | safe }}</td>
<td><ul>
{%- for maintainer in p["maintainers"] %}<li>{{ maintainer | urlize }}</li>{% endfor -%}
</ul></td>
<td><ul>
{%- if p["_testcase_regex_pattern"] -%}<li><code>/{{ p["_testcase_regex_pattern"] }}/</code></li>{%- endif -%}
{%- for testcase in p["testcases_ignore"] %}<li><b>NOT</b> <code>{{ testcase }}</code></li>{% endfor -%}
{%- for testcase in p["testcases"] %}<li><code>{{ testcase }}</code></li>{% endfor -%}
</ul></td>
<td>
{% if p["groups"] | length > 0 -%}
<span class="font-weight-bold">Groups:</span><br />
{{ p["groups"] | join("<br />") | replace('-', '&#8209;') | safe }}
{% if p["users"] | length > 0 -%}
<br />
{%- endif %}
<b>Groups:</b>
<ul>{%- for group in p["groups"] %}<li>{{ group }}</li>{% endfor -%}</ul>
{%- endif %}

{% if p["users"] | length > 0 -%}
<span class="font-weight-bold">Users:</span><br />
{{ p["users"] | join("<br />") | replace('-', '&#8209;') | safe }}
<b>Users:</b>
<ul>{%- for user in p["users"] %}<li>{{ user }}</li>{% endfor -%}</ul>
{%- endif %}
</td>
</tr>
Expand Down

0 comments on commit 397135b

Please sign in to comment.