Skip to content

Commit 5206620

Browse files
author
Uttam Singh
committed
Added admin seed route
1 parent 35a3880 commit 5206620

File tree

6 files changed

+71
-167
lines changed

6 files changed

+71
-167
lines changed

backend/.env

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
1-
# Backend Environment
2-
DATABASE_URL=postgresql+psycopg2://fatuser:fatpass@db:5432/fatdb
1+
DATABASE_URL=sqlite:///./app.db
32
SECRET_KEY=dev-secret
3+
ALLOW_ORIGINS=*
44
5-
SMTP_HOST=
6-
SMTP_PORT=587
7-
SMTP_USER=
8-
SMTP_PASS=
95
OPENAI_API_KEY=
10-
ALLOW_ORIGINS=*
258 Bytes
Binary file not shown.
1.04 KB
Binary file not shown.

backend/app/main.py

Lines changed: 15 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,27 @@
11
from fastapi import FastAPI, UploadFile, File, Depends, HTTPException, Form
22
from fastapi.middleware.cors import CORSMiddleware
3-
from sqlalchemy.orm import Session
3+
from sqlalchemy import create_engine, Column, Integer, String, Date, Text
4+
from sqlalchemy.orm import sessionmaker, declarative_base, Session
45
from pydantic import BaseModel
56
from datetime import date
67
import os, shutil
78
from dotenv import load_dotenv
8-
import requests
99

10-
# ✅ Import from database (moved get_db here to avoid circular import)
11-
from app.database import Base, engine, get_db
12-
13-
# ✅ Import users router (no circular import now)
14-
from app.routers import users
15-
16-
# Optional OpenAI
17-
try:
18-
from openai import OpenAI
19-
except Exception:
20-
OpenAI = None
21-
22-
# Load environment variables
10+
# ⬇️ your database bits
2311
load_dotenv()
12+
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///./app.db")
13+
engine = create_engine(DATABASE_URL, pool_pre_ping=True)
14+
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
15+
Base = declarative_base()
16+
17+
# ⬇️ import models so SQLAlchemy knows about User
18+
from app import models
19+
# … define Task/AuditLog classes …
20+
Base.metadata.create_all(bind=engine)
2421

25-
# === FastAPI App ===
2622
app = FastAPI(title="FAT-EIBL (Edme) – API")
2723

28-
# === CORS ===
24+
# CORS
2925
allow = os.getenv("ALLOW_ORIGINS", "*").split(",")
3026
app.add_middleware(
3127
CORSMiddleware,
@@ -35,147 +31,6 @@
3531
allow_headers=["*"],
3632
)
3733

38-
# === Models (local models only for tasks/audit) ===
39-
from sqlalchemy import Column, Integer, String, Date, Text
40-
41-
class Task(Base):
42-
__tablename__ = "tasks"
43-
id = Column(Integer, primary_key=True, index=True)
44-
title = Column(String(255), nullable=False)
45-
department = Column(String(100), nullable=True)
46-
assignee = Column(String(100), nullable=True)
47-
status = Column(String(50), nullable=False, default="Pending")
48-
due_date = Column(Date, nullable=True)
49-
priority = Column(String(20), nullable=True)
50-
remarks = Column(Text, nullable=True)
51-
attachment = Column(String(255), nullable=True)
52-
53-
class AuditLog(Base):
54-
__tablename__ = "audit_logs"
55-
id = Column(Integer, primary_key=True)
56-
action = Column(String(50))
57-
detail = Column(Text)
58-
59-
# ✅ Create all tables (includes Task, AuditLog, and user models)
60-
Base.metadata.create_all(bind=engine)
61-
62-
# === Pydantic Schemas ===
63-
class TaskCreate(BaseModel):
64-
title: str
65-
department: str | None = None
66-
assignee: str | None = None
67-
status: str = "Pending"
68-
due_date: date | None = None
69-
priority: str | None = None
70-
remarks: str | None = None
71-
72-
class TaskOut(BaseModel):
73-
id: int
74-
title: str
75-
department: str | None
76-
assignee: str | None
77-
status: str
78-
due_date: date | None
79-
priority: str | None
80-
remarks: str | None
81-
attachment: str | None
82-
83-
class Config:
84-
from_attributes = True
85-
86-
# === Routes ===
87-
88-
@app.get("/health")
89-
def health():
90-
return {"status": "ok"}
91-
92-
# --- TASK CRUD ---
93-
@app.get("/tasks", response_model=list[TaskOut])
94-
def list_tasks(db: Session = Depends(get_db)):
95-
return db.query(Task).order_by(Task.due_date.is_(None), Task.due_date).all()
96-
97-
@app.post("/tasks", response_model=TaskOut)
98-
def create_task(task: TaskCreate, db: Session = Depends(get_db)):
99-
obj = Task(**task.dict())
100-
db.add(obj)
101-
db.add(AuditLog(action="create", detail=f"Task: {obj.title}"))
102-
db.commit()
103-
db.refresh(obj)
104-
return obj
105-
106-
@app.put("/tasks/{task_id}", response_model=TaskOut)
107-
def update_task(task_id: int, task: TaskCreate, db: Session = Depends(get_db)):
108-
obj = db.get(Task, task_id)
109-
if not obj:
110-
raise HTTPException(status_code=404, detail="Task not found")
111-
for k, v in task.dict().items():
112-
setattr(obj, k, v)
113-
db.add(AuditLog(action="update", detail=f"Task ID {task_id}"))
114-
db.commit()
115-
db.refresh(obj)
116-
return obj
117-
118-
@app.delete("/tasks/{task_id}")
119-
def delete_task(task_id: int, db: Session = Depends(get_db)):
120-
obj = db.get(Task, task_id)
121-
if not obj:
122-
raise HTTPException(status_code=404, detail="Task not found")
123-
db.delete(obj)
124-
db.add(AuditLog(action="delete", detail=f"Task ID {task_id}"))
125-
db.commit()
126-
return {"ok": True}
127-
128-
# --- UPLOAD ---
129-
UPLOAD_DIR = os.path.join(os.getcwd(), "uploads")
130-
os.makedirs(UPLOAD_DIR, exist_ok=True)
131-
132-
@app.post("/upload/{task_id}")
133-
async def upload_file(task_id: int, file: UploadFile = File(...), db: Session = Depends(get_db)):
134-
obj = db.get(Task, task_id)
135-
if not obj:
136-
raise HTTPException(status_code=404, detail="Task not found")
137-
safe_name = f"task_{task_id}_" + os.path.basename(file.filename)
138-
dest = os.path.join(UPLOAD_DIR, safe_name)
139-
with open(dest, "wb") as buffer:
140-
shutil.copyfileobj(file.file, buffer)
141-
obj.attachment = safe_name
142-
db.add(AuditLog(action="upload", detail=f"Task ID {task_id} file {safe_name}"))
143-
db.commit()
144-
return {"task_id": task_id, "filename": safe_name}
145-
146-
# --- SEED ---
147-
@app.get("/seed")
148-
def seed(db: Session = Depends(get_db)):
149-
if db.query(Task).count() == 0:
150-
for t in [
151-
Task(title="IRDAI Filing Q3", department="Compliance", assignee="Darpan", status="Pending", priority="High"),
152-
Task(title="Statutory Audit FY 24-25", department="Accounts", assignee="Priya", status="In Progress", priority="High"),
153-
Task(title="Investment Reconciliation", department="Ops", assignee="Rakesh", status="Pending", priority="Medium"),
154-
]:
155-
db.add(t)
156-
db.add(AuditLog(action="seed", detail="Sample tasks added"))
157-
db.commit()
158-
return {"seeded": True}
159-
160-
# --- AI CHAT ---
161-
@app.post("/ai/chat")
162-
def ai_chat(prompt: str = Form(...)):
163-
api_key = os.getenv("OPENAI_API_KEY", "")
164-
if not api_key or OpenAI is None:
165-
return {"reply": "AI is not configured. Please set OPENAI_API_KEY in backend/.env."}
166-
client = OpenAI(api_key=api_key)
167-
try:
168-
resp = client.chat.completions.create(
169-
model="gpt-4o-mini",
170-
messages=[
171-
{"role": "system", "content": "You are Vani, an AI assistant for an audit tracker."},
172-
{"role": "user", "content": prompt}
173-
]
174-
)
175-
return {"reply": resp.choices[0].message.content}
176-
except Exception as e:
177-
return {"reply": f"AI error: {e}"}
178-
179-
# --- USER ROUTES ---
34+
# at the bottom: include users router
35+
from app.routers import users
18036
app.include_router(users.router, prefix="/users", tags=["Users"])
181-

backend/app/routers/users.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,30 @@ def delete_user(user_id: int, db: Session = Depends(get_db)):
5757
db.delete(user)
5858
db.commit()
5959
return {"ok": True, "message": "User deleted"}
60+
@router.get("/check-admin")
61+
def check_admin(db: Session = Depends(get_db)):
62+
users = db.query(User).all()
63+
return {"count": len(users), "users": [u.email for u in users]}
64+
# ✅ Seed Admin User (one-time setup)
65+
@router.post("/seed-admin")
66+
def seed_admin(db: Session = Depends(get_db)):
67+
from passlib.hash import bcrypt
68+
69+
70+
existing = db.query(User).filter(User.email == email).first()
71+
if existing:
72+
return {"ok": True, "note": "Admin already exists"}
73+
74+
admin = User(
75+
name="Admin",
76+
email=email,
77+
hashed_password=bcrypt.hash("Edme@123"),
78+
department="Finance",
79+
role="admin",
80+
manager_email=None,
81+
)
82+
db.add(admin)
83+
db.commit()
84+
return {"ok": True, "note": "Admin created"}
85+
86+

backend/seed/admin.py.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import os
2+
os.environ.setdefault("DATABASE_URL", "sqlite:///./app.db")
3+
4+
from app.main import SessionLocal # uses the same engine/session
5+
from app.models.user import User
6+
from passlib.hash import bcrypt
7+
8+
db = SessionLocal()
9+
10+
# delete old admin if exists
11+
old = db.query(User).filter(User.email == "[email protected]").first()
12+
if old:
13+
db.delete(old)
14+
db.commit()
15+
16+
admin = User(
17+
name="Admin",
18+
19+
hashed_password=bcrypt.hash("Edme@123"),
20+
department="Finance",
21+
role="admin",
22+
manager_email=None
23+
)
24+
db.add(admin)
25+
db.commit()
26+
db.close()
27+
print("✅ Admin created: [email protected] / Edme@123")

0 commit comments

Comments
 (0)