oldap-tools 0.1.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oldap_tools/__init__.py +0 -0
- oldap_tools/__main__.py +4 -0
- oldap_tools/cli.py +114 -0
- oldap_tools/config.py +11 -0
- oldap_tools/dump_list.py +43 -0
- oldap_tools/dump_project.py +127 -0
- oldap_tools/load_list.py +39 -0
- oldap_tools/load_project.py +110 -0
- oldap_tools/logging.py +13 -0
- oldap_tools-0.1.4.dist-info/METADATA +122 -0
- oldap_tools-0.1.4.dist-info/RECORD +13 -0
- oldap_tools-0.1.4.dist-info/WHEEL +4 -0
- oldap_tools-0.1.4.dist-info/entry_points.txt +3 -0
oldap_tools/__init__.py
ADDED
|
File without changes
|
oldap_tools/__main__.py
ADDED
oldap_tools/cli.py
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
from importlib.metadata import version
|
|
5
|
+
|
|
6
|
+
from oldap_tools.dump_list import dump_list
|
|
7
|
+
from oldap_tools.config import AppConfig
|
|
8
|
+
from oldap_tools.dump_project import dump_project
|
|
9
|
+
from oldap_tools.load_list import load_list
|
|
10
|
+
from oldap_tools.load_project import load_project
|
|
11
|
+
|
|
12
|
+
from oldap_tools.logging import setup_logging
|
|
13
|
+
|
|
14
|
+
app = typer.Typer(
|
|
15
|
+
no_args_is_help=True,
|
|
16
|
+
help="OLDAP command line tools"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
@app.callback()
|
|
20
|
+
def app_callback(ctx: typer.Context,
|
|
21
|
+
verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose (debug) logging"),
|
|
22
|
+
graphdb_base: str = typer.Option("http://localhost:7200", "--graphdb", "-g", help="GraphDB base URL"),
|
|
23
|
+
repo: str = typer.Option("oldap", "--repo", "-r", help="GraphDB repository"),
|
|
24
|
+
user: str = typer.Option(..., "--user", "-u", help="OLDAP user"),
|
|
25
|
+
password: str = typer.Option(..., "--password", "-p", help="OLDAP password", hide_input=True),
|
|
26
|
+
graphdb_user: str = typer.Option(None, "--graphdb_user", envvar="GRAPHDB_USER", help="GraphDB user"),
|
|
27
|
+
graphdb_password: str = typer.Option(None, "--graphdb_password", envvar="GRAPHDB_PASSWORD", help="GraphDB password", hide_input=True)
|
|
28
|
+
):
|
|
29
|
+
setup_logging(verbose)
|
|
30
|
+
ctx.obj = AppConfig(
|
|
31
|
+
graphdb_base=graphdb_base,
|
|
32
|
+
repo=repo,
|
|
33
|
+
user=user,
|
|
34
|
+
password=password,
|
|
35
|
+
graphdb_user=graphdb_user,
|
|
36
|
+
graphdb_password=graphdb_password
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
@app.command()
|
|
40
|
+
def show_version():
|
|
41
|
+
"""Show version information."""
|
|
42
|
+
typer.echo(version("oldap-tools"))
|
|
43
|
+
|
|
44
|
+
project = typer.Typer(help="Project-related commands")
|
|
45
|
+
app.add_typer(project, name="project")
|
|
46
|
+
|
|
47
|
+
@project.command("dump")
|
|
48
|
+
def project_dump(
|
|
49
|
+
ctx: typer.Context,
|
|
50
|
+
project_id: str = typer.Argument(..., help="Project ID (e.g. swissbritnet, hyha, ...)"),
|
|
51
|
+
out: Path = typer.Option(Path("<project>.trig.gz"), "--out", "-o", help="Output dump file"),
|
|
52
|
+
include_data: bool = typer.Option(True, "--data/--no-data", help="Include '<project>:data' graph"),
|
|
53
|
+
):
|
|
54
|
+
"""Export project data."""
|
|
55
|
+
if out == Path("<project>.trig.gz"):
|
|
56
|
+
out = Path(project_id).with_suffix(".trig.gz")
|
|
57
|
+
typer.echo(f"Exporting '{project_id}' data to {out}")
|
|
58
|
+
cfg = ctx.obj
|
|
59
|
+
dump_project(project_id=project_id,
|
|
60
|
+
graphdb_base=cfg.graphdb_base,
|
|
61
|
+
repo=cfg.repo,
|
|
62
|
+
out=out,
|
|
63
|
+
include_data=include_data,
|
|
64
|
+
user=cfg.user,
|
|
65
|
+
password=cfg.password,
|
|
66
|
+
graphdb_user=cfg.graphdb_user,
|
|
67
|
+
graphdb_password=cfg.graphdb_password)
|
|
68
|
+
|
|
69
|
+
@project.command("load")
|
|
70
|
+
def project_load(ctx: typer.Context,
|
|
71
|
+
inf: Path = typer.Option(Path("dump.trig.gz"), "--inf", "-i", help="Input file for load")):
|
|
72
|
+
cfg = ctx.obj
|
|
73
|
+
load_project(graphdb_base=cfg.graphdb_base,
|
|
74
|
+
repo=cfg.repo,
|
|
75
|
+
inf=inf,
|
|
76
|
+
user=cfg.user,
|
|
77
|
+
password=cfg.password,
|
|
78
|
+
graphdb_user=cfg.graphdb_user,
|
|
79
|
+
graphdb_password=cfg.graphdb_password)
|
|
80
|
+
|
|
81
|
+
lists = typer.Typer(help="List-related commands")
|
|
82
|
+
app.add_typer(lists, name="lists")
|
|
83
|
+
|
|
84
|
+
@lists.command("dump", help="Dump all list data to a YAML file.")
|
|
85
|
+
def list_dump(ctx: typer.Context,
|
|
86
|
+
project_id: str = typer.Argument(..., help="Project ID (e.g. swissbritnet, hyha, ...)"),
|
|
87
|
+
list_id: str = typer.Argument(..., help="List ID (e.g. 'CreativeCommons', 'BuildingCategories', ...)"),
|
|
88
|
+
out: Path = typer.Option(Path("dump.trig"), "--out", "-o", help="Output dump file")):
|
|
89
|
+
cfg = ctx.obj
|
|
90
|
+
dump_list(project_id=project_id,
|
|
91
|
+
list_id=list_id,
|
|
92
|
+
graphdb_base=cfg.graphdb_base,
|
|
93
|
+
repo=cfg.repo,
|
|
94
|
+
filepath=out,
|
|
95
|
+
user=cfg.user,
|
|
96
|
+
password=cfg.password,
|
|
97
|
+
graphdb_user = cfg.graphdb_user,
|
|
98
|
+
graphdb_password = cfg.graphdb_password
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
@lists.command("load", help="Load project data from a JSON/YAML file.")
|
|
102
|
+
def list_load(ctx: typer.Context,
|
|
103
|
+
project_id: str = typer.Argument(..., help="Project ID (e.g. swissbritnet, hyha, ...)"),
|
|
104
|
+
inf: Path = typer.Option(Path("dump.trig.gz"), "--inf", "-i", help="Input file for load")):
|
|
105
|
+
cfg = ctx.obj
|
|
106
|
+
load_list(project_id=project_id,
|
|
107
|
+
graphdb_base=cfg.graphdb_base,
|
|
108
|
+
repo=cfg.repo,
|
|
109
|
+
filepath=inf,
|
|
110
|
+
user=cfg.user,
|
|
111
|
+
password=cfg.password)
|
|
112
|
+
|
|
113
|
+
def main():
|
|
114
|
+
app()
|
oldap_tools/config.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# src/oldap_tools/config.py
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
|
|
4
|
+
@dataclass(frozen=True)
|
|
5
|
+
class AppConfig:
|
|
6
|
+
graphdb_base: str
|
|
7
|
+
repo: str
|
|
8
|
+
user: str | None = None
|
|
9
|
+
password: str | None = None
|
|
10
|
+
graphdb_user: str | None = None
|
|
11
|
+
graphdb_password: str | None = None
|
oldap_tools/dump_list.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import typer
|
|
5
|
+
from oldaplib.src.connection import Connection
|
|
6
|
+
from oldaplib.src.helpers.oldaperror import OldapError
|
|
7
|
+
from oldaplib.src.oldaplist_helpers import ListFormat, dump_list_to
|
|
8
|
+
from oldaplib.src.project import Project
|
|
9
|
+
|
|
10
|
+
log = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
def dump_list(project_id: str,
|
|
13
|
+
list_id: str,
|
|
14
|
+
graphdb_base: str,
|
|
15
|
+
repo: str,
|
|
16
|
+
filepath: Path,
|
|
17
|
+
user: str,
|
|
18
|
+
password: str,
|
|
19
|
+
graphdb_user: str | None = None,
|
|
20
|
+
graphdb_password: str | None = None
|
|
21
|
+
):
|
|
22
|
+
try:
|
|
23
|
+
con = Connection(server=graphdb_base,
|
|
24
|
+
repo=repo,
|
|
25
|
+
dbuser=graphdb_user,
|
|
26
|
+
dbpassword=graphdb_password,
|
|
27
|
+
userId=user,
|
|
28
|
+
credentials=password,
|
|
29
|
+
context_name="DEFAULT")
|
|
30
|
+
yamlfile = dump_list_to(con=con,
|
|
31
|
+
project=project_id,
|
|
32
|
+
oldapListId=list_id,
|
|
33
|
+
listformat=ListFormat.YAML,
|
|
34
|
+
ignore_cache=False)
|
|
35
|
+
except OldapError as error:
|
|
36
|
+
log.error(f"ERROR: Failed to connect to GraphDB database at '{graphdb_base}': {error}")
|
|
37
|
+
raise typer.Exit(code=1)
|
|
38
|
+
except FileNotFoundError as error:
|
|
39
|
+
log.error(f"ERROR: File {filepath} not found': {error}")
|
|
40
|
+
raise typer.Exit(code=1)
|
|
41
|
+
|
|
42
|
+
with open(filepath, "w", encoding="utf-8") as f:
|
|
43
|
+
f.write(yamlfile)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import gzip
|
|
2
|
+
import json
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import requests
|
|
7
|
+
import typer
|
|
8
|
+
import logging
|
|
9
|
+
|
|
10
|
+
from oldaplib.src.connection import Connection
|
|
11
|
+
from oldaplib.src.helpers.context import Context
|
|
12
|
+
from oldaplib.src.helpers.oldaperror import OldapError
|
|
13
|
+
from oldaplib.src.helpers.serializer import serializer
|
|
14
|
+
from oldaplib.src.role import Role
|
|
15
|
+
from oldaplib.src.project import Project
|
|
16
|
+
from oldaplib.src.user import User
|
|
17
|
+
from oldaplib.src.xsd.xsd_qname import Xsd_QName
|
|
18
|
+
from rdflib import Dataset
|
|
19
|
+
|
|
20
|
+
log = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
def export_graphs_as_trig(
|
|
23
|
+
graphdb_base: str, # e.g. "http://localhost:7200"
|
|
24
|
+
repo: str, # e.g. "oldap"
|
|
25
|
+
graph_iris: list[str], # the 4 graphs you want
|
|
26
|
+
auth: tuple[str, str] | None = None,
|
|
27
|
+
timeout: int = 120,
|
|
28
|
+
) -> str:
|
|
29
|
+
ds = Dataset()
|
|
30
|
+
|
|
31
|
+
for g in graph_iris:
|
|
32
|
+
# RDF4J "statements" endpoint; context must be given as <IRI>
|
|
33
|
+
url = f"{graphdb_base.rstrip('/')}/repositories/{repo}/statements"
|
|
34
|
+
params = {"context": f"<{g}>"}
|
|
35
|
+
r = requests.get(
|
|
36
|
+
url,
|
|
37
|
+
params=params,
|
|
38
|
+
headers={"Accept": "application/n-quads"},
|
|
39
|
+
auth=auth,
|
|
40
|
+
timeout=timeout,
|
|
41
|
+
)
|
|
42
|
+
if r.status_code != 200:
|
|
43
|
+
log.error(f"ERROR: Request to '{url}' failed with status code {r.status_code}")
|
|
44
|
+
raise typer.Exit(code=1)
|
|
45
|
+
|
|
46
|
+
# N-Quads keeps the graph/context in each statement -> perfect for Dataset
|
|
47
|
+
ds.parse(data=r.text, format="nquads")
|
|
48
|
+
|
|
49
|
+
trig = ds.serialize(format="trig")
|
|
50
|
+
return trig.decode("utf-8") if isinstance(trig, bytes) else trig
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def dump_project(project_id: str,
|
|
54
|
+
graphdb_base: str,
|
|
55
|
+
repo: str,
|
|
56
|
+
out: Path,
|
|
57
|
+
include_data: bool,
|
|
58
|
+
user: str,
|
|
59
|
+
password: str,
|
|
60
|
+
graphdb_user: str | None = None,
|
|
61
|
+
graphdb_password: str | None = None):
|
|
62
|
+
try:
|
|
63
|
+
con = Connection(server=graphdb_base,
|
|
64
|
+
repo = repo,
|
|
65
|
+
dbuser=graphdb_user,
|
|
66
|
+
dbpassword=graphdb_password,
|
|
67
|
+
userId=user,
|
|
68
|
+
credentials=password)
|
|
69
|
+
except OldapError as e:
|
|
70
|
+
log.error(f"ERROR: Failed to connect to GraphDB database at '{graphdb_base}': {e}")
|
|
71
|
+
raise typer.Exit(code=1)
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
project = Project.read(con=con, projectIri_SName=project_id)
|
|
75
|
+
except OldapError as e:
|
|
76
|
+
log.error(f"ERROR: Failed to connect to read project '{project_id}': {e}")
|
|
77
|
+
raise typer.Exit(code=1)
|
|
78
|
+
|
|
79
|
+
trig = "################################################################################\n"
|
|
80
|
+
trig += f"# Project: {project.projectShortName}\n"
|
|
81
|
+
trig += f"# Date: {datetime.now().isoformat()}\n"
|
|
82
|
+
trig += "################################################################################\n"
|
|
83
|
+
trig += "\n#\n# User info\n#\n"
|
|
84
|
+
userIris = User.search(con=con, inProject=project.projectIri)
|
|
85
|
+
for userIri in userIris:
|
|
86
|
+
user = User.read(con=con, userId=str(userIri))
|
|
87
|
+
user_json = json.dumps(user, default=serializer.encoder_default)
|
|
88
|
+
trig += "#>> " + user_json + "\n"
|
|
89
|
+
trig += "#<<\n\n"
|
|
90
|
+
|
|
91
|
+
context = Context(name=con.context_name)
|
|
92
|
+
trig += context.turtle_context
|
|
93
|
+
trig += "#\n# Load the oldap:admin part\n#\n"
|
|
94
|
+
trig += "oldap:admin {"
|
|
95
|
+
|
|
96
|
+
trig += "\n#\n# Project info\n#\n"
|
|
97
|
+
trig += project.trig_to_str(created=project.created, modified=project.modified, indent=1)
|
|
98
|
+
trig += " .\n\n"
|
|
99
|
+
|
|
100
|
+
trig += "\n#\n# Roles info\n#\n"
|
|
101
|
+
roleQNames = Role.search(con=con, definedByProject=project.projectIri)
|
|
102
|
+
for roleQName in roleQNames:
|
|
103
|
+
role = Role.read(con=con, qname=roleQName)
|
|
104
|
+
trig += role.trig_to_str(created=role.created, modified=role.modified, indent=1)
|
|
105
|
+
trig += " .\n\n"
|
|
106
|
+
|
|
107
|
+
trig += "\n}\n\n"
|
|
108
|
+
|
|
109
|
+
project_graphs = [
|
|
110
|
+
str(context.qname2iri(Xsd_QName(project.projectShortName, "shacl"))),
|
|
111
|
+
str(context.qname2iri(Xsd_QName(project.projectShortName, "onto"))),
|
|
112
|
+
str(context.qname2iri(Xsd_QName(project.projectShortName, "lists"))),
|
|
113
|
+
]
|
|
114
|
+
if include_data:
|
|
115
|
+
project_graphs.append(str(context.qname2iri(Xsd_QName(project.projectShortName, "data"))))
|
|
116
|
+
|
|
117
|
+
trig += export_graphs_as_trig(
|
|
118
|
+
graphdb_base="http://localhost:7200",
|
|
119
|
+
repo="oldap",
|
|
120
|
+
graph_iris=project_graphs,
|
|
121
|
+
auth=None, # or None
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
with gzip.open(out, "wt", encoding="utf-8", newline="") as f:
|
|
125
|
+
f.write(trig)
|
|
126
|
+
|
|
127
|
+
|
oldap_tools/load_list.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import typer
|
|
5
|
+
from oldaplib.src.connection import Connection
|
|
6
|
+
from oldaplib.src.helpers.oldaperror import OldapError
|
|
7
|
+
from oldaplib.src.oldaplist_helpers import load_list_from_yaml
|
|
8
|
+
from oldaplib.src.project import Project
|
|
9
|
+
|
|
10
|
+
log = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
def load_list(project_id: str,
|
|
13
|
+
graphdb_base: str,
|
|
14
|
+
repo: str,
|
|
15
|
+
filepath: Path,
|
|
16
|
+
user: str,
|
|
17
|
+
password: str,
|
|
18
|
+
graphdb_user: str | None = None,
|
|
19
|
+
graphdb_password: str | None = None):
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
connection = Connection(server=graphdb_base,
|
|
23
|
+
repo=repo,
|
|
24
|
+
dbuser=graphdb_user,
|
|
25
|
+
dbpassword=graphdb_password,
|
|
26
|
+
userId=user,
|
|
27
|
+
credentials=password,
|
|
28
|
+
context_name="DEFAULT")
|
|
29
|
+
project = Project.read(connection, project_id)
|
|
30
|
+
listnodes = load_list_from_yaml(con=connection,
|
|
31
|
+
project=project_id,
|
|
32
|
+
filepath=filepath)
|
|
33
|
+
except OldapError as error:
|
|
34
|
+
log.error(f"ERROR: Failed to connect to GraphDB database at '{graphdb_base}': {error}")
|
|
35
|
+
raise typer.Exit(code=1)
|
|
36
|
+
except FileNotFoundError as error:
|
|
37
|
+
log.error(f"ERROR: File {filepath} not found': {error}")
|
|
38
|
+
raise typer.Exit(code=1)
|
|
39
|
+
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import gzip
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import requests
|
|
7
|
+
import typer
|
|
8
|
+
from oldaplib.src.cachesingleton import CacheSingletonRedis
|
|
9
|
+
from oldaplib.src.connection import Connection
|
|
10
|
+
from oldaplib.src.helpers.oldaperror import OldapErrorAlreadyExists, OldapError, OldapErrorNotFound
|
|
11
|
+
from oldaplib.src.helpers.serializer import serializer
|
|
12
|
+
from oldaplib.src.user import User
|
|
13
|
+
|
|
14
|
+
log = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
def import_trig(
|
|
17
|
+
graphdb_base: str,
|
|
18
|
+
repo: str,
|
|
19
|
+
trig_str: str,
|
|
20
|
+
auth: tuple[str, str] | None = None,
|
|
21
|
+
timeout: int = 120,
|
|
22
|
+
):
|
|
23
|
+
url = f"{graphdb_base.rstrip('/')}/repositories/{repo}/statements"
|
|
24
|
+
r = requests.post(
|
|
25
|
+
url,
|
|
26
|
+
data=trig_str.encode("utf-8"),
|
|
27
|
+
headers={"Content-Type": "application/trig"},
|
|
28
|
+
auth=auth,
|
|
29
|
+
timeout=timeout,
|
|
30
|
+
)
|
|
31
|
+
if r.status_code != 200:
|
|
32
|
+
log.error(f"ERROR: Request to '{url}' failed with status code {r.status_code}")
|
|
33
|
+
raise typer.Exit(code=1)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def import_trig_gz(
|
|
37
|
+
graphdb_base: str,
|
|
38
|
+
repo: str,
|
|
39
|
+
trig_gz: bytes,
|
|
40
|
+
auth: tuple[str, str] | None = None,
|
|
41
|
+
timeout: int = 120,
|
|
42
|
+
):
|
|
43
|
+
url = f"{graphdb_base.rstrip('/')}/repositories/{repo}/statements"
|
|
44
|
+
r = requests.post(
|
|
45
|
+
url,
|
|
46
|
+
data=trig_gz,
|
|
47
|
+
headers={
|
|
48
|
+
"Content-Type": "application/trig",
|
|
49
|
+
"Content-Encoding": "gzip",
|
|
50
|
+
},
|
|
51
|
+
auth=auth,
|
|
52
|
+
timeout=timeout,
|
|
53
|
+
)
|
|
54
|
+
if r.status_code < 200 or r.status_code >= 300:
|
|
55
|
+
log.error(f"ERROR: Request to '{url}' failed with status code {r.status_code}")
|
|
56
|
+
raise typer.Exit(code=1)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def load_project(graphdb_base: str,
|
|
60
|
+
repo: str,
|
|
61
|
+
inf: Path,
|
|
62
|
+
user: str,
|
|
63
|
+
password: str,
|
|
64
|
+
graphdb_user: str | None = None,
|
|
65
|
+
graphdb_password: str | None = None) -> None:
|
|
66
|
+
cache = CacheSingletonRedis()
|
|
67
|
+
cache.clear()
|
|
68
|
+
|
|
69
|
+
with open(inf, "rb") as f:
|
|
70
|
+
import_trig_gz(graphdb_base=graphdb_base,
|
|
71
|
+
repo=repo,
|
|
72
|
+
auth=(graphdb_user, graphdb_password) if graphdb_user and graphdb_password else None,
|
|
73
|
+
trig_gz=f.read())
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
con = Connection(server=graphdb_base,
|
|
77
|
+
repo=repo,
|
|
78
|
+
dbuser=graphdb_user,
|
|
79
|
+
dbpassword=graphdb_password,
|
|
80
|
+
userId=user,
|
|
81
|
+
credentials=password)
|
|
82
|
+
except OldapError as e:
|
|
83
|
+
log.error(f"ERROR: Failed to connect to GraphDB database at '{graphdb_base}': {e}")
|
|
84
|
+
raise typer.Exit(code=1)
|
|
85
|
+
|
|
86
|
+
with gzip.open(inf, "rt", encoding="utf-8") as f:
|
|
87
|
+
for line in f:
|
|
88
|
+
if line.startswith('#>>'):
|
|
89
|
+
user_json = line[3:].strip()
|
|
90
|
+
user = json.loads(user_json, object_hook=serializer.make_decoder_hook(connection=con))
|
|
91
|
+
try:
|
|
92
|
+
existing_user = User.read(con=con, userId=user.userId)
|
|
93
|
+
except OldapErrorNotFound:
|
|
94
|
+
# user does not exist -> create it
|
|
95
|
+
user.create(keep_dates=True)
|
|
96
|
+
log.info(f"Created user {user.userId}")
|
|
97
|
+
else:
|
|
98
|
+
# user exists -> update it
|
|
99
|
+
if user.hasRole != existing_user.hasRole or user.inProject != existing_user.inProject:
|
|
100
|
+
existing_user.delete()
|
|
101
|
+
user.create(keep_dates=True)
|
|
102
|
+
log.info(f"Updated (replaced) user {user.userId}")
|
|
103
|
+
pass
|
|
104
|
+
if line.startswith('#<<'):
|
|
105
|
+
break
|
|
106
|
+
cache = CacheSingletonRedis()
|
|
107
|
+
cache.clear()
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
oldap_tools/logging.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
def setup_logging(verbose: bool = False) -> None:
|
|
5
|
+
level = logging.DEBUG if verbose else logging.INFO
|
|
6
|
+
|
|
7
|
+
logging.basicConfig(
|
|
8
|
+
level=level,
|
|
9
|
+
format="%(levelname)s: %(message)s",
|
|
10
|
+
handlers=[
|
|
11
|
+
logging.StreamHandler(sys.stderr)
|
|
12
|
+
],
|
|
13
|
+
)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: oldap-tools
|
|
3
|
+
Version: 0.1.4
|
|
4
|
+
Summary: CLI tools for OLDAP
|
|
5
|
+
License: GPL-3.0-only
|
|
6
|
+
Author: Lukas Rosenthaler
|
|
7
|
+
Author-email: lukas.rosenthaler@unibas.ch
|
|
8
|
+
Requires-Python: >=3.11,<4.0
|
|
9
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Requires-Dist: oldaplib (>=0.4.1,<0.5.0)
|
|
14
|
+
Requires-Dist: rdflib (>=7.5.0,<8.0.0)
|
|
15
|
+
Requires-Dist: typer (>=0.20.0,<0.21.0)
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
[](https://badge.fury.io/py/oldap-tools)
|
|
19
|
+
[](https://github.com/OMAS-IIIF/oldap-tools/releases)
|
|
20
|
+
# OLDAP tools
|
|
21
|
+
|
|
22
|
+
OLDAP tools is a CLI tool for managing parts of the OLDAP framework. It allows to
|
|
23
|
+
|
|
24
|
+
- dump all the data of a given project to a gzipped TriG file
|
|
25
|
+
- load a project from a gzipped TriG file created by oldap-tools
|
|
26
|
+
- load a hierarchical list from a YAML file
|
|
27
|
+
- dump a hierarchical list to a YAML file
|
|
28
|
+
|
|
29
|
+
# Installation
|
|
30
|
+
|
|
31
|
+
The installation is done using pip: `pip install oldap-tools`
|
|
32
|
+
|
|
33
|
+
# Usage
|
|
34
|
+
|
|
35
|
+
The CLI tool provides the following commands:
|
|
36
|
+
|
|
37
|
+
- `oldap-tools project dump`: Dump all the data of a given project to a gzipped TriG file
|
|
38
|
+
- `oldap-tools project load`: Load a project from a gzipped TriG file created by oldap-tools
|
|
39
|
+
- `oldap-tools list dump`: Dump a hierarchical list to a YAML file
|
|
40
|
+
- `oldap-tools list load`: Load a hierarchical list from a YAML file
|
|
41
|
+
|
|
42
|
+
# Common options
|
|
43
|
+
|
|
44
|
+
- `--graphdb`, `-g`: URL of the GraphDB server (default: "http://localhost:7200")
|
|
45
|
+
- `--repo`, `-r`: Name of the repository (default: "oldap")
|
|
46
|
+
- `--user`, `-u`: OLDAP user (*required*) which performs the operations
|
|
47
|
+
- `--password` `-p`: OLDAP password (*required*)
|
|
48
|
+
- `--graphdb_user`: GraphDB user (default: None). Not needed if GraphDB runs without athentification.
|
|
49
|
+
- `--graphdb_password`: GraphDB password (default: None). Not needed if GraphDB runs without athentification.
|
|
50
|
+
- `--verbose`, `-v`: Print more information
|
|
51
|
+
|
|
52
|
+
# Command
|
|
53
|
+
|
|
54
|
+
## Project dump
|
|
55
|
+
|
|
56
|
+
This command dumps all the data of a given project to a gzipped TriG file. It includes user information
|
|
57
|
+
of all users associated with the project. The command has the following syntax (in addition to the common options):
|
|
58
|
+
|
|
59
|
+
```oldap-tools [common_options] [graphdb-options] project dump [-out <filename>] [--data | --no-data] [-verbose] <project_id>```
|
|
60
|
+
|
|
61
|
+
The graphdb options see above. The other options are defined as follows:
|
|
62
|
+
|
|
63
|
+
- `-out <filename>`: Name of the output file (default: "<project_id>.trig.gz")
|
|
64
|
+
- `--data | --no-data`: Include or exclude the data of the project (default: include)
|
|
65
|
+
- `-verbose`: Print more information
|
|
66
|
+
- `<project_id>`: Project identifier (project shortname)
|
|
67
|
+
|
|
68
|
+
The file is basically a dump of the project specific named graphs of the GraphDB repository.
|
|
69
|
+
This are the following graphs:
|
|
70
|
+
|
|
71
|
+
- `<project_id>:shacl`: Contains all the SHACL shapes of the project
|
|
72
|
+
- `<project_id>:onto`: Contains all the OWL ontology information of the project
|
|
73
|
+
- `<project_id>:lists`: Contains all the hierarchical lists of the project
|
|
74
|
+
- `<project_id>:data`: Contains all the resources (instances) of the project
|
|
75
|
+
|
|
76
|
+
The user information is stored as special comment in the TriG file and is interpreted by oldap-tools project load.
|
|
77
|
+
|
|
78
|
+
## Project load
|
|
79
|
+
|
|
80
|
+
This command loads a project from a gzipped TriG file created by oldap-tools. It has the following syntax
|
|
81
|
+
(in addition to the common options):
|
|
82
|
+
|
|
83
|
+
```oldap-tools [common_options] [graphdb-options] project load --i <filename>```
|
|
84
|
+
|
|
85
|
+
The options are as follows:
|
|
86
|
+
|
|
87
|
+
- `--inf`, `-i`: Name of the input file (required)
|
|
88
|
+
- `-verbose`: Print more information
|
|
89
|
+
|
|
90
|
+
If a user does not exist, then the user is created. If the User is already existing, then the user is replaced.
|
|
91
|
+
|
|
92
|
+
*NOTE: This will change in the future in order to only update project specific permissions to the existing user.*
|
|
93
|
+
|
|
94
|
+
## List dump
|
|
95
|
+
|
|
96
|
+
This command dumps a hierarchical list to a YAML file. This file can be edited to add/remove or change list items.
|
|
97
|
+
The command has the following syntax (in addition to the common options):
|
|
98
|
+
|
|
99
|
+
```oldap-tools [common_options] list dump [-out <filename>] <project_id> <list_id>```
|
|
100
|
+
|
|
101
|
+
This command generates a YAML file which can be edited and contains the list and all it nodes
|
|
102
|
+
|
|
103
|
+
The options are as follows:
|
|
104
|
+
|
|
105
|
+
- `-out `, `-o`: Output file
|
|
106
|
+
- `<project_id>`: Project identifier (project shortname)
|
|
107
|
+
- `<list_id>`: List identifier
|
|
108
|
+
|
|
109
|
+
## List load
|
|
110
|
+
|
|
111
|
+
This command loads a hierarchical list from a YAML file into the given project. The command has the following syntax
|
|
112
|
+
(in addition to the common options):
|
|
113
|
+
|
|
114
|
+
```oldap-tools [common_options] list load --inf <filename> <project_id>```
|
|
115
|
+
|
|
116
|
+
The options are as follows:
|
|
117
|
+
|
|
118
|
+
- `--inf`, `-i`: Name of the input file (required)
|
|
119
|
+
- `<project_id>`: Project identifier (project shortname)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
oldap_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
oldap_tools/__main__.py,sha256=0g3iknXOS9gZUcpL_trgAcuCJnZZKjdsT_xt61WOVb4,60
|
|
3
|
+
oldap_tools/cli.py,sha256=R2QR1sJ9eX3TOjkoGOUER31aaTLBVeJfL73md2Bsz-g,4599
|
|
4
|
+
oldap_tools/config.py,sha256=_VrFlBZG5EBeoA5HyCxxMuSM8qRPJWUN0QILOrYjKMU,275
|
|
5
|
+
oldap_tools/dump_list.py,sha256=kHW-u57Pgso0cKl2R59KQLBY9J8abpRIDtX8iS6rRgs,1577
|
|
6
|
+
oldap_tools/dump_project.py,sha256=0GaIVLB0nURiPJVl5_y00y3E6E0XRINFY2qWZnIpSQ0,4535
|
|
7
|
+
oldap_tools/load_list.py,sha256=i4npHMRoZuPXyizAeab5qjzlIyvMEaFGiuJq3P-7xxQ,1472
|
|
8
|
+
oldap_tools/load_project.py,sha256=KLfGHzIXAH2fwtTyzkmC7uozxmCs2geQp-XjBbGQXEo,3661
|
|
9
|
+
oldap_tools/logging.py,sha256=qxBtN_HcUMYeSAHZVQ1YiWd5pgB-beBwEUSOv5f_KvM,305
|
|
10
|
+
oldap_tools-0.1.4.dist-info/METADATA,sha256=zdYmoBWIjikFcH6ABZBidGRTmBaSYUlUjaKREkwf1Is,4891
|
|
11
|
+
oldap_tools-0.1.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
12
|
+
oldap_tools-0.1.4.dist-info/entry_points.txt,sha256=3UTWo7Z79A2m4rmTMnBeQZI5BXT19VJSPIdu7pWMp2I,52
|
|
13
|
+
oldap_tools-0.1.4.dist-info/RECORD,,
|