[verified] add user subset reset scope
This commit is contained in:
@@ -5,6 +5,7 @@ Clears:
|
||||
- Neo4j: drops ALL databases except system, neo4j (including gaisdata, cc.users.*, cc.institutes.*)
|
||||
- Supabase: deletes ALL data tables except gais_local_authorities and gais_schools
|
||||
- Supabase: deletes all auth users except kcar, then re-seeds kcar profile state
|
||||
- Granular scopes can clear exam corpus, timetable data, or --user-subset seed copies
|
||||
|
||||
Safe invariants (never touched):
|
||||
- kcar auth account
|
||||
@@ -261,10 +262,40 @@ def _clear_exam_storage() -> Dict[str, Any]:
|
||||
return {"removed": removed, "buckets": list(by_bucket)}
|
||||
|
||||
|
||||
def _clear_user_subset_files() -> Dict[str, Any]:
|
||||
"""Remove files rows and cc.users storage objects created by --user-subset seeding.
|
||||
|
||||
Reuses the seed/unseed implementation so reset(scope="user-subset") has the
|
||||
same storage-before-row deletion order and idempotency guarantees as
|
||||
seed_exam_corpus.py --unseed. The helper only targets rows marked by the seeder:
|
||||
bucket='cc.users', source='exam-corpus-seed', path LIKE 'exam-marker/%'.
|
||||
"""
|
||||
try:
|
||||
from modules.database.supabase.utils.client import SupabaseServiceRoleClient
|
||||
from modules.database.supabase.utils.storage import StorageAdmin
|
||||
from run.initialization.seed_exam_corpus import LoadReport, _delete_user_subset_files
|
||||
except Exception as exc:
|
||||
logger.warning(f" user-subset clear skipped (import): {exc}")
|
||||
return {"files_rows_deleted": 0, "storage_objects_removed": 0, "errors": [str(exc)]}
|
||||
|
||||
rep = LoadReport()
|
||||
_delete_user_subset_files(
|
||||
SupabaseServiceRoleClient(),
|
||||
StorageAdmin(),
|
||||
exam_codes=None,
|
||||
rep=rep,
|
||||
)
|
||||
return {
|
||||
"files_rows_deleted": rep.unseed_user_files,
|
||||
"storage_objects_removed": rep.unseed_objects,
|
||||
"errors": rep.errors,
|
||||
}
|
||||
|
||||
|
||||
# ─── Main reset ───────────────────────────────────────────────────────────────
|
||||
|
||||
def reset(scope: str = "all") -> Dict[str, Any]:
|
||||
"""Destructive reset. scope ∈ {all, exam-corpus, timetable}.
|
||||
"""Destructive reset. scope ∈ {all, exam-corpus, timetable, user-subset}.
|
||||
|
||||
- all : full wipe (Neo4j + Supabase data + auth users) AND the entire
|
||||
exam-marker subsystem listed below.
|
||||
@@ -273,10 +304,12 @@ def reset(scope: str = "all") -> Dict[str, Any]:
|
||||
templates, template layouts, questions, boundaries, response
|
||||
areas, marking batches, student submissions, and mark entries.
|
||||
- timetable : ONLY timetable/calendar materialization tables.
|
||||
- user-subset : ONLY files rows and cc.users storage objects created by
|
||||
seed_exam_corpus.py --user-subset.
|
||||
"""
|
||||
scope = (scope or "all").lower()
|
||||
if scope not in ("all", "exam-corpus", "timetable"):
|
||||
raise ValueError(f"invalid scope {scope!r} (want all|exam-corpus|timetable)")
|
||||
if scope not in ("all", "exam-corpus", "timetable", "user-subset"):
|
||||
raise ValueError(f"invalid scope {scope!r} (want all|exam-corpus|timetable|user-subset)")
|
||||
url, headers = _sb_headers()
|
||||
_assert_reset_allowed(url, scope)
|
||||
|
||||
@@ -291,6 +324,11 @@ def reset(scope: str = "all") -> Dict[str, Any]:
|
||||
cleared, failed = _clear_tables(url, headers, TIMETABLE_TABLES)
|
||||
return {"scope": scope, "tables_cleared": cleared, "tables_failed": failed}
|
||||
|
||||
if scope == "user-subset":
|
||||
logger.info("RESET (scope=user-subset) — --user-subset cc.users storage objects and files rows")
|
||||
user_subset = _clear_user_subset_files()
|
||||
return {"scope": scope, "user_subset": user_subset}
|
||||
|
||||
logger.info("=" * 60)
|
||||
logger.info("RESET ENVIRONMENT — full destructive wipe starting")
|
||||
logger.info("=" * 60)
|
||||
|
||||
Reference in New Issue
Block a user