Orgs continuation #34
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/org-sections"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Backend - create_section / list_sections in gear-core. Sections are auto-active, one level deep, and refuse `approve` / `reject`. - Section creation gated on `is_admin OR parent.requested_by == actor` — a placeholder OrgAdmin check until memberships land. - HTTP: GET/POST /api/organizations/{id}/sections. Tauri commands mirror the pair. Frontend - gear-client: CreateSectionRequest + listOrganizationSections + createOrganizationSection on both transports. - OrganizationsAdminView renders sections indented under each active org; an "Add section" button opens a dialog (name / kind / description). EN + FR strings. Tests - 5 new gear-http integration tests (requester creates section, stranger denied, no nesting, approve refuses sections, list returns children only). - 2 new gear-web specs (indent rendering, create-section dialog wiring).Backend - New Membership { org_id, user_id, role: Member|Manager|OrgAdmin, joined_at } entity + migration m0010, indexed on org_id / user_id with a partial unique index that only covers active rows so re-joining after a leave stays possible. - Service ops: join / set_role / remove / list_by_org / list_by_user + is_org_admin helper. - Organization approve seeds the requester as OrgAdmin of the freshly-active org, idempotent under re-approval. - Section create / update gates dropped the `requested_by(parent)` placeholder — they now consult the real OrgAdmin membership. Root read gate accepts members alongside admin + requester. HTTP + Tauri - GET/POST /api/organizations/{id}/members (enriched view: user displayName + email). - PUT/DELETE /api/memberships/{id}, GET /api/me/memberships. - Tauri commands mirror the same surface. Frontend - gear-client types + methods on both transports. - "Members" dialog on active orgs in both /organizations (requester-side) and /admin/organizations (instance-admin side): list + add-by-email + change-role + remove. - New "Other affiliations" card on /organizations listing orgs the user is a member of but did not request. - EN + FR translations. Tests - 4 gear-http integration tests on /api/organizations/{id}/members and the section-gate switch (approve seeds OrgAdmin, add/remove by email, stranger denied, section create refused for a Member).Backend - MembershipStatus (pending | active) on Membership. Migration m0011 adds the column with default 'active' so slice-5 rows stay unaffected. - Service split: join() keeps the admin path (auto-active), request_join() creates a pending row. - POST /api/organizations/{id}/join for user-initiated requests (rejected on non-active orgs), POST /api/memberships/{id}/approve for OrgAdmin / instance-admin activation. - is_org_admin + is_active_member now filter on status = active. A pending row grants no read access nor management power. Frontend - Directory: per-row Join button on active orgs, replaced by a Pending / Member chip once the caller has a row on the org. - Members dialog (both user and admin views): dedicated "Pending join requests" section at the top with Approve / reject actions. - Affiliations card on /organizations shows a Pending chip alongside the role. - EN + FR strings. Tests - 2 new gear-http integration tests: request → approve flow (with read-gate flip), rejection of a join on a non-active org.Backend - Equipment.org_id: Option<EntityId> in gear-core, migration m0012 adds a nullable BLOB column with an idx_equipment_org_id index. Existing rows stay personal (NULL). - Service create/update refuse to pin equipment to an org the actor is not an active member of. - list_visible unions the caller's owned equipment with every piece belonging to orgs they actively belong to. - GET /api/equipments/{id} accepts an active org member without a ShareGrant; RBAC still covers personal + individually-shared rows. Frontend - New useOrgContext Pinia store (persisted localStorage): `active: 'personal' | orgId`, cached list of active orgs, `reset()` on logout, auto-falls back to personal if the persisted org is no longer accessible. - App-bar dropdown switches context globally (icon + label follow the selection). MainLayout refreshes the cache on mount and whenever isAuthenticated flips. - EquipmentView drops its local per-page filter, reads orgContext.activeOrgId for filtering, and defaults the create form's orgId to the current context. - EN + FR strings. Tests - New gear-http integration test: org-scoped equipment is only listable/gettable by active members (non-members get an empty list + 403 on the id). - Existing suites keep passing (148 vitest, 8 equipment integration tests).