Skip to content

Commit

Permalink
Merge pull request #18 from usnistgov/feature/config-prj-perm
Browse files Browse the repository at this point in the history
DBIO: configure the default permissions applied to new records
  • Loading branch information
RayPlante authored Nov 13, 2024
2 parents 5f95f24 + 3cf1e94 commit 9a1f1dd
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 2 deletions.
34 changes: 32 additions & 2 deletions python/nistoar/midas/dbio/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from nistoar.pdr.utils.prov import Agent, Action
from nistoar.id.versions import OARVersion
from nistoar.pdr import ARK_NAAN
from nistoar.base.config import ConfigurationException

_STATUS_ACTION_CREATE = RecordStatus.CREATE_ACTION
_STATUS_ACTION_UPDATE = RecordStatus.UPDATE_ACTION
Expand All @@ -42,10 +43,16 @@ class ProjectService(MIDASSystem):
to a particular user at construction time (as given by a :py:class:`~nistoar.pdr.utils.Agent`
instance); thus, requests to this service are subject to internal Authorization checks.
This base service supports a two parameters, ``dbio`` and ``clients``. The optional ``dbio``
parameter will be passed to the :py:class:`~nistoar.midas.dbio.base.DBClientFactory`'s
This base service supports three parameters, ``dbio``, ``default_perms``, and ``clients``. The
optional ``dbio`` parameter will be passed to the :py:class:`~nistoar.midas.dbio.base.DBClientFactory`'s
``create_client()`` function to create the :py:class:`~nistoar.midas.dbio.base.DBClient`.
The optional ``default_perms`` is an object that sets the ACLs for newly created project records.
Its optional properties name the permisson types that defaults are to be set for, including "read",
"write", "admin", and "delete" but can also include other (non-standard) category names. Each
property is a list of user identifiers that the should be given the particular type of permission.
Typically, only virtual group identifiers (like "grp0:public") make sense.
The ``clients`` parameter is an object that places restrictions on the
creation of records based on which group the user is part of. The keys of the object
are user group names that are authorized to use this service, and whose values are themselves objects
Expand Down Expand Up @@ -92,7 +99,24 @@ def __init__(self, project_type: str, dbclient_factory: DBClientFactory, config:
if not _subsysabbrev:
_subsysabbrev = "DBIO"
super(ProjectService, self).__init__(_subsys, _subsysabbrev)

# set configuration, check values
self.cfg = config
for param in "clients default_perms".split():
if not isinstance(self.cfg.get(param,{}), Mapping):
raise ConfigurationException("%s: value is not a object as required: %s" %
(param, type(self.cfg.get(param))))
for param,val in self.cfg.get('clients',{}).items():
if not isinstance(val, Mapping):
raise ConfigurationException("clients.%s: value is not a object as required: %s" %
(param, repr(val)))
for param,val in self.cfg.get('default_perms',{}).items():
if not isinstance(val, list) or not all(isinstance(p, str) for p in val):
raise ConfigurationException(
"default_perms.%s: value is not a list of strings as required: %s" %
(param, repr(val))
)

if not who:
who = Agent("dbio.project", Agent.USER, Agent.ANONYMOUS, Agent.PUBLIC)
self.who = who
Expand Down Expand Up @@ -124,6 +148,7 @@ def create_record(self, name, data=None, meta=None) -> ProjectRecord:
if self.dbcli.user_id == ANONYMOUS:
self.log.warning("A new record requested for an anonymous user")
prec = self.dbcli.create_record(name, shoulder)
self._set_default_perms(prec.acls)

if meta:
meta = self._moderate_metadata(meta, shoulder)
Expand All @@ -144,6 +169,11 @@ def create_record(self, name, data=None, meta=None) -> ProjectRecord:
self.log.info("Created %s record %s (%s) for %s", self.dbcli.project, prec.id, prec.name, self.who)
return prec

def _set_default_perms(self, acls: ACLs):
defs = self.cfg.get("default_perms", {})
for perm in defs:
acls.grant_perm_to(perm, *defs[perm])

def delete_record(self, id) -> ProjectRecord:
"""
delete the draft record. This may leave a stub record in place if, for example, the record
Expand Down
8 changes: 8 additions & 0 deletions python/tests/nistoar/midas/dbio/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ def setUp(self):
"default_shoulder": "mdm0"
}
},
"default_perms": {
"read": ["grp0:public"],
"edit": ["grp0:overlord"]
},
"dbio": {
"allowed_project_shoulders": ["mdm1", "spc1"],
"default_shoulder": "mdm0"
Expand Down Expand Up @@ -114,6 +118,10 @@ def test_create_record(self):
self.assertEqual(prec.status.message, "draft created")
self.assertEqual(prec.status.state, "edit")

self.assertEqual(prec.acls._perms.get("read"), [ self.project.who.actor, "grp0:public"])
self.assertEqual(prec.acls._perms.get("write"), [ self.project.who.actor ])
self.assertEqual(prec.acls._perms.get("edit"), [ "grp0:overlord"])

self.assertTrue(self.project.dbcli.name_exists("goob"))
prec2 = self.project.get_record(prec.id)
self.assertEqual(prec2.name, "goob")
Expand Down

0 comments on commit 9a1f1dd

Please sign in to comment.