Add is_default flag for system trees

- Add is_default column to trees table
- Default trees have no author and are visible to all users
- Only admins can create default trees
- Update seed script to mark seeded trees as default
- Update seed script to use CLI auth instead of creating seed user

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-02-01 01:32:10 -05:00
parent b96cbab087
commit db0b05eba7
5 changed files with 72 additions and 44 deletions

View File

@@ -20,13 +20,9 @@ from typing import Any
# API Configuration
API_BASE_URL = "http://localhost:8000/api/v1"
# Default admin user for seeding
SEED_USER = {
"email": "seed.admin@example.com",
"password": "SeedAdmin123!",
"name": "Seed Admin",
"role": "admin"
}
# Admin credentials (set via command line or environment)
ADMIN_EMAIL = None
ADMIN_PASSWORD = None
# =============================================================================
@@ -3308,39 +3304,23 @@ def get_file_share_access_tree() -> dict[str, Any]:
# SEEDING FUNCTIONS
# =============================================================================
async def get_or_create_admin_user(client: httpx.AsyncClient) -> tuple[str, dict]:
"""Get authentication token for seeding. Creates admin user if needed."""
async def get_admin_token(client: httpx.AsyncClient) -> str:
"""Get authentication token using provided admin credentials."""
# Try to login first
if not ADMIN_EMAIL or not ADMIN_PASSWORD:
raise Exception("Admin email and password are required. Use --email and --password arguments.")
# Login with provided credentials
login_response = await client.post(
f"{API_BASE_URL}/auth/login/json",
json={"email": SEED_USER["email"], "password": SEED_USER["password"]}
)
if login_response.status_code == 200:
token_data = login_response.json()
return token_data["access_token"], {"exists": True}
# User doesn't exist, create them
register_response = await client.post(
f"{API_BASE_URL}/auth/register",
json=SEED_USER
)
if register_response.status_code not in (200, 201):
raise Exception(f"Failed to create seed user: {register_response.text}")
# Now login
login_response = await client.post(
f"{API_BASE_URL}/auth/login/json",
json={"email": SEED_USER["email"], "password": SEED_USER["password"]}
f"{API_BASE_URL}/auth/login",
data={"username": ADMIN_EMAIL, "password": ADMIN_PASSWORD}
)
if login_response.status_code != 200:
raise Exception(f"Failed to login as seed user: {login_response.text}")
raise Exception(f"Failed to login: {login_response.text}")
token_data = login_response.json()
return token_data["access_token"], {"exists": False, "user": register_response.json()}
return token_data["access_token"]
async def create_tree(client: httpx.AsyncClient, token: str, tree_data: dict) -> dict | None:
@@ -3356,6 +3336,9 @@ async def create_tree(client: httpx.AsyncClient, token: str, tree_data: dict) ->
print(f" [SKIP] Tree '{tree_data['name']}' already exists (ID: {tree['id']})")
return None
# Mark as default/system tree
tree_data["is_default"] = True
# Create the tree
response = await client.post(
f"{API_BASE_URL}/trees",
@@ -3390,16 +3373,13 @@ async def seed_database():
print(" Run: uvicorn app.main:app --reload")
return False
# Get or create admin user
print("\n[1/3] Setting up seed user...")
# Authenticate with admin credentials
print("\n[1/3] Authenticating...")
try:
token, user_info = await get_or_create_admin_user(client)
if user_info.get("exists"):
print(" Using existing seed admin user")
else:
print(f" Created seed admin user: {SEED_USER['email']}")
token = await get_admin_token(client)
print(f" Logged in as {ADMIN_EMAIL}")
except Exception as e:
print(f" [ERROR] Failed to setup seed user: {e}")
print(f" [ERROR] Failed to authenticate: {e}")
return False
# Get all tree definitions
@@ -3460,10 +3440,22 @@ def main():
default="http://localhost:8000/api/v1",
help="API base URL (default: http://localhost:8000/api/v1)"
)
parser.add_argument(
"--email",
required=True,
help="Admin user email for authentication"
)
parser.add_argument(
"--password",
required=True,
help="Admin user password for authentication"
)
args = parser.parse_args()
global API_BASE_URL
global API_BASE_URL, ADMIN_EMAIL, ADMIN_PASSWORD
API_BASE_URL = args.api_url
ADMIN_EMAIL = args.email
ADMIN_PASSWORD = args.password
success = asyncio.run(seed_database())
exit(0 if success else 1)