feat: Add Bulk Registration, Change Password, and update Auth UI
This commit is contained in:
@@ -195,6 +195,93 @@ class LoginPayload(BaseModel):
|
||||
email: str
|
||||
password: str
|
||||
|
||||
|
||||
import csv
|
||||
import io
|
||||
import secrets
|
||||
import string
|
||||
import bcrypt
|
||||
|
||||
class ChangePasswordRequest(BaseModel):
|
||||
current_password: str
|
||||
new_password: str
|
||||
|
||||
@app.post("/api/auth/change-password", tags=["Authentication"])
|
||||
def change_password(payload: ChangePasswordRequest, session: Session = Depends(get_session), current_user: models.User = Depends(get_current_user)):
|
||||
# Check demo account
|
||||
if current_user.email == "demo@pragativeer.com":
|
||||
if payload.current_password != "Pv9#kL2$mQ8!vX4@":
|
||||
raise HTTPException(status_code=400, detail="Incorrect current password")
|
||||
# Don't actually change demo password
|
||||
return {"success": True, "message": "Demo password unchanged"}
|
||||
|
||||
if not current_user.password_hash or current_user.password_hash == "mock_hash":
|
||||
raise HTTPException(status_code=400, detail="User has no password set")
|
||||
|
||||
if not bcrypt.checkpw(payload.current_password.encode('utf-8'), current_user.password_hash.encode('utf-8')):
|
||||
raise HTTPException(status_code=400, detail="Incorrect current password")
|
||||
|
||||
hashed_password = bcrypt.hashpw(payload.new_password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
|
||||
current_user.password_hash = hashed_password
|
||||
session.add(current_user)
|
||||
session.commit()
|
||||
return {"success": True, "message": "Password updated successfully"}
|
||||
|
||||
@app.post("/api/admin/students/bulk", tags=["Admin"])
|
||||
async def bulk_register_students(file: UploadFile = File(...), session: Session = Depends(get_session)):
|
||||
# Simple check for now (we can rely on frontend calling it correctly or auth middleware if we add it)
|
||||
content = await file.read()
|
||||
decoded = content.decode('utf-8')
|
||||
csv_reader = csv.DictReader(io.StringIO(decoded))
|
||||
|
||||
results = []
|
||||
|
||||
for row in csv_reader:
|
||||
email = row.get("email", "").strip()
|
||||
name = row.get("name", "").strip()
|
||||
phone = row.get("phone", "").strip()
|
||||
target_exam_str = row.get("target_exam", "JEE_Main").strip()
|
||||
tier_str = row.get("tier", "Free").strip()
|
||||
|
||||
if not email or not name:
|
||||
continue
|
||||
|
||||
existing = session.exec(select(models.User).where(models.User.email == email)).first()
|
||||
if existing:
|
||||
continue
|
||||
|
||||
alphabet = string.ascii_letters + string.digits
|
||||
password = ''.join(secrets.choice(alphabet) for i in range(8))
|
||||
|
||||
exam = models.ExamEnum.JEE_Main
|
||||
if target_exam_str == "NEET": exam = models.ExamEnum.NEET
|
||||
elif target_exam_str == "JEE_Advanced": exam = models.ExamEnum.JEE_Advanced
|
||||
elif target_exam_str == "JEE_NEET": exam = models.ExamEnum.JEE_NEET
|
||||
elif target_exam_str == "JEE + NEET": exam = models.ExamEnum.JEE_NEET
|
||||
|
||||
tier = models.TierEnum.Free
|
||||
if tier_str == "Pro": tier = models.TierEnum.Pro
|
||||
elif tier_str in ("Al_Coach", "AI Coach"): tier = models.TierEnum.Al_Coach
|
||||
|
||||
hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
|
||||
user = models.User(
|
||||
email=email,
|
||||
name=name,
|
||||
phone=phone,
|
||||
password_hash=hashed_password,
|
||||
target_exam=exam,
|
||||
tier=tier
|
||||
)
|
||||
session.add(user)
|
||||
results.append({
|
||||
"name": name,
|
||||
"email": email,
|
||||
"password": password
|
||||
})
|
||||
|
||||
session.commit()
|
||||
return results
|
||||
|
||||
@app.post("/api/auth/register", tags=["Authentication"])
|
||||
def register(payload: RegisterPayload, session: Session = Depends(get_session)):
|
||||
import bcrypt
|
||||
|
||||
Reference in New Issue
Block a user