2022-12-26 00:32:57 +00:00
|
|
|
"""
|
|
|
|
Functions that perform read-write operations
|
|
|
|
"""
|
|
|
|
|
2022-12-10 10:34:05 +00:00
|
|
|
import json
|
|
|
|
from os import environ as env
|
2022-12-15 04:19:32 +00:00
|
|
|
from urllib.parse import quote_plus as url_encode
|
2022-12-10 10:34:05 +00:00
|
|
|
from pathlib import Path
|
|
|
|
|
2022-12-26 00:32:57 +00:00
|
|
|
from webfinger.models import JRD, Link
|
|
|
|
|
|
|
|
|
|
|
|
DictJRD = dict[str, str | list[str] | dict[str,str] | list[dict[str,str]]]
|
|
|
|
|
|
|
|
|
|
|
|
def get_jrd_as_dict(resource: str) -> DictJRD:
|
2022-12-15 04:19:32 +00:00
|
|
|
"""
|
2022-12-26 00:32:57 +00:00
|
|
|
Obtain a JSON Resource Descriptor (JRD) as a dictionary
|
2022-12-15 04:19:32 +00:00
|
|
|
|
|
|
|
A JRD is a JSON object containing the following:
|
|
|
|
- subject (string value; SHOULD be present)
|
|
|
|
- aliases (array of string values; OPTIONAL)
|
|
|
|
- properties (object containing key-value pairs as strings; OPTIONAL)
|
|
|
|
- links (array of objects containing link relation information; OPTIONAL)
|
|
|
|
|
|
|
|
Parameters:
|
|
|
|
resource (str): The URI of the resouce
|
2022-12-26 00:32:57 +00:00
|
|
|
|
2022-12-15 04:19:32 +00:00
|
|
|
Returns:
|
2022-12-26 00:32:57 +00:00
|
|
|
jrd (dict): Parsed JRD dictionary
|
2022-12-15 04:19:32 +00:00
|
|
|
|
|
|
|
Raises:
|
|
|
|
FileNotFoundError: No JRD file exists in the resource directory
|
|
|
|
OSError: A file may exist, but it is not readable
|
|
|
|
json.JSONDecodeError: A file exists, but does not contain a valid JSON object
|
|
|
|
"""
|
2022-12-10 10:34:05 +00:00
|
|
|
# Get a filename for the resource document.
|
2022-12-26 00:32:57 +00:00
|
|
|
directory = env.get("RESOURCE_DIR") or "resource"
|
2022-12-15 04:19:32 +00:00
|
|
|
filename = resource
|
2022-12-26 00:32:57 +00:00
|
|
|
path = f"{directory}/{filename}.jrd"
|
2022-12-15 04:19:32 +00:00
|
|
|
|
|
|
|
# If we can't get a file, try percent-encoding
|
|
|
|
if not Path(path).is_file():
|
|
|
|
filename = url_encode(resource)
|
2022-12-26 00:32:57 +00:00
|
|
|
path = f"{directory}/{filename}.jrd"
|
2022-12-15 07:42:48 +00:00
|
|
|
|
|
|
|
# Try plain JSON
|
|
|
|
if not Path(path).is_file():
|
|
|
|
filename = resource
|
2022-12-26 00:32:57 +00:00
|
|
|
path = f"{directory}/{filename}.json"
|
2022-12-15 07:42:48 +00:00
|
|
|
|
|
|
|
# Try plain JSON and percent-encoding
|
|
|
|
if not Path(path).is_file():
|
|
|
|
filename = resource
|
2022-12-26 00:32:57 +00:00
|
|
|
path = f"{directory}/{filename}.json"
|
2022-12-10 10:34:05 +00:00
|
|
|
|
|
|
|
# Open the file and load the JSON as a dictionary.
|
2022-12-26 00:32:57 +00:00
|
|
|
# This may fail and raise an exception.
|
|
|
|
with open(path, mode="r", encoding="utf-8") as file:
|
|
|
|
jrd: DictJRD = json.loads(file.read())
|
|
|
|
|
|
|
|
return {k: v for k, v in jrd.items() if v} # remove null values
|
|
|
|
|
|
|
|
|
|
|
|
def get_jrd(resource: str) -> JRD:
|
|
|
|
"""
|
|
|
|
Obtain a JSON Resource Descriptor (JRD) as a Pydantic model
|
|
|
|
|
|
|
|
A JRD is a JSON object containing the following:
|
|
|
|
- subject (string value; SHOULD be present)
|
|
|
|
- aliases (array of string values; OPTIONAL)
|
|
|
|
- properties (object containing key-value pairs as strings; OPTIONAL)
|
|
|
|
- links (array of objects containing link relation information; OPTIONAL)
|
|
|
|
|
|
|
|
Parameters:
|
|
|
|
resource (str): The URI of the resouce
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
jrd (JRD): Parsed and valid JRD model
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
FileNotFoundError: No JRD file exists in the resource directory
|
|
|
|
OSError: A file may exist, but it is not readable
|
|
|
|
json.JSONDecodeError: A file exists, but does not contain a valid JSON object
|
|
|
|
pydantic.ValidationError: A file exists and was parsed, but some properties failed validation
|
|
|
|
"""
|
2022-12-10 10:34:05 +00:00
|
|
|
|
2022-12-26 00:32:57 +00:00
|
|
|
jrd = get_jrd_as_dict(resource)
|
|
|
|
return JRD(
|
|
|
|
subject = jrd.get('subject') or resource,
|
|
|
|
aliases = jrd.get('aliases'),
|
|
|
|
properties = jrd.get('properties'),
|
|
|
|
links = [
|
|
|
|
Link(
|
|
|
|
rel = link.get('rel'),
|
|
|
|
type = link.get('type'),
|
|
|
|
href = link.get('href'),
|
|
|
|
titles = link.get('titles'),
|
|
|
|
properties = link.get('properties'),
|
|
|
|
)
|
|
|
|
for link in jrd.get('links', [])
|
|
|
|
],
|
|
|
|
)
|