Skip to content

Add Unix username field#15

Merged
CannonLock merged 8 commits into
mainfrom
unix-username
May 13, 2026
Merged

Add Unix username field#15
CannonLock merged 8 commits into
mainfrom
unix-username

Conversation

@fallow64
Copy link
Copy Markdown
Contributor

@fallow64 fallow64 commented Apr 27, 2026

Adds username to the user table and related user/project views and schemas.

For active users, netid is required, and username defaults to netid if omitted. Existing active users are backfilled the same way, with the exceptions found in the migration script.

Resolves CHTC/chtc-user-ui#57

@fallow64 fallow64 marked this pull request as ready for review April 27, 2026 20:30
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new username field intended to represent a Unix username alongside netid, and updates API schemas/views/tests to expose it while preserving legacy “auth_*” compatibility fields.

Changes:

  • Adds username to the users table and to the joined_projects DB view (with an Alembic migration to backfill existing rows).
  • Updates Pydantic schemas (UserGet, UserPost, UserPatch, JoinedProjectView) to include username and recompute auth_netid / auth_username based on username vs netid.
  • Updates/reshapes user API tests and test payload generation to include the new field and validate the new compatibility behavior.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
userapp/core/schemas/users.py Adds username to user schemas and updates computed auth compatibility fields / POST validation.
userapp/core/schemas/general.py Adds username to JoinedProjectView schema and updates computed auth compatibility fields.
userapp/core/models/views.py Extends the SQLAlchemy view model to include username.
userapp/core/models/tables.py Adds username column (unique) to the User table model.
userapp/api/tests/test_users.py Updates user endpoint tests and adds schema/auth behavior tests for username vs netid.
userapp/api/tests/test_users_active_field.py Removes redundant/older active/auth compatibility tests.
userapp/api/tests/test_user_schemas_active.py Removes redundant/older schema active/auth computed field tests.
userapp/api/tests/fake_data.py Extends test user payload factory to support username.
userapp/api/routes/users.py Minor formatting-only change in the update route.
userapp/api/routes/security.py Sets username when auto-creating users via OIDC.
alembic/versions/47f8adc9859b_add_unix_username_field.py Migration to add/backfill username, add unique constraint, and recreate joined_projects view with username.
Comments suppressed due to low confidence (1)

userapp/core/schemas/users.py:105

  • PR description/tests expect that when creating an active user with username omitted, username defaults to netid. Currently the UserPost validator only enforces netid presence and never sets a default for username, so /users POST will persist username=NULL when omitted. Add validation/defaulting (e.g., set username = netid when active is True and username is not provided) to match the intended behavior.
class UserPost(BaseModel):

    model_config = ConfigDict(extra='ignore')

    name: str
    username: Optional[str] = Field(default=None)
    email1: Optional[EmailStr] = Field(default=None)
    email2: Optional[EmailStr] = Field(default=None)
    netid: Optional[str] = Field(default=None)
    netid_exp_datetime: Optional[datetime] = Field(default=None)
    phone1: Optional[str] = Field(default=None)
    phone2: Optional[str] = Field(default=None)
    is_admin: Optional[bool] = Field(default=None)
    active: Optional[bool] = Field(default=None)
    unix_uid: Optional[int] = Field(default=None)
    position: Optional[PositionEnum] = Field(default=None)

    @field_serializer('position')
    def serialize_position(self, position: PositionEnum) -> str:
        return position.name if position is not None else None

    @model_validator(mode="after")
    def check_active_requires_netid(self):
        if self.active and not self.netid:
            raise ValueError("If active is True, netid must be provided.")
        return self


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread userapp/core/schemas/users.py Outdated
Comment thread userapp/core/schemas/users.py Outdated
Comment thread userapp/core/schemas/general.py Outdated
@CannonLock CannonLock merged commit db4f786 into main May 13, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Adding controllable Username

3 participants