Orgs¶
Purpose¶
The orgs app defines the multi-tenant foundation of the platform.
It is responsible for:
- modeling organizations (internal and customer)
- structuring organizations in a hierarchical tree
- managing user membership and roles within organizations
- separating internal workforce users from customer users
- enabling organization-level configuration and branding
- enforcing tenant isolation and access control boundaries
Every other domain (projects, servicereports, inventory, accounts, etc.) relies on orgs to determine who can access what within which organization.
Key concepts¶
Organization¶
A tenant in the system. Can be: - internal (your company structure) - customer (external client organization)
Organizations are arranged in a tree (MPTT): - parent → child inheritance - used for settings and branding fallback
OrgMembership¶
Defines a user’s role inside an internal organization.
Key roles:
- owner
- admin
- manager
- engineer
- viewer
This is the primary authorization layer across the backend.
CustomerMembership¶
Separate membership model for customer users.
Why separate? - avoids mixing internal roles with customer roles - enforces clean boundary between tenants
Roles:
- customer_admin
- customer_user
CustomerLink¶
Links an internal org to a customer org.
Used for: - portal access - controlled cross-tenant visibility - project/customer sharing
Org-scoped requests¶
Most APIs rely on a current organization context (typically via headers):
X-ORG-IDX-ORG-SLUG
This ensures: - correct tenant isolation - consistent permission checks
Effective settings & branding¶
Organizations support inherited configuration:
- parent org defines defaults
- child org overrides selectively
Used for: - branding (logos, colors) - document generation (PDF identity) - feature flags or org-level config
Entry points¶
URLs¶
Main endpoints include:
/orgs/me/→ list user organizations/orgs/members/→ members of current org
Future endpoints may include: - org detail/update - membership management - customer linking APIs
Admin¶
Django admin is typically used for:
- managing organizations and hierarchy
- correcting memberships
- inspecting historical changes (via
simple_history)
Tasks¶
Currently:
- no dedicated Celery tasks in orgs
(Tasks exist in accounts, e.g. invites/emails)
Signals¶
No explicit signals in this app currently.
(Unlike accounts, which auto-creates profile/settings/schedule)
Dependencies¶
Depends on¶
accounts→ user modelcore→ permissions (e.g.HasCurrentOrg)django-mptt→ tree structuredjango-simple-history→ audit tracking
Used by¶
projects→ org-scoped projectsservicereports→ org-scoped reportsinventory→ org-scoped stockteams→ org-based groupingaccounts→ membership + access controlportal→ customer org access
The orgs app is a central dependency for almost all backend domains.
Operational notes¶
Known pitfalls¶
1. Missing org context¶
Many endpoints require a current org.
If headers are missing:
- requests may fail with 403 or 400
- or behave unpredictably
2. Role vs permission confusion¶
Permissions are role-based, not user-based.
Avoid:
- hardcoding user checks
- bypassing OrgMembership
Always: - resolve permissions via membership role
3. Owner safety constraints¶
Certain operations must never leave an org without an owner.
Examples: - demoting the last owner - deactivating the last owner
These rules must always be enforced in services.
4. Internal vs customer separation¶
Never mix:
- OrgMembership (internal)
- CustomerMembership (external)
This is a critical security boundary.
5. Tree inheritance complexity¶
Settings and branding are inherited:
- debugging issues may require checking parent orgs
- overrides may not behave as expected if hierarchy is deep
Performance considerations¶
1. Membership queries¶
Common pattern:
Should be: • indexed • often prefetched when used in bulk
2. Organization tree queries¶
MPTT operations: • get_ancestors() • get_descendants()
Can be expensive if misused.
3. Branding resolution¶
effective_branding() merges: • model fields • inherited JSON settings
Avoid calling this repeatedly in loops without caching.
4. Member listing¶
Endpoints like: • /orgs/members/
Should use: • select_related("user")
to avoid N+1 queries.
Architecture overview¶
flowchart TD
User["User"]
Org["Organization"]
OrgMembership["OrgMembership"]
CustomerMembership["CustomerMembership"]
CustomerLink["CustomerLink"]
User --> OrgMembership
OrgMembership --> Org
User --> CustomerMembership
CustomerMembership --> Org
Org --> CustomerLink
CustomerLink --> Org
Org --> Org
¶
flowchart TD
User["User"]
Org["Organization"]
OrgMembership["OrgMembership"]
CustomerMembership["CustomerMembership"]
CustomerLink["CustomerLink"]
User --> OrgMembership
OrgMembership --> Org
User --> CustomerMembership
CustomerMembership --> Org
Org --> CustomerLink
CustomerLink --> Org
Org --> Org
Summary¶
The orgs app is the backbone of tenancy and authorization.
It ensures: • users belong to the correct organizations • roles are enforced consistently • data stays isolated per tenant • customer access is controlled and explicit
If orgs breaks, everything breaks — which is why: • services are strongly tested • permissions are centralized • role logic is carefully enforced