Wiki/docmost-acadenice-seed/create-space-etudiant.py
Corentin JOGUET 8b42cbc787
Some checks are pending
CI / Lint bridge (Biome) (push) Waiting to run
CI / Type-check bridge (push) Blocked by required conditions
CI / Tests unit bridge (push) Blocked by required conditions
CI / Tests integration bridge (push) Blocked by required conditions
CI / Security scan (push) Waiting to run
CI / Docker build + healthcheck (push) Blocked by required conditions
chore(docmost): clone upstream + isole seed scripts Acadenice
- Move docmost/setup/* vers docmost-acadenice-seed/ (preserve historique git)
- Clone Docmost upstream (depth=1) dans docmost/, gitignore le sub-repo
- Branche acadenice/main creee dans le fork pour patches
- Prepare Bloc 4 (auth federee) puis Bloc 8 (Tiptap node-views)
2026-05-07 20:57:15 +02:00

182 lines
6.4 KiB
Python

#!/usr/bin/env python3
"""Cree un space etudiant prive dans Docmost — pattern story S-08.
Usage :
DOCMOST_URL=http://localhost:3000 \\
DOCMOST_ADMIN_EMAIL=corentin@acadenice.fr \\
DOCMOST_ADMIN_PASSWORD=... \\
python docmost/setup/create-space-etudiant.py \\
--nom "Dupont" --prenom "Marie" --email "marie.dupont@acadenice.fr"
Cree :
- Un space "Etudiant - Marie Dupont" en visibility=private
- Y invite l'etudiant en role 'writer'
- Cree une page template "Bienvenue" avec instructions
Idempotent : skip si space existe deja.
"""
import argparse
import os
import sys
from typing import Any
import requests
class DocmostSpaceCreator:
def __init__(self, base_url: str) -> None:
self.base_url = base_url.rstrip("/")
self.session = requests.Session()
self.session.headers.update({"Content-Type": "application/json"})
def _post(self, path: str, body: dict[str, Any] | None = None) -> dict[str, Any]:
r = self.session.post(f"{self.base_url}{path}", json=body or {})
if r.status_code >= 300:
print(f" [ERROR] POST {path}{r.status_code} resp={r.text[:300]}")
r.raise_for_status()
if not r.text:
return {}
payload = r.json()
if isinstance(payload, dict) and "data" in payload and isinstance(payload["data"], (dict, list)):
return payload["data"]
return payload
def login(self, email: str, password: str) -> None:
self._post("/api/auth/login", {"email": email, "password": password})
print(f" [auth] Logged in as {email}")
def list_spaces(self) -> list[dict[str, Any]]:
try:
data = self._post("/api/spaces/", {"page": 1, "limit": 100})
if isinstance(data, dict):
return data.get("items") or []
if isinstance(data, list):
return data
except requests.HTTPError:
pass
return []
def create_space(self, name: str, description: str, slug: str, visibility: str = "private") -> str:
result = self._post(
"/api/spaces/create",
{"name": name, "description": description, "slug": slug, "visibility": visibility},
)
return result.get("id")
def add_member_by_email(self, space_id: str, email: str, role: str = "writer") -> dict[str, Any] | None:
try:
return self._post(
"/api/spaces/members/add",
{"spaceId": space_id, "userEmails": [email], "role": role},
)
except requests.HTTPError as e:
print(f" [member] Echec ajout {email} : {e}")
print(f" (l'etudiant doit deja exister comme user Docmost. Sinon, l'inviter d'abord via UI ou API user/create.)")
return None
def create_page(self, space_id: str, title: str, content_md: str) -> str:
result = self._post(
"/api/pages/create",
{"spaceId": space_id, "title": title, "format": "markdown", "content": content_md},
)
return result.get("id")
def welcome_template(prenom: str, nom: str) -> str:
return f"""# Bienvenue {prenom} !
Voici ton **espace personnel** sur le wiki Acadenice. Il est **prive** : seul toi et l'admin peuvent le voir.
## Tu peux faire ce que tu veux ici
- Prendre des notes pendant les cours
- Garder tes ressources perso (liens, references, brouillons)
- Tester les fonctionnalites du wiki :
- `/mermaid` pour faire un diagramme
- `/excalidraw` pour dessiner
- `/drawio` pour des schemas techniques
- Liste, tableaux, code blocks, embeds video, etc.
## Quelques idees pour commencer
- Cree une page "Mes objectifs formation"
- Une page par module avec tes notes
- Un journal d'apprentissage hebdomadaire
## Acces aux supports formation
Les supports officiels sont dans le space **CFA** (lecture seule pour toi).
Bonne formation !
— L'equipe Acadenice
"""
def slugify(s: str) -> str:
"""Docmost exige slug = lettres + chiffres uniquement."""
import re
return re.sub(r"[^a-z0-9]", "", s.lower())
def main() -> int:
parser = argparse.ArgumentParser(description="Cree un space etudiant Docmost")
parser.add_argument("--nom", required=True)
parser.add_argument("--prenom", required=True)
parser.add_argument("--email", required=True, help="Email de l'etudiant (doit exister comme user Docmost)")
parser.add_argument("--no-template", action="store_true", help="Ne pas creer la page Bienvenue")
args = parser.parse_args()
base_url = os.environ.get("DOCMOST_URL", "http://localhost:3000")
admin_email = os.environ.get("DOCMOST_ADMIN_EMAIL")
admin_password = os.environ.get("DOCMOST_ADMIN_PASSWORD")
if not admin_email or not admin_password:
print("ERROR: set DOCMOST_ADMIN_EMAIL and DOCMOST_ADMIN_PASSWORD", file=sys.stderr)
return 1
creator = DocmostSpaceCreator(base_url)
space_name = f"Etudiant - {args.prenom} {args.nom}"
slug = slugify(f"etudiant-{args.prenom}-{args.nom}")
try:
print(f"\n[1/4] Login admin")
creator.login(admin_email, admin_password)
print(f"\n[2/4] Check existing space '{space_name}'")
existing = next((s for s in creator.list_spaces() if s.get("slug") == slug or s.get("name") == space_name), None)
if existing:
sid = existing["id"]
print(f" [space] Reuse id={sid}")
else:
sid = creator.create_space(
name=space_name,
description=f"Space personnel de {args.prenom} {args.nom}. Libre usage.",
slug=slug,
visibility="private",
)
print(f" [space] Created id={sid}")
print(f"\n[3/4] Add etudiant {args.email} as writer")
creator.add_member_by_email(sid, args.email, role="writer")
if not args.no_template:
print(f"\n[4/4] Welcome page template")
try:
creator.create_page(sid, "Bienvenue", welcome_template(args.prenom, args.nom))
print(f" [page] Created Bienvenue")
except requests.HTTPError as e:
print(f" [page] Skip (peut-etre deja existante) : {e}")
print(f"\n=== Space etudiant OK ===")
print(f" Name : {space_name}")
print(f" Slug : {slug}")
print(f" URL : {base_url} (login {args.email})")
except requests.HTTPError as e:
print(f"\nHTTP error: {e}", file=sys.stderr)
return 2
return 0
if __name__ == "__main__":
sys.exit(main())