From 53827591ff7d977126d9d1944c5249aa9d5e9ea7 Mon Sep 17 00:00:00 2001 From: "posthog[bot]" <206114724+posthog[bot]@users.noreply.github.com> Date: Sun, 30 Aug 2026 06:17:54 +0000 Subject: [PATCH] fix(access-control): load roles page access controls after team loads The roles settings page fired its project-scoped resource_access_controls request in afterMount, before the team was loaded. currentProjectId then fell back to "@current", the request 404'd, and a "Load resource access controls failed. Not found." toast appeared with no access control content. Gate the load on a real project id: subscribe to currentTeam and fire the loader once the team is loaded, and guard the loader so it never sends "@current". Mirrors the pattern in pathCleaningSuggestionsLogic. Generated-By: PostHog Desktop Task-Id: c97d4903-0b6b-4852-974f-e3255cc46bbc --- .../access_control/roleAccessControlLogic.ts | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/frontend/src/layout/navigation-3000/sidepanel/panels/access_control/roleAccessControlLogic.ts b/frontend/src/layout/navigation-3000/sidepanel/panels/access_control/roleAccessControlLogic.ts index 30d69e2ca8bc..cfa640755efc 100644 --- a/frontend/src/layout/navigation-3000/sidepanel/panels/access_control/roleAccessControlLogic.ts +++ b/frontend/src/layout/navigation-3000/sidepanel/panels/access_control/roleAccessControlLogic.ts @@ -3,6 +3,7 @@ import { forms } from 'kea-forms' import type { DeepPartial, DeepPartialMap, FieldName, ValidationErrorType } from 'kea-forms' import { loaders } from 'kea-loaders' import { actionToUrl, router } from 'kea-router' +import { subscriptions } from 'kea-subscriptions' import { lemonToast } from '@posthog/lemon-ui' @@ -12,14 +13,14 @@ import { organizationLogic } from 'scenes/organizationLogic' import { teamLogic } from 'scenes/teamLogic' import { userLogic } from 'scenes/userLogic' -import { AccessControlResponseType, RoleType } from '~/types' +import { AccessControlResponseType, RoleType, TeamPublicType, TeamType } from '~/types' import type { AvailableFeature, OrganizationMemberType } from '../../../../../types' // Generated by kea-typegen. Update if you're an agent, ignore if you're human. export interface roleAccessControlLogicValues { sortedMembers: OrganizationMemberType[] | null // membersLogic - currentProjectId: number | string // teamLogic + currentTeam: TeamPublicType | TeamType | null // teamLogic hasAvailableFeature: (feature: AvailableFeature, currentUsage?: number | undefined) => boolean // userLogic canEditRoles: boolean | null editingRole: { @@ -125,10 +126,10 @@ export interface roleAccessControlLogicActions { errorObject?: any } loadResourceAccessControlsSuccess: ( - resourceAccessControls: AccessControlResponseType, + resourceAccessControls: AccessControlResponseType | null, payload?: any ) => { - resourceAccessControls: AccessControlResponseType + resourceAccessControls: AccessControlResponseType | null payload?: any } loadRoles: () => any @@ -249,7 +250,7 @@ export type roleAccessControlLogicType = MakeLogicType< export const roleAccessControlLogic = kea([ path(['scenes', 'accessControl', 'roleAccessControlLogic']), connect(() => ({ - values: [membersLogic, ['sortedMembers'], teamLogic, ['currentProjectId'], userLogic, ['hasAvailableFeature']], + values: [membersLogic, ['sortedMembers'], teamLogic, ['currentTeam'], userLogic, ['hasAvailableFeature']], actions: [membersLogic, ['ensureAllMembersLoaded'], organizationLogic, ['loadCurrentOrganization']], })), actions({ @@ -320,8 +321,13 @@ export const roleAccessControlLogic = kea([ null as AccessControlResponseType | null, { loadResourceAccessControls: async () => { + // This endpoint is project-scoped. On org-level settings pages no project sits in + // the URL, so wait for the team to load rather than sending "@current" and 404ing. + if (!values.currentTeam?.project_id) { + return values.resourceAccessControls + } const response = await api.get( - `api/projects/${values.currentProjectId}/resource_access_controls` + `api/projects/${values.currentTeam.project_id}/resource_access_controls` ) return response }, @@ -417,10 +423,19 @@ export const roleAccessControlLogic = kea([ }, })), + subscriptions(({ actions }) => ({ + // Fire the project-scoped load only once the team is really loaded. Doing it in afterMount + // races the team load and shows a "Not found" toast on org-level settings pages. + currentTeam: (currentTeam: TeamPublicType | TeamType | null) => { + if (currentTeam?.project_id) { + actions.loadResourceAccessControls() + } + }, + })), + afterMount(({ actions }) => { actions.loadRoles() actions.ensureAllMembersLoaded() - actions.loadResourceAccessControls() }), actionToUrl(({ values }) => ({