Skip to content

Commit

Permalink
YDA-5598: remove the secured folder status
Browse files Browse the repository at this point in the history
Co-authored-by: Lazlo Westerhof <l.r.westerhof@uu.nl>
  • Loading branch information
kaur16 and lwesterhof authored Jul 30, 2024
1 parent ca28eb3 commit 3b943c3
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 62 deletions.
2 changes: 2 additions & 0 deletions browse.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ def transform(row):
status_value = status[1]
if status[0] == "research":
status_name = constants.IISTATUSATTRNAME
# Backwards compatibility for folders that hold deprecated SECURED status.
status_value = "FOLDER" if status_value == "SECURED" else status_value
else:
status_name = constants.IIVAULTSTATUSATTRNAME

Expand Down
5 changes: 3 additions & 2 deletions folder.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,8 @@ def folder_secure_succeed_avus(ctx, coll, group_name):
return False

# Note: this is the status that must always be one of the last to be set
# in folder secure, otherwise could be a problem for deposit groups
if not avu.set_on_coll(ctx, coll, constants.IISTATUSATTRNAME, constants.research_package_state.SECURED, True):
# on folder, otherwise could be a problem for deposit groups
if not avu.set_on_coll(ctx, coll, constants.IISTATUSATTRNAME, constants.research_package_state.FOLDER, True):
return False

# Remove target AVU on source folder. This should be done after all possibly failing steps
Expand Down Expand Up @@ -726,6 +726,7 @@ def get_status(ctx, path, org_metadata=None):
if constants.IISTATUSATTRNAME in org_metadata:
x = org_metadata[constants.IISTATUSATTRNAME]
try:
x = "" if x == "FOLDER" else x
return constants.research_package_state(x)
except Exception:
log.write(ctx, 'Invalid folder status <{}>'.format(x))
Expand Down
5 changes: 3 additions & 2 deletions iiConstants.r
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# \author Paul Frederiks
# \author Lazlo Westerhof
# \copyright Copyright (c) 2016-2018, Utrecht University. All rights reserved.
# \copyright Copyright (c) 2016-2024, Utrecht University. All rights reserved.
# \license GPLv3, see LICENSE.

# \constant IIGROUPPREFIX
Expand Down Expand Up @@ -59,7 +59,8 @@ IIFOLDERTRANSITIONS = list((FOLDER, LOCKED),
(REJECTED, LOCKED),
(REJECTED, FOLDER),
(REJECTED, SUBMITTED),
(ACCEPTED, SECURED),
(ACCEPTED, FOLDER),
# Backwards compatibility for folders that hold deprecated SECURED status.
(SECURED, LOCKED),
(SECURED, FOLDER),
(SECURED, SUBMITTED))
Expand Down
3 changes: 2 additions & 1 deletion iiFolderStatusTransitions.r
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,8 @@ iiCanTransitionFolderStatus(*folder, *transitionFrom, *transitionTo, *actor, *al
}
}

if (*transitionTo == SECURED) {
# Note: The folders will not transition to SECURED status.
if (*transitionFrom == ACCEPTED && *transitionTo == FOLDER) {
*allowed = false;
*reason = "Only a rodsadmin is allowed to secure a folder to the vault";
succeed;
Expand Down
93 changes: 53 additions & 40 deletions policies_folder_status.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# -*- coding: utf-8 -*-
"""Policy check functions for folder status transitions."""

__copyright__ = 'Copyright (c) 2019-2021, Utrecht University'
__copyright__ = 'Copyright (c) 2019-2024, Utrecht University'
__license__ = 'GPLv3, see LICENSE'

import time

import folder
import meta
import notifications
Expand All @@ -16,11 +18,17 @@ def pre_status_transition(ctx, coll, current, new):
if current != constants.research_package_state.LOCKED \
and new in [constants.research_package_state.LOCKED,
constants.research_package_state.SUBMITTED]:
# Backwards compatibility for folders that hold deprecated SECURED status.
# Clear action log coming from SECURED state.
# SECURED -> LOCKED and SECURED -> SUBMITTED
if current is constants.research_package_state.SECURED:
ctx.iiRemoveAVUs(coll, constants.UUORGMETADATAPREFIX + 'action_log')

# Clear action log coming from FOLDER state.
# FOLDER -> LOCKED and FOLDER -> SUBMITTED
if current is constants.research_package_state.FOLDER:
ctx.iiRemoveAVUs(coll, constants.UUORGMETADATAPREFIX + 'action_log')

# Add locks to folder, descendants and ancestors
x = ctx.iiFolderLockChange(coll, 'lock', '')
if x['arguments'][2] != '0':
Expand All @@ -29,8 +37,9 @@ def pre_status_transition(ctx, coll, current, new):
if new in [constants.research_package_state.FOLDER,
constants.research_package_state.REJECTED,
constants.research_package_state.SECURED]:
# Backwards compatibility for folders that hold deprecated SECURED status.
# Clear action log coming from SECURED state.
# SECURED -> FOLDER (backwards compatibility for v1.2 and older)
# SECURED -> FOLDER
if current is constants.research_package_state.SECURED:
ctx.iiRemoveAVUs(coll, constants.UUORGMETADATAPREFIX + 'action_log')

Expand Down Expand Up @@ -68,7 +77,7 @@ def can_transition_folder_status(ctx, actor, coll, status_from, status_to):
if group.exists(ctx, dmgrp) and not user.is_member_of(ctx, dmgrp, actor):
return policy.fail('Only a member of {} is allowed to accept or reject a submitted folder'.format(dmgrp))

elif status_to is constants.research_package_state.SECURED:
elif status_from is constants.research_package_state.ACCEPTED and status_to is constants.research_package_state.FOLDER:
actor = user.user_and_zone(ctx)
if not user.is_admin(ctx, actor):
return policy.fail('Only a rodsadmin is allowed to secure a folder to the vault')
Expand All @@ -78,6 +87,7 @@ def can_transition_folder_status(ctx, actor, coll, status_from, status_to):

def can_set_folder_status_attr(ctx, actor, coll, status):
try:
status = "" if status == "FOLDER" else status
new = constants.research_package_state(status)
except ValueError:
return policy.fail('New folder status attribute is invalid')
Expand All @@ -93,6 +103,8 @@ def can_set_folder_status_attr(ctx, actor, coll, status):

def post_status_transition(ctx, path, actor, status):
"""Post folder status transition actions."""

status = "" if status == "FOLDER" else status
status = constants.research_package_state(status)

if status is constants.research_package_state.SUBMITTED:
Expand All @@ -117,6 +129,8 @@ def post_status_transition(ctx, path, actor, status):
if pathutil.info(path).space is pathutil.Space.DEPOSIT or not folder.datamanager_exists(ctx, path):
actor = "system"

# Log action at least one second after previous action, to ensure correct order of provenance log.
time.sleep(1)
provenance.log_action(ctx, actor, path, "accepted for vault")

# Store actor of accepted for vault.
Expand All @@ -138,6 +152,42 @@ def post_status_transition(ctx, path, actor, status):
provenance_log = provenance.get_provenance_log(ctx, path)
if provenance_log[0][1] == "submitted for vault":
provenance.log_action(ctx, actor, path, "unsubmitted for vault")
elif provenance_log[0][1] == "accepted for vault":
actor = "system"
provenance.log_action(ctx, actor, path, "secured in vault")

# Send notifications to submitter and accepter
data_package = folder.get_vault_data_package(ctx, path)
submitter = folder.get_submitter(ctx, path)
accepter = folder.get_accepter(ctx, path)
message = "Data package secured in vault"
notifications.set(ctx, actor, submitter, data_package, message)
notifications.set(ctx, actor, accepter, data_package, message)

# Handle vault packages from deposit module.
if pathutil.info(path).space is pathutil.Space.DEPOSIT:
# Grant submitter (depositor) read access to vault package.
msi.set_acl(ctx, "recursive", "read", submitter, data_package)

# Retrieve Data Access Restriction of vault package.
meta_path = meta.get_collection_metadata_path(ctx, path)
open_package = False
if meta_path is not None:
metadata = jsonutil.read(ctx, meta_path)
data_access_restriction = metadata.get("Data_Access_Restriction", "")
if data_access_restriction == "Open - freely retrievable":
open_package = True

# Revoke read access for research group when data package is not open.
if not open_package:
_, _, group, _ = pathutil.info(path)
msi.set_acl(ctx, "recursive", "null", group, data_package)

# Remove deposit folder after secure in vault.
parent, _ = pathutil.chop(path)
msi.set_acl(ctx, "default", "admin:write", user.full_name(ctx), parent)
msi.set_acl(ctx, "recursive", "admin:own", user.full_name(ctx), path)
collection.remove(ctx, path)
else:
provenance.log_action(ctx, actor, path, "unlocked")

Expand All @@ -151,40 +201,3 @@ def post_status_transition(ctx, path, actor, status):
submitter = folder.get_submitter(ctx, path)
message = "Data package rejected for vault"
notifications.set(ctx, actor, submitter, path, message)

elif status is constants.research_package_state.SECURED:
actor = "system"
provenance.log_action(ctx, actor, path, "secured in vault")

# Send notifications to submitter and accepter
data_package = folder.get_vault_data_package(ctx, path)
submitter = folder.get_submitter(ctx, path)
accepter = folder.get_accepter(ctx, path)
message = "Data package secured in vault"
notifications.set(ctx, actor, submitter, data_package, message)
notifications.set(ctx, actor, accepter, data_package, message)

# Handle vault packages from deposit module.
if pathutil.info(path).space is pathutil.Space.DEPOSIT:
# Grant submitter (depositor) read access to vault package.
msi.set_acl(ctx, "recursive", "read", submitter, data_package)

# Retrieve Data Access Restriction of vault package.
meta_path = meta.get_collection_metadata_path(ctx, path)
open_package = False
if meta_path is not None:
metadata = jsonutil.read(ctx, meta_path)
data_access_restriction = metadata.get("Data_Access_Restriction", "")
if data_access_restriction == "Open - freely retrievable":
open_package = True

# Revoke read access for research group when data package is not open.
if not open_package:
_, _, group, _ = pathutil.info(path)
msi.set_acl(ctx, "recursive", "null", group, data_package)

# Remove deposit folder after secure in vault.
parent, _ = pathutil.chop(path)
msi.set_acl(ctx, "default", "admin:write", user.full_name(ctx), parent)
msi.set_acl(ctx, "recursive", "admin:own", user.full_name(ctx), path)
collection.remove(ctx, path)
12 changes: 6 additions & 6 deletions tests/features/api/api_folder.feature
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,9 @@ Feature: Folder API

Examples:
| folder | status |
| /tempZone/home/research-core-0 | SECURED |
| /tempZone/home/research-default-1 | SECURED |
| /tempZone/home/research-core-1 | SECURED |
| /tempZone/home/research-default-2 | SECURED |
| /tempZone/home/research-core-2 | SECURED |
| /tempZone/home/research-default-3 | SECURED |
| /tempZone/home/research-core-0 | FOLDER |
| /tempZone/home/research-default-1 | FOLDER |
| /tempZone/home/research-core-1 | FOLDER |
| /tempZone/home/research-default-2 | FOLDER |
| /tempZone/home/research-core-2 | FOLDER |
| /tempZone/home/research-default-3 | FOLDER |
8 changes: 4 additions & 4 deletions tests/features/api/api_search.feature
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Feature: Search API

Examples:
| status | result |
| research:SECURED | /research-core-0 |
| research:SECURED | /research-default-1 |
| research:SECURED | /research-core-1 |
| research:SECURED | /research-default-2 |
| research:FOLDER | /research-core-0 |
| research:FOLDER | /research-default-1 |
| research:FOLDER | /research-core-1 |
| research:FOLDER | /research-default-2 |
4 changes: 2 additions & 2 deletions tests/features/smoke/smoke_test.feature
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ Feature: Smoke tests
Then folder <folder> status is <status>

Examples:
| folder | status |
| /tempZone/home/research-smoke-test | SECURED |
| folder | status |
| /tempZone/home/research-smoke-test | FOLDER |


Scenario Outline: Vault meta form save in vault
Expand Down
6 changes: 3 additions & 3 deletions tests/features/ui/ui_search.feature
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ Feature: Search UI
Then result <result> is found

Examples:
| status | result |
| research:SECURED | /research-initial1 |
| status | result |
| research:FOLDER | /research-initial1 |


Scenario Outline: Search folder status from top search bar
Expand All @@ -81,4 +81,4 @@ Feature: Search UI

Examples:
| status | result |
| research:SECURED | /research-initial1 |
| research:FOLDER | /research-initial1 |
2 changes: 1 addition & 1 deletion tests/step_defs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def collection_is_unlocked(user, collection):
)
assert http_status == 200
else:
assert body["data"]["status"] == "" or body["data"]["status"] == "SECURED"
assert body["data"]["status"] == "" or body["data"]["status"] == "FOLDER"


@given(parsers.parse("{collection} is locked"))
Expand Down
3 changes: 2 additions & 1 deletion util/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ def __str__(self):
('REJECTED', 'LOCKED'),
('REJECTED', ''),
('REJECTED', 'SUBMITTED'),
('ACCEPTED', 'SECURED'),
('ACCEPTED', ''),
# Backwards compatibility for folders that hold deprecated SECURED status.
('SECURED', 'LOCKED'),
('SECURED', ''),
('SECURED', 'SUBMITTED')]]
Expand Down

0 comments on commit 3b943c3

Please sign in to comment.