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 }) => ({