Added init endpoint.

This commit is contained in:
2026-01-11 18:57:47 -06:00
parent a97912188e
commit e0801b7f29
2 changed files with 81 additions and 7 deletions

View File

@ -1,8 +1,13 @@
from fastapi import FastAPI
from fastapi import FastAPI, Depends
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
from app.database import init_db
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func
from decimal import Decimal
from app.database import init_db, get_db
from app.routers import auth, users, wallet, bets, websocket, admin, sport_events, spread_bets, gamification, matches
from app.models import User, Wallet
from app.utils.security import get_password_hash
@asynccontextmanager
@ -50,3 +55,64 @@ async def root():
@app.get("/health")
async def health():
return {"status": "healthy"}
@app.get("/init")
async def init_admin(db: AsyncSession = Depends(get_db)):
"""
Initialize the application with a default admin user.
Only works if no admin users exist in the database.
Creates: admin@test.com / password123
"""
# Check if any admin users exist
result = await db.execute(
select(func.count(User.id)).where(User.is_admin == True)
)
admin_count = result.scalar()
if admin_count > 0:
return {
"success": False,
"message": "Admin user(s) already exist. Initialization skipped.",
"admin_count": admin_count
}
# Check if user with this email already exists
existing = await db.execute(
select(User).where(User.email == "admin@test.com")
)
if existing.scalar_one_or_none():
return {
"success": False,
"message": "User with email admin@test.com already exists but is not an admin."
}
# Create admin user
admin_user = User(
email="admin@test.com",
username="admin",
password_hash=get_password_hash("password123"),
display_name="Administrator",
is_admin=True,
)
db.add(admin_user)
await db.flush()
# Create wallet for admin
wallet = Wallet(
user_id=admin_user.id,
balance=Decimal("10000.00"),
escrow=Decimal("0.00"),
)
db.add(wallet)
await db.commit()
return {
"success": True,
"message": "Admin user created successfully",
"credentials": {
"email": "admin@test.com",
"password": "password123"
}
}

View File

@ -44,17 +44,25 @@ export const AdminDataTools = () => {
const seedMutation = useMutation({
mutationFn: adminApi.seedDatabase,
onSuccess: (data) => {
console.log('Seed success:', data)
toast.success(data.message)
if (data.test_admin) {
toast.success(`Test admin created: ${data.test_admin.username} / ${data.test_admin.password}`, {
duration: 10000,
})
}
// Show what was created
const counts = data.created_counts
toast.success(`Created: ${counts.users} users, ${counts.events} events, ${counts.bets} bets`, {
duration: 5000,
})
queryClient.invalidateQueries()
refetchPreview()
},
onError: (error: any) => {
toast.error(error.response?.data?.detail || 'Seed failed')
console.error('Seed error:', error)
const message = error.response?.data?.detail || error.message || 'Seed failed'
toast.error(message)
},
})
@ -216,7 +224,7 @@ export const AdminDataTools = () => {
<input
type="number"
value={seedConfig.num_users}
onChange={(e) => setSeedConfig({ ...seedConfig, num_users: parseInt(e.target.value) || 0 })}
onChange={(e) => setSeedConfig({ ...seedConfig, num_users: Math.max(1, parseInt(e.target.value) || 1) })}
min={1}
max={100}
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
@ -228,7 +236,7 @@ export const AdminDataTools = () => {
<input
type="number"
value={seedConfig.num_events}
onChange={(e) => setSeedConfig({ ...seedConfig, num_events: parseInt(e.target.value) || 0 })}
onChange={(e) => setSeedConfig({ ...seedConfig, num_events: Math.max(0, parseInt(e.target.value) || 0) })}
min={0}
max={50}
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
@ -240,7 +248,7 @@ export const AdminDataTools = () => {
<input
type="number"
value={seedConfig.num_bets_per_event}
onChange={(e) => setSeedConfig({ ...seedConfig, num_bets_per_event: parseInt(e.target.value) || 0 })}
onChange={(e) => setSeedConfig({ ...seedConfig, num_bets_per_event: Math.max(0, parseInt(e.target.value) || 0) })}
min={0}
max={20}
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
@ -252,7 +260,7 @@ export const AdminDataTools = () => {
<input
type="number"
value={seedConfig.starting_balance}
onChange={(e) => setSeedConfig({ ...seedConfig, starting_balance: parseInt(e.target.value) || 0 })}
onChange={(e) => setSeedConfig({ ...seedConfig, starting_balance: parseInt(e.target.value) || 100 })}
min={100}
max={10000}
className="w-full px-3 py-2 border border-gray-300 rounded-lg"