Skip to content

Commit

Permalink
Merge pull request #357 from uc-cdis/feat/DCF-450-Drs-description-and…
Browse files Browse the repository at this point in the history
…-timestamps

feat(DCF-450): Add DRS Fields
  • Loading branch information
k-burt-uch authored Apr 25, 2023
2 parents 5f0435b + 145cb3e commit 6cf4627
Show file tree
Hide file tree
Showing 14 changed files with 596 additions and 34 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,5 @@ docs/_build/
local_settings.py
settings.yaml
*.sq3
#IDEs
.idea
24 changes: 21 additions & 3 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,15 @@
"line_number": 14
}
],
"migrations/versions/a72f117515c5_add_description_created_time_and_.py": [
{
"type": "Hex High Entropy String",
"filename": "migrations/versions/a72f117515c5_add_description_created_time_and_.py",
"hashed_secret": "7c52f05d2823f0becb8196c04678c822ac71bcdf",
"is_verified": false,
"line_number": 14
}
],
"tests/default_test_settings.py": [
{
"type": "Basic Auth Credentials",
Expand All @@ -242,6 +251,15 @@
"line_number": 18
}
],
"tests/postgres/migrations/test_a72f117515c5_add_description_created_time_and_.py": [
{
"type": "Hex High Entropy String",
"filename": "tests/postgres/migrations/test_a72f117515c5_add_description_created_time_and_.py",
"hashed_secret": "7c52f05d2823f0becb8196c04678c822ac71bcdf",
"is_verified": false,
"line_number": 21
}
],
"tests/postgres/migrations/test_legacy_schema_migration.py": [
{
"type": "Hex High Entropy String",
Expand Down Expand Up @@ -382,7 +400,7 @@
"filename": "tests/test_deprecated_aliases_endpoints.py",
"hashed_secret": "5666c088b494f26cd8f63ace013992f5fc391ce0",
"is_verified": false,
"line_number": 12
"line_number": 13
}
],
"tests/test_drs.py": [
Expand All @@ -391,9 +409,9 @@
"filename": "tests/test_drs.py",
"hashed_secret": "5666c088b494f26cd8f63ace013992f5fc391ce0",
"is_verified": false,
"line_number": 32
"line_number": 38
}
]
},
"generated_at": "2023-04-13T17:00:13Z"
"generated_at": "2023-04-20T22:58:41Z"
}
15 changes: 10 additions & 5 deletions indexd/drs/blueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def indexd_to_drs(record, expand=False):

name = record["file_name"] if "file_name" in record else record["name"]

created_time = (
index_created_time = (
record["created_date"] if "created_date" in record else record["created_time"]
)

Expand All @@ -162,10 +162,14 @@ def indexd_to_drs(record, expand=False):
else ""
)

updated_date = (
index_updated_time = (
record["updated_date"] if "updated_date" in record else record["updated_time"]
)

content_created_date = record.get("content_created_date", "")

content_updated_date = record.get("content_updated_date", "")

form = record["form"] if "form" in record else "bundle"

description = record["description"] if "description" in record else None
Expand All @@ -180,11 +184,12 @@ def indexd_to_drs(record, expand=False):

drs_object = {
"id": did,
"description": "",
"mime_type": "application/json",
"name": name,
"created_time": created_time,
"updated_time": updated_date,
"index_created_time": index_created_time,
"index_updated_time": index_updated_time,
"created_time": content_created_date,
"updated_time": content_updated_date,
"size": record["size"],
"aliases": alias,
"self_uri": self_uri,
Expand Down
41 changes: 40 additions & 1 deletion indexd/index/blueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,21 @@ def post_index_record():
version = flask.request.json.get("version")
baseid = flask.request.json.get("baseid")
uploader = flask.request.json.get("uploader")
description = flask.request.json.get("description")
content_created_date = flask.request.json.get("content_created_date")
content_updated_date = flask.request.json.get("content_updated_date")

if content_updated_date is None:
content_updated_date = content_created_date

if content_updated_date is not None and content_created_date is None:
raise UserError("Cannot set content_updated_date without content_created_date")

if content_updated_date is not None and content_created_date is not None:
if content_updated_date < content_created_date:
raise UserError(
"content_updated_date cannot come before content_created_date"
)

did, rev, baseid = blueprint.index_driver.add(
form,
Expand All @@ -422,6 +437,9 @@ def post_index_record():
hashes=hashes,
baseid=baseid,
uploader=uploader,
description=description,
content_created_date=content_created_date,
content_updated_date=content_updated_date,
)

ret = {"did": did, "rev": rev, "baseid": baseid}
Expand Down Expand Up @@ -508,9 +526,15 @@ def put_index_record(record):
raise UserError(err)

rev = flask.request.args.get("rev")
json = flask.request.json
if "content_updated_date" in json and "content_created_date" in json:
if json["content_updated_date"] < json["content_created_date"]:
raise UserError(
"content_updated_date cannot come before content_created_date"
)

# authorize done in update
did, baseid, rev = blueprint.index_driver.update(record, rev, flask.request.json)
did, baseid, rev = blueprint.index_driver.update(record, rev, json)

ret = {"did": did, "baseid": baseid, "rev": rev}

Expand Down Expand Up @@ -553,6 +577,18 @@ def add_index_record_version(record):
metadata = flask.request.json.get("metadata")
urls_metadata = flask.request.json.get("urls_metadata")
version = flask.request.json.get("version")
description = flask.request.json.get("description")
content_created_date = flask.request.json.get("content_created_date")
content_updated_date = flask.request.json.get("content_updated_date")

if content_updated_date is None:
content_updated_date = content_created_date

if content_updated_date is not None and content_created_date is not None:
if content_updated_date < content_created_date:
raise UserError(
"content_updated_date cannot come before content_created_date"
)

# authorize done in add_version for both the old and new authz
did, baseid, rev = blueprint.index_driver.add_version(
Expand All @@ -568,6 +604,9 @@ def add_index_record_version(record):
urls_metadata=urls_metadata,
version=version,
hashes=hashes,
description=description,
content_created_date=content_created_date,
content_updated_date=content_updated_date,
)

ret = {"did": did, "baseid": baseid, "rev": rev}
Expand Down
6 changes: 6 additions & 0 deletions indexd/index/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ def add(
hashes=None,
baseid=None,
uploader=None,
description=None,
content_created_date=None,
content_updated_date=None,
):
"""
Creates record for given data.
Expand Down Expand Up @@ -100,6 +103,9 @@ def add_version(
acl=None,
authz=None,
hashes=None,
description=None,
content_created_date=None,
content_updated_date=None,
):
"""
Add a record version given did
Expand Down
69 changes: 68 additions & 1 deletion indexd/index/drivers/alchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ class IndexRecord(Base):
file_name = Column(String, index=True)
version = Column(String, index=True)
uploader = Column(String, index=True)
description = Column(String)
content_created_date = Column(DateTime)
content_updated_date = Column(DateTime)

urls = relationship(
"IndexRecordUrl", backref="index_record", cascade="all, delete-orphan"
Expand Down Expand Up @@ -120,6 +123,16 @@ def to_document_dict(self):
}
created_date = self.created_date.isoformat()
updated_date = self.updated_date.isoformat()
content_created_date = (
self.content_created_date.isoformat()
if self.content_created_date is not None
else ""
)
content_updated_date = (
self.content_updated_date.isoformat()
if self.content_created_date is not None
else ""
)

return {
"did": self.did,
Expand All @@ -138,6 +151,9 @@ def to_document_dict(self):
"form": self.form,
"created_date": created_date,
"updated_date": updated_date,
"description": self.description,
"content_created_date": content_created_date,
"content_updated_date": content_updated_date,
}


Expand Down Expand Up @@ -675,6 +691,9 @@ def add(
hashes=None,
baseid=None,
uploader=None,
description=None,
content_created_date=None,
content_updated_date=None,
):
"""
Creates a new record given size, urls, acl, authz, hashes, metadata,
Expand Down Expand Up @@ -733,6 +752,20 @@ def add(
IndexRecordMetadata(did=record.did, key=m_key, value=m_value)
for m_key, m_value in metadata.items()
]

record.description = description

if content_created_date is not None:
record.content_created_date = datetime.datetime.fromisoformat(
content_created_date
)
# Users cannot set content_updated_date without a content_created_date
record.content_updated_date = (
datetime.datetime.fromisoformat(content_updated_date)
if content_updated_date is not None
else record.content_created_date # Set updated to created if no updated is provided
)

session.merge(base_version)

try:
Expand Down Expand Up @@ -1137,7 +1170,15 @@ def update(self, did, rev, changing_fields):
"""
authz_err_msg = "Auth error when attempting to update a record. User must have '{}' access on '{}' for service 'indexd'."

composite_fields = ["urls", "acl", "authz", "metadata", "urls_metadata"]
composite_fields = [
"urls",
"acl",
"authz",
"metadata",
"urls_metadata",
"content_created_date",
"content_updated_date",
]

with self.session as session:
query = session.query(IndexRecord).filter(IndexRecord.did == did)
Expand Down Expand Up @@ -1209,6 +1250,26 @@ def update(self, did, rev, changing_fields):

create_urls_metadata(changing_fields["urls_metadata"], record, session)

if "content_created_date" in changing_fields:
record.content_created_date = datetime.datetime.fromisoformat(
changing_fields["content_created_date"]
)
if "content_updated_date" in changing_fields:
if record.content_created_date is None:
raise UserError(
"Cannot set content_updated_date on record that does not have a content_created_date"
)
if record.content_created_date > datetime.datetime.fromisoformat(
changing_fields["content_updated_date"]
):
raise UserError(
"Cannot set content_updated_date before the content_created_date"
)

record.content_updated_date = datetime.datetime.fromisoformat(
changing_fields["content_updated_date"]
)

for key, value in changing_fields.items():
if key not in composite_fields:
# No special logic needed for other updates.
Expand Down Expand Up @@ -1259,6 +1320,9 @@ def add_version(
acl=None,
authz=None,
hashes=None,
description=None,
content_created_date=None,
content_updated_date=None,
):
"""
Add a record version given did
Expand Down Expand Up @@ -1297,6 +1361,9 @@ def add_version(
record.size = size
record.file_name = file_name
record.version = version
record.description = description
record.content_created_date = content_created_date
record.content_updated_date = content_updated_date

record.urls = [IndexRecordUrl(did=record.did, url=url) for url in urls]

Expand Down
17 changes: 17 additions & 0 deletions indexd/index/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
"description": "optional version string of the object",
"type": "string",
},
"description": {
"description": "optional description string of the object",
"type": "string",
},
"uploader": {
"description": "optional uploader of the object",
"type": "string",
Expand All @@ -46,6 +50,16 @@
"type": "string",
"pattern": "^.*[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$",
},
"content_created_date": {
"description": "Timestamp of content creation. Refers to the underyling content, not the JSON object.",
"type": "string",
"format": "date-time",
},
"content_updated_date": {
"description": "Timestamp of content update, identical to created_time in systems that do not support updates. Refers to the underyling content, not the JSON object.",
"type": "string",
"format": "date-time",
},
"hashes": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -82,6 +96,9 @@
"uploader": {"type": ["string", "null"]},
"metadata": {"type": "object"},
"urls_metadata": {"type": "object"},
"description": {"type": ["string", "null"]},
"content_created_date": {"type": ["string", "null"], "format": "date-time"},
"content_updated_date": {"type": ["string", "null"], "format": "date-time"},
},
}

Expand Down
Loading

0 comments on commit 6cf4627

Please sign in to comment.