Skip to content

Accounts

Purpose

The accounts app is the identity, access, and workforce core of the system.

It is responsible for:

  • authenticating users (login, logout, password flows)
  • managing user sessions and devices
  • modeling workforce profiles (skills, schedules, availability context)
  • handling organization onboarding via invites
  • storing user preferences and settings

This app acts as the foundation layer that all other apps depend on (projects, servicereports, planning, inventory, etc.).


Key concepts

User (identity)

The central authenticated entity.

  • based on a custom User model
  • extended via:
  • UserProfile (human/workforce data)
  • UserSettings (UI + preferences)
  • UserWorkSchedule (availability logic)

Organization membership (external dependency)

Permissions are not defined here, but:

  • accounts integrates with org roles via:
  • OrgMembership
  • CustomerMembership

This means: - authorization = role-based (orgs app) - identity & profile = accounts app


Device & session model

Supports mobile/web authentication flows.

  • Device = physical/logical client (phone, browser)
  • DeviceSession = refresh token session bound to a device

Enables: - multi-device login - session revocation - push notification targeting


Workforce profile

Operational user data used across the system.

  • profile (bio, department, location, etc.)
  • work schedule (days, hours, breaks)
  • skills (capabilities + certifications)

Used heavily in: - planning - assignments - service reports


Invite system

Handles onboarding into the platform.

Supports: - internal users (org members) - customer users (portal access)

Lifecycle: - create → send → preview → accept → membership created


Service layer architecture

Business logic is intentionally moved into:

  • accounts/services/auth.py
  • accounts/services/invite.py

This ensures: - thin views - testable logic - reusable workflows


Entry points

URLs (API)

Main endpoints exposed by the app:

  • /auth/*
  • login
  • logout
  • logout-all
  • password flows
  • device/session management

  • /me/*

  • current user
  • profile update
  • settings update
  • notification preferences
  • work schedule

  • /accounts/skills/*

  • skill directory
  • user skill assignment

  • /accounts/invites/*

  • create invite
  • preview invite
  • accept invite

  • /bootstrap/

  • initial app load (user + orgs + teams)

Admin

Django admin provides:

  • user management (extended with skills inline)
  • skill directory management
  • user-skill relationships

Used mainly for: - internal support - debugging - quick data fixes


Tasks (Celery)

Asynchronous operations:

  • send_invite_email
  • send_password_reset_email

Responsibilities: - offload email sending - prevent request blocking - allow retries and resilience


Signals

Automatic creation of related models on user creation:

  • UserProfile
  • UserSettings
  • UserWorkSchedule
  • 7 UserWorkDay rows

Guarantees: - frontend always receives a complete user structure - no need for defensive checks in API


Dependencies

Depends on:

  • orgs
  • organization model
  • org memberships (permissions)
  • teams
  • team memberships
  • core
  • shared permissions (e.g. HasCurrentOrg)
  • rest_framework
  • API layer
  • simplejwt
  • authentication tokens

Used by:

  • projects
  • servicereports
  • inventory
  • planning (future)
  • any module that needs:
  • user identity
  • skills
  • availability
  • org-scoped access

Operational notes

Known pitfalls

1. Org context is required

Many endpoints depend on:

  • X-ORG-ID header
  • request-scoped org resolution

Missing this results in: - 403 / 400 errors


2. Signals must remain idempotent

User creation signals must:

  • never create duplicates
  • always ensure 7 workdays exist

Breaking this causes: - frontend crashes - inconsistent schedule payloads


3. Token/session consistency

When working with sessions:

  • always blacklist refresh tokens when revoking
  • always sync DeviceSession.revoked_at

Otherwise: - ghost sessions remain valid


4. Invite lifecycle integrity

Invite states must be respected:

  • cannot accept expired invites
  • cannot reuse accepted invites
  • cannot resend cancelled invites

This logic lives in the service layer — not views.


Performance considerations

1. Device/session queries

  • use select_related / prefetch_related
  • avoid N+1 when listing devices + sessions

2. Skills & user skills

  • indexed fields:
  • skill
  • user
  • category
  • safe for filtering/searching

3. Work schedule calculations

  • derived_weekly_hours loops over days
  • lightweight but should not be recomputed excessively in bulk queries

4. Invite queries

  • indexed on:
  • email
  • token
  • optimized for lookup and validation

High-level architecture

flowchart TD
    User["User"]

    Profile["UserProfile"]
    Settings["UserSettings"]
    Schedule["UserWorkSchedule"]
    WorkDays["UserWorkDay"]
    Skills["UserSkill"]
    Skill["Skill"]

    Device["Device"]
    Session["DeviceSession"]

    Invite["Invite"]

    OrgMembership["OrgMembership"]
    CustomerMembership["CustomerMembership"]

    User --> Profile
    User --> Settings
    User --> Schedule
    Schedule --> WorkDays

    User --> Skills
    Skills --> Skill

    User --> Device
    Device --> Session

    Invite --> User
    Invite --> OrgMembership
    Invite --> CustomerMembership

Design philosophy

The accounts app follows a clear structure: • Models → represent state • Serializers → validate input/output • Services → contain business logic • Views → orchestrate requests • Tasks → handle async work • Tests → protect every layer

This separation ensures the app remains: • scalable • testable • maintainable

as the system grows.