Skip to content

Commit

Permalink
Merge pull request #255 from informatics-isi-edu/reg-cat
Browse files Browse the repository at this point in the history
Expose registry as a catalog
  • Loading branch information
karlcz authored Jun 18, 2024
2 parents 91ebb21 + 793db60 commit 137db5a
Show file tree
Hide file tree
Showing 21 changed files with 773 additions and 128 deletions.
21 changes: 20 additions & 1 deletion docs/api-doc/rest-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Known feature flags at time of writing of this document:
- `quantified_value_lists`: Service supports `all(...)` and `any(...)` URL syntax for lists of values as query predicate right-hand side values.
- `quantified_rid_lists`: Service supports `RID=all(...)` and `RID=any(...)`, a bug-fix to the `quantified_value_lists` feature.
- `rid_lease`: Service supports `?nondefaults=RID` for POST operations on the `/entity/` API by clients who are not catalog owners. Such use is limited to the rules described for [Entity Creation with Defaults](data/rest.md#entity-creation-with-defaults).
- `registry_catalog`: Service supports special catalog `0` to introspect the registry, and also supports additional metadata parameters when creating catalogs and creating or updating aliases.

Generally, absence of a feature flag means the service is running
older software which predates the release of the feature. A flag will
Expand Down Expand Up @@ -81,13 +82,23 @@ This method supports an optional JSON input document:

{
"id": desired catalog id,
"owner": administrative ACL
"owner": administrative ACL,
"name": string,
"description": string,
"is_persistent": boolean,
"clone_source": string
}

These fields are optional and, if present, override the default behavior obtained in a POST without input:

- `"id"`: The desired _cid_ to bind (default is a service-generated serial number)
- `"owner"`: Initial owner-level access control list for the new catalog (default is the requesting client's identity)
- `"name"`: A short, human-readable name or title string for the catalog (default is untitled)
- `"description"`: A markdown-formatted, human-readable description for the catalog (default is empty)
- `"is_persistent"`: A boolean. When false, a deployment MAY perform auto-expiry. Supplying a value may be forbidden by policy. (Default is deployment-specific.)
- `"clone_source"`: An existing catalog ID in the same catalog, to document provenance for clones (catalogs initialized with copied content). Default is empty.

The `name`, `description`, `is_persistent`, and `clone_source` parameters are an extension understood when the service feature-advertisement includes `"registry_catalog": true`. The resulting metadata will then be visible in the corresponding entry in the registy.

On success, this request yields the new catalog identifier, e.g. `42` in this example:

Expand Down Expand Up @@ -194,13 +205,21 @@ This method supports an optional JSON input document:
"id": desired alias id,
"owner": administrative access control list,
"alias_target": existing storage catalog id
"name": string,
"description": string,
"is_persistent": boolean,
}

These fields are optional and, if present, override the default behavior obtained in a POST without input:

- `"id"`: The desired _alias_ to bind (default is a service-generated serial number)
- `"owner"`: Initial access control list for the alias (default is the requesting client's identity)
- `"alias_target"`: Storage catalog to bind with the new alias (default unbound)
- `"name"`: A short, human-readable name or title string for the catalog (default is untitled)
- `"description"`: A markdown-formatted, human-readable description for the catalog (default is empty)
- `"is_persistent"`: A boolean. When false, a deployment MAY perform auto-expiry. Supplying a value may be forbidden by policy. (Default is deployment-specific.)

The `name`, `description`, and `is_persistent` parameters are an extension understood when the service feature-advertisement includes `"registry_catalog": true`. The resulting metadata will then be visible in the corresponding entry in the registy.

An unbound alias can reserve the alias for future use by clients permitted by the adminstrative access control list.

Expand Down
2 changes: 1 addition & 1 deletion ermrest/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

#
# Copyright 2012-2019 University of Southern California
# Copyright 2012-2023 University of Southern California
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down
6 changes: 5 additions & 1 deletion ermrest/catalog.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

#
# Copyright 2013-2023 University of Southern California
# Copyright 2013-2024 University of Southern California
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -202,6 +202,10 @@ def __init__(self, factory, reg_entry, config=None):
self.dsn = self._serialize_descriptor(self.descriptor)
self._factory = factory
self.alias_target = reg_entry.get('alias_target')
self.name = reg_entry.get('name')
self.description = reg_entry.get('description')
self.is_persistent = reg_entry.get('is_persistent')
self.clone_source = reg_entry.get('clone_source')
self._config = config # Not sure we need to tuck away the config

def _serialize_descriptor(self, descriptor):
Expand Down
2 changes: 1 addition & 1 deletion ermrest/ermrest.wsgi
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

#
# Copyright 2012-2013 University of Southern California
# Copyright 2012-2023 University of Southern California
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down
10 changes: 9 additions & 1 deletion ermrest/model/column.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

#
# Copyright 2013-2023 University of Southern California
# Copyright 2013-2024 University of Southern California
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -97,6 +97,14 @@ def has_right(self, aclname, roles=None):
return False
if self.name in {'RID', 'RCB'} and aclname in {'update', 'write'}:
return False
if self.table.name == 'registry' and self.table.schema.name == 'ermrest':
if self.name == 'descriptor':
return False
if self.name in {
'id', 'is_catalog', 'deleted_on',
'owner', 'alias_target',
} and aclname in {'insert', 'update', 'write'}:
return False
if self.table.has_right(aclname, roles) is False:
return False
return self._has_right(aclname, roles)
Expand Down
7 changes: 5 additions & 2 deletions ermrest/model/key.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

#
# Copyright 2013-2023 University of Southern California
# Copyright 2013-2024 University of Southern California
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -727,7 +727,10 @@ def add(self, conn, cur):
def delete(self, conn, cur):
if self.constraint_name:
fkr_schema, fkr_name = self.constraint_name
idx_name = '_'.join(fkr_name.split('_')[:-1]) + '_idx'
# suppress deletion of registry table built-in fkeys
if fkr_schema == 'ermrest':
if fkr_name in {'registry_alias_target_fkey', 'registry_clone_source_fkey'}:
raise exception.Forbidden('owner access on built-in foreign key')
self.foreign_key.table.alter_table(
conn, cur,
'DROP CONSTRAINT %s' % sql_identifier(fkr_name),
Expand Down
2 changes: 1 addition & 1 deletion ermrest/model/name.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

#
# Copyright 2013-2021 University of Southern California
# Copyright 2013-2023 University of Southern California
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down
15 changes: 14 additions & 1 deletion ermrest/model/table.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

#
# Copyright 2013-2023 University of Southern California
# Copyright 2013-2024 University of Southern California
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -119,6 +119,10 @@ def has_right(self, aclname, roles=None):
# we need parent enumeration too
if not self.schema.has_right('enumerate', roles):
return False
# registry lifecycle changes should be via /catalog/ and /alias/ APIs
if aclname in {'insert', 'delete'}:
if self.name == 'registry' and self.schema.name == 'ermrest':
return False
# a table without history is not enumerable during historical access
if deriva_ctx.ermrest_history_snaptime is not None:
if not table_exists(deriva_ctx.ermrest_catalog_pc.cur, '_ermrest_history', 't%s' % self.rid):
Expand Down Expand Up @@ -473,6 +477,15 @@ def add_column(self, conn, cur, columndoc, ermrest_config):
def delete_column(self, conn, cur, cname):
"""Delete column from table."""
self.enforce_right('owner')
# suppress deletion of registry table built-in columns
if self.name == 'registry' and self.schema.name == 'ermrest':
if cname in {
'RID', 'RCT', 'RMT', 'RCB', 'RMB',
'id', 'is_catalog', 'deleted_on',
'owner', 'descriptor', 'alias_target',
'clone_source', 'name', 'description',
}:
raise exception.Forbidden('owner access on built-in column')
column = self.columns[cname]
self.alter_table(
conn, cur,
Expand Down
Loading

0 comments on commit 137db5a

Please sign in to comment.