Skip to content

Commit 1f38ea2

Browse files
committed
Add helper management command to fix user access permissions to table objects. Was used when manuel import of data to the OEP, as data was to large for upload
1 parent a8bff0c commit 1f38ea2

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
"""
2+
SPDX-License-Identifier: AGPL-3.0-or-later
3+
"""
4+
5+
from __future__ import annotations
6+
7+
from pathlib import Path
8+
9+
from django.core.management.base import BaseCommand, CommandError
10+
from django.db import transaction
11+
12+
from dataedit.models import Table
13+
from login.models import myuser
14+
from login.utils import assign_table_holder
15+
16+
17+
class Command(BaseCommand):
18+
help = "Patch table owners by assigning a user as permission"
19+
"holder (via assign_table_holder)."
20+
21+
def add_arguments(self, parser):
22+
user_group = parser.add_mutually_exclusive_group(required=True)
23+
user_group.add_argument("--user-id", type=int, help="User id (myuser.pk)")
24+
user_group.add_argument("--username", type=str, help="Username (myuser.name)")
25+
user_group.add_argument("--email", type=str, help="Email (myuser.email)")
26+
27+
parser.add_argument(
28+
"--from-file",
29+
type=str,
30+
default=None,
31+
help="Read table names from file (one per line; blank lines"
32+
"and #comments ignored).",
33+
)
34+
parser.add_argument(
35+
"table_names",
36+
nargs="*",
37+
help="Table names (edut_00) or schema-qualified (data.edut_00).",
38+
)
39+
parser.add_argument(
40+
"--dry-run",
41+
action="store_true",
42+
help="Don't write changes; only show what would happen.",
43+
)
44+
45+
def _resolve_user(self, options) -> myuser:
46+
if options["user_id"] is not None:
47+
return myuser.objects.get(pk=options["user_id"])
48+
if options["username"]:
49+
return myuser.objects.get(name=options["username"])
50+
if options["email"]:
51+
return myuser.objects.get(email=options["email"])
52+
raise CommandError("No user selector provided (should be unreachable).")
53+
54+
def _load_names(self, options) -> list[str]:
55+
names = list(options["table_names"] or [])
56+
57+
if options["from_file"]:
58+
p = Path(options["from_file"])
59+
if not p.exists():
60+
raise CommandError(f"--from-file path does not exist: {p}")
61+
for line in p.read_text(encoding="utf-8").splitlines():
62+
line = line.strip()
63+
if not line or line.startswith("#"):
64+
continue
65+
names.append(line)
66+
67+
if not names:
68+
raise CommandError(
69+
"No table names provided. Use positional names or --from-file."
70+
)
71+
return names
72+
73+
@staticmethod
74+
def _normalize_table_name(raw: str) -> str:
75+
raw = raw.strip()
76+
# Accept `data.<name>` (schema is always data in your setup)
77+
if raw.startswith("data."):
78+
return raw.split(".", 1)[1]
79+
return raw
80+
81+
def handle(self, *args, **options):
82+
try:
83+
user = self._resolve_user(options)
84+
except myuser.DoesNotExist as e:
85+
raise CommandError(f"User not found: {e}") from e
86+
87+
dry_run = options["dry_run"]
88+
raw_names = self._load_names(options)
89+
table_names = [self._normalize_table_name(n) for n in raw_names]
90+
91+
missing = []
92+
changed = 0
93+
94+
with transaction.atomic():
95+
for name in table_names:
96+
table = Table.objects.filter(name=name).first()
97+
if not table:
98+
missing.append(name)
99+
self.stdout.write(self.style.ERROR(f"missing: {name}"))
100+
continue
101+
102+
if dry_run:
103+
self.stdout.write(
104+
self.style.WARNING(
105+
f"[DRY] would assign holder {user} to {name}"
106+
)
107+
)
108+
continue
109+
110+
# This should create/update the proper UserPermission row(s)
111+
# exactly like normal table creation does.
112+
assign_table_holder(user=user, table=table)
113+
114+
changed += 1
115+
self.stdout.write(self.style.SUCCESS(f"assigned: {user} -> {name}"))
116+
117+
if dry_run:
118+
transaction.set_rollback(True)
119+
120+
self.stdout.write(
121+
self.style.SUCCESS(
122+
f"Done. assigned={changed}, missing={len(missing)}, dry_run={dry_run}"
123+
)
124+
)

0 commit comments

Comments
 (0)