"""Seed Casdoor (dev) — org `inventory`, app `inventory-app`, users. Idempotent, best-effort helper for local development. Run AFTER the stack is up (casdoor on http://localhost:8080, admin/123): python tools/seed_casdoor.py It talks to Casdoor's REST API. If the Casdoor API version differs, the script logs the failure and keeps going (the important part for local dev is the app + client id/secret, which match frontend/public/casdoor-config.js). """ import os import urllib.request import json BASE = os.environ.get("CASDOOR_BASE", "http://localhost:8080") ADMIN = os.environ.get("CASDOOR_ADMIN", "admin") ADMIN_PW = os.environ.get("CASDOOR_ADMIN_PW", "123") ORG = "inventory" APP = "inventory-app" CLIENT_ID = "inventory-app-client" CLIENT_SECRET = "inventory-app-secret-2026" REDIRECT_URI = "http://localhost:3000/login" USERS = [ # (name, first_name, last_name, email, password, role_tag) ("razaei", "آقای", "رضایی", "razaei@sample.ir", "123456", "admin"), ("mousavi", "آقای", "موسوی", "mousavi@sample.ir", "123456", "pm"), ("mohaghegh", "آقای", "محقق", "mohaghegh@sample.ir", "123456", "pm"), ] def _req(method: str, path: str, body=None, auth: str | None = None): url = BASE + path data = json.dumps(body).encode() if body is not None else None req = urllib.request.Request(url, data=data, method=method) req.add_header("Content-Type", "application/json") if auth: import base64 req.add_header("Authorization", "Basic " + base64.b64encode(auth.encode()).decode()) try: with urllib.request.urlopen(req, timeout=20) as resp: return resp.status, json.loads(resp.read() or b"{}") except Exception as exc: return 0, {"error": str(exc)} def _login(): """Casdoor login -> JWT (its /api/login is form-encoded).""" import urllib.parse data = urllib.parse.urlencode({ "type": "login-normal", "organization": "built-in", "username": ADMIN, "password": ADMIN_PW, }).encode() req = urllib.request.Request(BASE + "/api/login", data=data, method="POST") req.add_header("Content-Type", "application/x-www-form-urlencoded") try: with urllib.request.urlopen(req, timeout=20) as resp: body = json.loads(resp.read() or b"{}") return body.get("data", "") or body.get("accessToken", "") except Exception: return "" def main(): token = _login() auth = f"{ADMIN}:{ADMIN_PW}" if not token else f"Bearer {token}".replace("Bearer ", "Bearer ") # placeholder auth = f"Bearer {token}" if token else None # 1) organization status, body = _req("POST", "/api/add-organization", { "owner": "admin", "name": ORG, "displayName": "سازمان تدارکات", }, auth) print("add-organization:", status, body.get("msg", body.get("error", ""))) # 2) application (client id/secret fixed — matches casdoor-config.js) status, body = _req("POST", "/api/add-application", { "owner": "admin", "name": APP, "displayName": "سامانه تدارکات و انبار", "organization": ORG, "clientId": CLIENT_ID, "clientSecret": CLIENT_SECRET, "redirectUris": [REDIRECT_URI], "grantTypes": ["authorization_code"], "enablePassword": True, "enableSignUp": False, "tokenFormat": "JWT", "expireInHours": 24, }, auth) print("add-application:", status, body.get("msg", body.get("error", ""))) # 3) users for name, first, last, email, pw, _role in USERS: status, body = _req("POST", "/api/add-user", { "owner": ORG, "name": name, "displayName": f"{first} {last}", "firstName": first, "lastName": last, "email": email, "password": pw, "phone": "", "type": "normal-user", }, auth) print(f"add-user {name}:", status, body.get("msg", body.get("error", ""))) print("\nDone. Casdoor console: http://localhost:8080 (admin/123)") print("Login in the app: http://localhost:3000/login") if __name__ == "__main__": main()