Add first and last name fields for users
All checks were successful
PostgreSQL Compatibility Matrix / PG14 smoke (pull_request) Successful in 12s
PostgreSQL Compatibility Matrix / PG15 smoke (pull_request) Successful in 11s
PostgreSQL Compatibility Matrix / PG16 smoke (pull_request) Successful in 9s
PostgreSQL Compatibility Matrix / PG17 smoke (pull_request) Successful in 10s
PostgreSQL Compatibility Matrix / PG18 smoke (pull_request) Successful in 11s
All checks were successful
PostgreSQL Compatibility Matrix / PG14 smoke (pull_request) Successful in 12s
PostgreSQL Compatibility Matrix / PG15 smoke (pull_request) Successful in 11s
PostgreSQL Compatibility Matrix / PG16 smoke (pull_request) Successful in 9s
PostgreSQL Compatibility Matrix / PG17 smoke (pull_request) Successful in 10s
PostgreSQL Compatibility Matrix / PG18 smoke (pull_request) Successful in 11s
This commit introduces optional `first_name` and `last_name` fields to the user model, including database migrations, backend, and frontend support. It enhances user profiles, updates user creation and editing flows, and refines the UI to display full names where available.
This commit is contained in:
@@ -23,7 +23,13 @@ async def create_user(payload: UserCreate, admin: User = Depends(require_roles("
|
||||
exists = await db.scalar(select(User).where(User.email == payload.email))
|
||||
if exists:
|
||||
raise HTTPException(status_code=409, detail="Email already exists")
|
||||
user = User(email=payload.email, password_hash=hash_password(payload.password), role=payload.role)
|
||||
user = User(
|
||||
email=payload.email,
|
||||
first_name=payload.first_name,
|
||||
last_name=payload.last_name,
|
||||
password_hash=hash_password(payload.password),
|
||||
role=payload.role,
|
||||
)
|
||||
db.add(user)
|
||||
await db.commit()
|
||||
await db.refresh(user)
|
||||
@@ -42,8 +48,15 @@ async def update_user(
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
update_data = payload.model_dump(exclude_unset=True)
|
||||
if "password" in update_data and update_data["password"]:
|
||||
user.password_hash = hash_password(update_data.pop("password"))
|
||||
next_email = update_data.get("email")
|
||||
if next_email and next_email != user.email:
|
||||
existing = await db.scalar(select(User).where(User.email == next_email))
|
||||
if existing and existing.id != user.id:
|
||||
raise HTTPException(status_code=409, detail="Email already exists")
|
||||
if "password" in update_data:
|
||||
raw_password = update_data.pop("password")
|
||||
if raw_password:
|
||||
user.password_hash = hash_password(raw_password)
|
||||
for key, value in update_data.items():
|
||||
setattr(user, key, value)
|
||||
await db.commit()
|
||||
|
||||
@@ -2,7 +2,7 @@ from functools import lru_cache
|
||||
from pydantic import field_validator
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
NEXAPG_VERSION = "0.1.3"
|
||||
NEXAPG_VERSION = "0.1.4"
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
|
||||
@@ -9,6 +9,8 @@ class User(Base):
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
email: Mapped[str] = mapped_column(String(255), unique=True, index=True, nullable=False)
|
||||
first_name: Mapped[str | None] = mapped_column(String(120), nullable=True)
|
||||
last_name: Mapped[str | None] = mapped_column(String(120), nullable=True)
|
||||
password_hash: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
role: Mapped[str] = mapped_column(String(20), nullable=False, default="viewer")
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=False)
|
||||
|
||||
@@ -5,6 +5,8 @@ from pydantic import BaseModel, EmailStr, field_validator
|
||||
class UserOut(BaseModel):
|
||||
id: int
|
||||
email: EmailStr
|
||||
first_name: str | None = None
|
||||
last_name: str | None = None
|
||||
role: str
|
||||
created_at: datetime
|
||||
|
||||
@@ -13,12 +15,16 @@ class UserOut(BaseModel):
|
||||
|
||||
class UserCreate(BaseModel):
|
||||
email: EmailStr
|
||||
first_name: str | None = None
|
||||
last_name: str | None = None
|
||||
password: str
|
||||
role: str = "viewer"
|
||||
|
||||
|
||||
class UserUpdate(BaseModel):
|
||||
email: EmailStr | None = None
|
||||
first_name: str | None = None
|
||||
last_name: str | None = None
|
||||
password: str | None = None
|
||||
role: str | None = None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user