Merge pull request #3073 from appwrite/fix-hide-granular-project-access-flag

fix: hide granular project access behind flag
This commit is contained in:
Harsh Mahajan
2026-05-31 00:07:38 +05:30
committed by GitHub
5 changed files with 37 additions and 12 deletions
+2 -1
View File
@@ -19,5 +19,6 @@ function isFlagEnabled(name: string) {
}
export const flags = {
multiDb: isFlagEnabled('multi-db')
multiDb: isFlagEnabled('multi-db'),
granularProjectAccess: isFlagEnabled('granular-project-access')
};
@@ -11,6 +11,8 @@
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
import { isCloud, isSelfHosted } from '$lib/system';
import { roles, buildProjectRole } from '$lib/stores/billing';
import { flags } from '$lib/flags';
import { user } from '$lib/stores/user';
import InputSelect from '$lib/elements/forms/inputSelect.svelte';
import Roles from '$lib/components/roles/roles.svelte';
import { Icon, Popover, Layout } from '@appwrite.io/pink-svelte';
@@ -26,7 +28,11 @@
oncreated?: (team: Models.Membership) => void;
} = $props();
const supportsProjectRoles = $derived(isCloud && !!$currentPlan?.supportsOrganizationRoles);
const supportsProjectRoles = $derived(
isCloud &&
flags.granularProjectAccess({ account: $user, organization: $organization }) &&
!!$currentPlan?.supportsOrganizationRoles
);
let email = $state('');
let name = $state('');
@@ -20,8 +20,10 @@
} from '$lib/helpers/tooltipContent';
import { addNotification } from '$lib/stores/notifications';
import { currentPlan, newMemberModal, organization } from '$lib/stores/organization';
import { flags } from '$lib/flags';
import { isOwner } from '$lib/stores/roles';
import { sdk } from '$lib/stores/sdk';
import { user } from '$lib/stores/user';
import type { Models } from '@appwrite.io/console';
import Delete from '../deleteMember.svelte';
import Edit from './edit.svelte';
@@ -60,6 +62,10 @@
$: isLimited = limit !== 0 && limit < Infinity;
$: isButtonDisabled =
isCloud && (($readOnly && !GRACE_PERIOD_OVERRIDE) || (isLimited && memberCount >= limit));
$: supportsProjectRoles =
isCloud &&
flags.granularProjectAccess({ account: $user, organization: $organization }) &&
$currentPlan?.supportsOrganizationRoles;
const resend = async (member: Models.Membership) => {
try {
@@ -156,7 +162,7 @@
</Typography.Text>
</Table.Cell>
<Table.Cell column="roles" {root}>
{#if member.roles.some(isProjectSpecificRole)}
{#if supportsProjectRoles && member.roles.some(isProjectSpecificRole)}
{@const projectRoles = member.roles.filter(isProjectSpecificRole)}
{@const firstRole = projectRoles[0]}
{@const firstParsed = parseProjectRole(firstRole)}
@@ -217,7 +223,7 @@
</Button.Button>
<div style:min-width="232px" slot="tooltip">
<ActionMenu.Root>
{#if isCloud && $currentPlan?.supportsOrganizationRoles}
{#if supportsProjectRoles}
<ActionMenu.Item.Button
trailingIcon={IconPencil}
on:click={() => {
@@ -1,10 +1,12 @@
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
import { flags } from '$lib/flags';
import { getLimit, getPage, getSearch, pageToOffset } from '$lib/helpers/load';
import { sdk } from '$lib/stores/sdk';
import { Query } from '@appwrite.io/console';
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ url, params, route, depends }) => {
export const load: PageLoad = async ({ url, params, route, depends, parent }) => {
const { account, organization } = await parent();
depends(Dependencies.ORGANIZATION);
depends(Dependencies.MEMBERS);
@@ -13,18 +15,22 @@ export const load: PageLoad = async ({ url, params, route, depends }) => {
const limit = getLimit(url, route, PAGE_LIMIT);
const offset = pageToOffset(page, limit);
const supportsProjectRoles = flags.granularProjectAccess({ account, organization });
const [organizationMembers, orgProjects] = await Promise.all([
sdk.forConsole.teams.listMemberships({
teamId: params.organization,
queries: [Query.limit(limit), Query.offset(offset)],
search
}),
sdk.forConsole
.organization(params.organization)
.listProjects({
queries: [Query.limit(100), Query.equal('teamId', params.organization)]
})
.catch(() => null)
supportsProjectRoles
? sdk.forConsole
.organization(params.organization)
.listProjects({
queries: [Query.limit(100), Query.equal('teamId', params.organization)]
})
.catch(() => null)
: null
]);
return {
@@ -19,6 +19,8 @@
buildProjectRole
} from '$lib/stores/billing';
import { isCloud, isSelfHosted } from '$lib/system';
import { flags } from '$lib/flags';
import { user } from '$lib/stores/user';
import ProjectAccessSelector from '../projectAccessSelector.svelte';
let {
@@ -31,7 +33,11 @@
onupdated?: (membership: Models.Membership) => void;
} = $props();
const supportsProjectRoles = $derived(isCloud && !!$currentPlan?.supportsOrganizationRoles);
const supportsProjectRoles = $derived(
isCloud &&
flags.granularProjectAccess({ account: $user, organization: $organization }) &&
!!$currentPlan?.supportsOrganizationRoles
);
const defaultRole = isSelfHosted ? 'owner' : 'developer';
let error = $state<string>(null);