feat: add boards and tasks management endpoints
This commit is contained in:
@@ -1,37 +0,0 @@
|
||||
# DB reset + seed (dev-machine)
|
||||
|
||||
This repo uses Alembic migrations as schema source-of-truth.
|
||||
|
||||
## Reset to the current seed
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
./scripts/reset_db.sh
|
||||
```
|
||||
|
||||
Environment variables (optional):
|
||||
|
||||
- `DB_NAME` (default `openclaw_agency`)
|
||||
- `DB_USER` (default `postgres`)
|
||||
- `DB_HOST` (default `127.0.0.1`)
|
||||
- `DB_PORT` (default `5432`)
|
||||
- `DB_PASSWORD` (default `postgres`)
|
||||
|
||||
## Updating the seed
|
||||
|
||||
The seed is a **data-only** dump (not schema). Regenerate it from the current DB state:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
PGPASSWORD=postgres pg_dump \
|
||||
--data-only \
|
||||
--column-inserts \
|
||||
--disable-triggers \
|
||||
--no-owner \
|
||||
--no-privileges \
|
||||
-U postgres -h 127.0.0.1 -d openclaw_agency \
|
||||
> scripts/seed_data.sql
|
||||
|
||||
# IMPORTANT: do not include alembic_version in the seed (migrations already set it)
|
||||
# (our committed seed already has this removed)
|
||||
```
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
. .venv/bin/activate
|
||||
|
||||
python -m black .
|
||||
python -m isort .
|
||||
python -m flake8 .
|
||||
@@ -1,55 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
DB_NAME=${DB_NAME:-openclaw_agency}
|
||||
DB_USER=${DB_USER:-postgres}
|
||||
DB_HOST=${DB_HOST:-127.0.0.1}
|
||||
DB_PORT=${DB_PORT:-5432}
|
||||
|
||||
# Never hardcode passwords in git. Prefer:
|
||||
# - DB_PASSWORD env var, or
|
||||
# - infer from backend/.env DATABASE_URL
|
||||
DB_PASSWORD=${DB_PASSWORD:-}
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
if [[ -z "${DB_PASSWORD}" ]] && [[ -f .env ]]; then
|
||||
DB_PASSWORD=$(python3 - <<'PY'
|
||||
import os
|
||||
from pathlib import Path
|
||||
from urllib.parse import urlparse
|
||||
|
||||
def parse_database_url(url: str) -> str:
|
||||
# supports postgresql+psycopg://user:pass@host:port/db
|
||||
u = urlparse(url)
|
||||
return u.password or ""
|
||||
|
||||
for line in Path('.env').read_text().splitlines():
|
||||
if line.startswith('DATABASE_URL='):
|
||||
print(parse_database_url(line.split('=',1)[1].strip()))
|
||||
break
|
||||
PY
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ -z "${DB_PASSWORD}" ]]; then
|
||||
echo "ERROR: DB_PASSWORD not set and could not infer it from backend/.env DATABASE_URL" >&2
|
||||
echo "Set DB_PASSWORD=... or create backend/.env with DATABASE_URL" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
export PGPASSWORD="$DB_PASSWORD"
|
||||
|
||||
# 1) wipe schema
|
||||
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -v ON_ERROR_STOP=1 \
|
||||
-c 'DROP SCHEMA public CASCADE; CREATE SCHEMA public;'
|
||||
|
||||
# 2) migrate
|
||||
. .venv/bin/activate
|
||||
alembic upgrade head
|
||||
|
||||
# 3) seed
|
||||
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -v ON_ERROR_STOP=1 \
|
||||
-f scripts/seed_data.sql
|
||||
|
||||
echo "Reset complete: $DB_USER@$DB_HOST:$DB_PORT/$DB_NAME"
|
||||
@@ -1,50 +0,0 @@
|
||||
-- Mission Control seed data (minimal)
|
||||
-- Keep this data-only seed small and deterministic.
|
||||
-- NOTE: Do NOT include alembic_version here; migrations manage it.
|
||||
|
||||
SET client_min_messages = warning;
|
||||
SET row_security = off;
|
||||
|
||||
-- Disable triggers to avoid FK ordering issues during seed.
|
||||
ALTER TABLE public.employees DISABLE TRIGGER ALL;
|
||||
ALTER TABLE public.departments DISABLE TRIGGER ALL;
|
||||
ALTER TABLE public.teams DISABLE TRIGGER ALL;
|
||||
ALTER TABLE public.projects DISABLE TRIGGER ALL;
|
||||
ALTER TABLE public.tasks DISABLE TRIGGER ALL;
|
||||
ALTER TABLE public.task_comments DISABLE TRIGGER ALL;
|
||||
ALTER TABLE public.project_members DISABLE TRIGGER ALL;
|
||||
ALTER TABLE public.activities DISABLE TRIGGER ALL;
|
||||
|
||||
-- Employees (keep only Abhimanyu)
|
||||
INSERT INTO public.employees (id, name, employee_type, department_id, manager_id, title, status, openclaw_session_key, notify_enabled, team_id)
|
||||
VALUES
|
||||
(1, 'Abhimanyu', 'human', NULL, NULL, 'CEO', 'active', NULL, false, NULL)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
name = EXCLUDED.name,
|
||||
employee_type = EXCLUDED.employee_type,
|
||||
department_id = EXCLUDED.department_id,
|
||||
manager_id = EXCLUDED.manager_id,
|
||||
title = EXCLUDED.title,
|
||||
status = EXCLUDED.status,
|
||||
openclaw_session_key = EXCLUDED.openclaw_session_key,
|
||||
notify_enabled = EXCLUDED.notify_enabled,
|
||||
team_id = EXCLUDED.team_id;
|
||||
|
||||
-- Fix sequences (avoid PK reuse after explicit ids)
|
||||
SELECT setval('employees_id_seq', (SELECT COALESCE(max(id), 1) FROM public.employees));
|
||||
SELECT setval('departments_id_seq', (SELECT COALESCE(max(id), 1) FROM public.departments));
|
||||
SELECT setval('teams_id_seq', (SELECT COALESCE(max(id), 1) FROM public.teams));
|
||||
SELECT setval('projects_id_seq', (SELECT COALESCE(max(id), 1) FROM public.projects));
|
||||
SELECT setval('tasks_id_seq', (SELECT COALESCE(max(id), 1) FROM public.tasks));
|
||||
SELECT setval('task_comments_id_seq', (SELECT COALESCE(max(id), 1) FROM public.task_comments));
|
||||
SELECT setval('project_members_id_seq', (SELECT COALESCE(max(id), 1) FROM public.project_members));
|
||||
SELECT setval('activities_id_seq', (SELECT COALESCE(max(id), 1) FROM public.activities));
|
||||
|
||||
ALTER TABLE public.employees ENABLE TRIGGER ALL;
|
||||
ALTER TABLE public.departments ENABLE TRIGGER ALL;
|
||||
ALTER TABLE public.teams ENABLE TRIGGER ALL;
|
||||
ALTER TABLE public.projects ENABLE TRIGGER ALL;
|
||||
ALTER TABLE public.tasks ENABLE TRIGGER ALL;
|
||||
ALTER TABLE public.task_comments ENABLE TRIGGER ALL;
|
||||
ALTER TABLE public.project_members ENABLE TRIGGER ALL;
|
||||
ALTER TABLE public.activities ENABLE TRIGGER ALL;
|
||||
46
backend/scripts/seed_demo.py
Normal file
46
backend/scripts/seed_demo.py
Normal file
@@ -0,0 +1,46 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from uuid import uuid4
|
||||
|
||||
from sqlmodel import Session
|
||||
|
||||
from app.db.session import engine
|
||||
from app.models.orgs import Org, Workspace
|
||||
from app.models.users import Membership, User
|
||||
|
||||
|
||||
def run() -> None:
|
||||
with Session(engine) as session:
|
||||
org = Org(name="Demo Org", slug="demo-org")
|
||||
session.add(org)
|
||||
session.commit()
|
||||
session.refresh(org)
|
||||
|
||||
workspace = Workspace(org_id=org.id, name="Demo Workspace", slug="demo-workspace")
|
||||
session.add(workspace)
|
||||
session.commit()
|
||||
session.refresh(workspace)
|
||||
|
||||
user = User(
|
||||
clerk_user_id=f"demo-{uuid4()}",
|
||||
email="demo@example.com",
|
||||
name="Demo Admin",
|
||||
is_super_admin=True,
|
||||
)
|
||||
session.add(user)
|
||||
session.commit()
|
||||
session.refresh(user)
|
||||
|
||||
membership = Membership(
|
||||
org_id=org.id,
|
||||
workspace_id=workspace.id,
|
||||
user_id=user.id,
|
||||
role="admin",
|
||||
)
|
||||
session.add(membership)
|
||||
|
||||
session.commit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
Reference in New Issue
Block a user