aboutsummaryrefslogtreecommitdiff
path: root/gn3/case_attributes.py
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2024-08-01 14:54:49 -0500
committerFrederick Muriuki Muriithi2024-08-01 14:59:24 -0500
commit025eaca42fc74fc7ed5793e9eb4959c42c1b61c9 (patch)
tree8f419414807887c563f4b4b989fbd8b435e9bbf4 /gn3/case_attributes.py
parent2d1c546ac9f4707cb30d1a3dbfea6b80c5c2cc89 (diff)
downloadgenenetwork3-025eaca42fc74fc7ed5793e9eb4959c42c1b61c9.tar.gz
Update case-attribute editing to use new authorisation.
Diffstat (limited to 'gn3/case_attributes.py')
-rw-r--r--gn3/case_attributes.py96
1 files changed, 60 insertions, 36 deletions
diff --git a/gn3/case_attributes.py b/gn3/case_attributes.py
index d973b8e..efc82e9 100644
--- a/gn3/case_attributes.py
+++ b/gn3/case_attributes.py
@@ -26,8 +26,8 @@ from gn3.commands import run_cmd
from gn3.db_utils import Connection, database_connection
+from gn3.oauth2.authorisation import require_token
from gn3.auth.authorisation.errors import AuthorisationError
-from gn3.auth.authorisation.oauth2.resource_server import require_oauth
caseattr = Blueprint("case-attribute", __name__)
@@ -61,8 +61,10 @@ class CAJSONEncoder(json.JSONEncoder):
return json.JSONEncoder.default(self, obj)
def required_access(
- inbredset_id: int, access_levels: tuple[str, ...]) -> Union[
- bool, tuple[str, ...]]:
+ token: dict,
+ inbredset_id: int,
+ access_levels: tuple[str, ...]
+) -> Union[bool, tuple[str, ...]]:
"""Check whether the user has the appropriate access"""
def __species_id__(conn):
with conn.cursor() as cursor:
@@ -71,19 +73,21 @@ def required_access(
(inbredset_id,))
return cursor.fetchone()[0]
try:
- with (require_oauth.acquire("profile resource") as the_token,
- database_connection(current_app.config["SQL_URI"]) as conn):
+ with database_connection(current_app.config["SQL_URI"]) as conn:
result = requests.get(
+ # this section fetches the resource ID from the auth server
urljoin(current_app.config["AUTH_SERVER_URL"],
"auth/resource/inbredset/resource-id"
f"/{__species_id__(conn)}/{inbredset_id}"))
if result.status_code == 200:
resource_id = result.json()["resource-id"]
auth = requests.post(
+ # this section fetches the authorisations/privileges that
+ # the current user has on the resource we got above
urljoin(current_app.config["AUTH_SERVER_URL"],
"auth/resource/authorisation"),
json={"resource-ids": [resource_id]},
- headers={"Authorization": f"Bearer {the_token.access_token}"})
+ headers={"Authorization": f"Bearer {token['access_token']}"})
if auth.status_code == 200:
privs = tuple(priv["privilege_id"]
for role in auth.json()[resource_id]["roles"]
@@ -398,14 +402,15 @@ def __apply_deletions__(
params)
def __apply_diff__(
- conn: Connection, inbredset_id: int, diff_filename, the_diff) -> None:
+ conn: Connection, auth_token, inbredset_id: int, diff_filename, the_diff) -> None:
"""
Apply the changes in the diff at `diff_filename` to the data in the database
if the user has appropriate privileges.
"""
- required_access(
- inbredset_id, ("system:inbredset:edit-case-attribute",
- "system:inbredset:apply-case-attribute-edit"))
+ required_access(auth_token,
+ inbredset_id,
+ ("system:inbredset:edit-case-attribute",
+ "system:inbredset:apply-case-attribute-edit"))
diffs = the_diff["diff"]
with conn.cursor(cursorclass=DictCursor) as cursor:
# __apply_additions__(cursor, inbredset_id, diffs["Additions"])
@@ -419,6 +424,7 @@ def __apply_diff__(
os.rename(diff_filename, new_path)
def __reject_diff__(conn: Connection,
+ auth_token: dict,
inbredset_id: int,
diff_filename: Path,
diff: dict) -> Path:
@@ -426,38 +432,45 @@ def __reject_diff__(conn: Connection,
Reject the changes in the diff at `diff_filename` to the data in the
database if the user has appropriate privileges.
"""
- required_access(
- inbredset_id, ("system:inbredset:edit-case-attribute",
- "system:inbredset:apply-case-attribute-edit"))
+ required_access(auth_token,
+ inbredset_id,
+ ("system:inbredset:edit-case-attribute",
+ "system:inbredset:apply-case-attribute-edit"))
__save_diff__(conn, diff, EditStatus.rejected)
new_path = Path(diff_filename.parent, f"{diff_filename.stem}-rejected{diff_filename.suffix}")
os.rename(diff_filename, new_path)
return diff_filename
@caseattr.route("/<int:inbredset_id>/add", methods=["POST"])
-def add_case_attributes(inbredset_id: int) -> Response:
+@require_token
+def add_case_attributes(inbredset_id: int, auth_token=None) -> Response:
"""Add a new case attribute for `InbredSetId`."""
- required_access(inbredset_id, ("system:inbredset:create-case-attribute",))
- with (require_oauth.acquire("profile resource") as the_token, # pylint: disable=[unused-variable]
- database_connection(current_app.config["SQL_URI"]) as conn): # pylint: disable=[unused-variable]
+ required_access(
+ auth_token, inbredset_id, ("system:inbredset:create-case-attribute",))
+ with database_connection(current_app.config["SQL_URI"]) as conn: # pylint: disable=[unused-variable]
raise NotImplementedError
@caseattr.route("/<int:inbredset_id>/delete", methods=["POST"])
-def delete_case_attributes(inbredset_id: int) -> Response:
+@require_token
+def delete_case_attributes(inbredset_id: int, auth_token=None) -> Response:
"""Delete a case attribute from `InbredSetId`."""
- required_access(inbredset_id, ("system:inbredset:delete-case-attribute",))
- with (require_oauth.acquire("profile resource") as the_token, # pylint: disable=[unused-variable]
- database_connection(current_app.config["SQL_URI"]) as conn): # pylint: disable=[unused-variable]
+ required_access(
+ auth_token, inbredset_id, ("system:inbredset:delete-case-attribute",))
+ with database_connection(current_app.config["SQL_URI"]) as conn: # pylint: disable=[unused-variable]
raise NotImplementedError
@caseattr.route("/<int:inbredset_id>/edit", methods=["POST"])
-def edit_case_attributes(inbredset_id: int) -> Response:
- """Edit the case attributes for `InbredSetId` based on data received."""
- with (require_oauth.acquire("profile resource") as the_token,
- database_connection(current_app.config["SQL_URI"]) as conn):
- required_access(inbredset_id,
+@require_token
+def edit_case_attributes(inbredset_id: int, auth_token = None) -> Response:
+ """Edit the case attributes for `InbredSetId` based on data received.
+
+ :inbredset_id: Identifier for the population that the case attribute belongs
+ :auth_token: A validated JWT from the auth server
+ """
+ with database_connection(current_app.config["SQL_URI"]) as conn:
+ required_access(auth_token,
+ inbredset_id,
("system:inbredset:edit-case-attribute",))
- user = the_token.user
fieldnames = tuple(["Strain"] + sorted(
attr["Name"] for attr in
__case_attribute_labels_by_inbred_set__(conn, inbredset_id)))
@@ -465,7 +478,7 @@ def edit_case_attributes(inbredset_id: int) -> Response:
diff_filename = __queue_diff__(
conn, {
"inbredset_id": inbredset_id,
- "user_id": str(user.user_id),
+ "user_id": auth_token["jwt"]["sub"],
"fieldnames": fieldnames,
"diff": __compute_diff__(
fieldnames,
@@ -488,8 +501,11 @@ def edit_case_attributes(inbredset_id: int) -> Response:
return response
try:
- __apply_diff__(
- conn, inbredset_id, diff_filename, __load_diff__(diff_filename))
+ __apply_diff__(conn,
+ auth_token,
+ inbredset_id,
+ diff_filename,
+ __load_diff__(diff_filename))
return jsonify({
"diff-status": "applied",
"message": ("The changes to the case-attributes have been "
@@ -555,37 +571,45 @@ def list_diffs(inbredset_id: int) -> Response:
return resp
@caseattr.route("/approve/<path:filename>", methods=["POST"])
-def approve_case_attributes_diff(filename: str) -> Response:
+@require_token
+def approve_case_attributes_diff(filename: str, auth_token = None) -> Response:
"""Approve the changes to the case attributes in the diff."""
diff_dir = Path(current_app.config["TMPDIR"], CATTR_DIFFS_DIR)
diff_filename = Path(diff_dir, filename)
the_diff = __load_diff__(diff_filename)
with database_connection(current_app.config["SQL_URI"]) as conn:
- __apply_diff__(conn, the_diff["inbredset_id"], diff_filename, the_diff)
+ __apply_diff__(conn, auth_token, the_diff["inbredset_id"], diff_filename, the_diff)
return jsonify({
"message": "Applied the diff successfully.",
"diff_filename": diff_filename.name
})
@caseattr.route("/reject/<path:filename>", methods=["POST"])
-def reject_case_attributes_diff(filename: str) -> Response:
+@require_token
+def reject_case_attributes_diff(filename: str, auth_token=None) -> Response:
"""Reject the changes to the case attributes in the diff."""
diff_dir = Path(current_app.config["TMPDIR"], CATTR_DIFFS_DIR)
diff_filename = Path(diff_dir, filename)
the_diff = __load_diff__(diff_filename)
with database_connection(current_app.config["SQL_URI"]) as conn:
- __reject_diff__(conn, the_diff["inbredset_id"], diff_filename, the_diff)
+ __reject_diff__(conn,
+ auth_token,
+ the_diff["inbredset_id"],
+ diff_filename,
+ the_diff)
return jsonify({
"message": "Rejected diff successfully",
"diff_filename": diff_filename.name
})
@caseattr.route("/<int:inbredset_id>/diff/<int:diff_id>/view", methods=["GET"])
-def view_diff(inbredset_id: int, diff_id: int) -> Response:
+@require_token
+def view_diff(inbredset_id: int, diff_id: int, auth_token=None) -> Response:
"""View a diff."""
with (database_connection(current_app.config["SQL_URI"]) as conn,
conn.cursor(cursorclass=DictCursor) as cursor):
- required_access(inbredset_id, ("system:inbredset:view-case-attribute",))
+ required_access(
+ auth_token, inbredset_id, ("system:inbredset:view-case-attribute",))
cursor.execute(
"SELECT * FROM caseattributes_audit WHERE id=%s",
(diff_id,))