Skip to content

Commit

Permalink
Always query and show projects members
Browse files Browse the repository at this point in the history
This ensures our "middleware" can detect when the user was added to the project and stops hiding members on non-confidential projects
  • Loading branch information
myieye committed Nov 7, 2024
1 parent dea3463 commit b597b52
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
$: isEmpty = project?.lastCommit == null;
// TODO: Once we've stabilized the lastCommit issue with project reset, get rid of the next line
$: if (! $changesetStore.fetching) isEmpty = $changesetStore.changesets.length === 0;
$: members = project.users?.sort((a, b) => {
$: members = project.users.sort((a, b) => {
if (a.role !== b.role) {
return a.role === ProjectRole.Manager ? -1 : 1;
}
Expand Down Expand Up @@ -118,12 +118,12 @@
$: orgRoles = project.organizations
?.map((o) => user.orgs?.find((org) => org.orgId === o.id)?.role)
.filter(r => !!r) ?? [];
$: projectRole = project?.users?.find((u) => u.user.id == user.id)?.role;
$: projectRole = project?.users.find((u) => u.user.id == user.id)?.role;
// Mirrors PermissionService.CanViewProjectMembers() in C#
$: canViewProjectMembers = user.isAdmin
$: canViewOtherMembers = user.isAdmin
|| projectRole == ProjectRole.Manager
|| projectRole == ProjectRole.Editor && !project.isConfidential
|| projectRole && !project.isConfidential // public by default for members (non-members shouldn't even be here)
|| orgRoles.some(role => role === OrgRole.Admin);
let resetProjectModal: ResetProjectModal;
Expand Down Expand Up @@ -178,7 +178,7 @@
$: userId = user.id;
$: orgsManagedByUser = user.orgs.filter(o => o.role === OrgRole.Admin).map(o => o.orgId);
$: canManage = user.isAdmin || project?.users?.find((u) => u.user.id == userId)?.role == ProjectRole.Manager || !!project?.organizations?.find((o) => orgsManagedByUser.includes(o.id));
$: canManage = user.isAdmin || project?.users.find((u) => u.user.id == userId)?.role == ProjectRole.Manager || !!project?.organizations?.find((o) => orgsManagedByUser.includes(o.id));
const projectNameValidation = z.string().trim().min(1, $t('project_page.project_name_empty_error'));
Expand Down Expand Up @@ -486,37 +486,35 @@
{$t('project_page.confirm_remove_org', {orgName: orgToRemove})}
</DeleteModal>
</OrgList>
{#if members}
<MembersList
projectId={project.id}
{members}
canManageMember={(member) => canManage && (member.user?.id !== userId || user.isAdmin)}
canManageList={canManage}
canViewMembers={canViewProjectMembers}
on:openUserModal={(event) => userModal.open(event.detail.user)}
on:deleteProjectUser={(event) => deleteProjectUser(event.detail)}
<MembersList
projectId={project.id}
{members}
canManageMember={(member) => canManage && (member.user?.id !== userId || user.isAdmin)}
canManageList={canManage}
{canViewOtherMembers}
on:openUserModal={(event) => userModal.open(event.detail.user)}
on:deleteProjectUser={(event) => deleteProjectUser(event.detail)}
>
<svelte:fragment slot="extraButtons">
<BadgeButton variant="badge-success" icon="i-mdi-account-plus-outline" on:click={() => addProjectMember.openModal(undefined, undefined)}>
{$t('project_page.add_user.add_button')}
</BadgeButton>

<AddProjectMember bind:this={addProjectMember} projectId={project.id} />
<BulkAddProjectMembers projectId={project.id} />
</svelte:fragment>
<UserModal bind:this={userModal}/>

<DeleteModal
bind:this={removeUserModal}
entityName={$t('project_page.remove_project_user_title')}
isRemoveDialog
>
<svelte:fragment slot="extraButtons">
<BadgeButton variant="badge-success" icon="i-mdi-account-plus-outline" on:click={() => addProjectMember.openModal(undefined, undefined)}>
{$t('project_page.add_user.add_button')}
</BadgeButton>

<AddProjectMember bind:this={addProjectMember} projectId={project.id} />
<BulkAddProjectMembers projectId={project.id} />
</svelte:fragment>
<UserModal bind:this={userModal}/>

<DeleteModal
bind:this={removeUserModal}
entityName={$t('project_page.remove_project_user_title')}
isRemoveDialog
>
{$t('project_page.confirm_remove', {
userName: userToDelete?.user.name ?? '',
})}
</DeleteModal>
</MembersList>
{/if}
{$t('project_page.confirm_remove', {
userName: userToDelete?.user.name ?? '',
})}
</DeleteModal>
</MembersList>
<div class="divider" />
<div class="space-y-2">
<p class="text-2xl mb-4 flex gap-4 items-baseline">
Expand Down
57 changes: 26 additions & 31 deletions frontend/src/routes/(authenticated)/project/[project_code]/+page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ import type {
UpdateProjectLanguageListMutation,
UpdateProjectLexEntryCountMutation,
} from '$lib/gql/types';
import { getClient, graphql } from '$lib/gql';
import {getClient, graphql} from '$lib/gql';

import type { PageLoadEvent } from './$types';
import { derived } from 'svelte/store';
import { error } from '@sveltejs/kit';
import { tryMakeNonNullable } from '$lib/util/store';
import type {PageLoadEvent} from './$types';
import {derived} from 'svelte/store';
import {error} from '@sveltejs/kit';
import {tryMakeNonNullable} from '$lib/util/store';

export type Project = NonNullable<ProjectPageQuery['projectByCode']>;
export type ProjectUser = NonNullable<Project['users']>[number];
Expand All @@ -41,13 +41,10 @@ export async function load(event: PageLoadEvent) {
const client = getClient();
const user = (await event.parent()).user;
const projectCode = event.params.project_code;
const projectId = event.url.searchParams.get('id') ?? '';
//projectId is not required, so if it's not there we assume the user is a member, if we're wrong there will be an error
const userIsMember = projectId === '' ? true : (user.isAdmin || user.projects.some(p => p.projectId === projectId));
const projectResult = await client
.awaitedQueryStore(event.fetch,
graphql(`
query projectPage($projectCode: String!, $userIsAdmin: Boolean!, $userIsMember: Boolean!) {
query projectPage($projectCode: String!, $userIsAdmin: Boolean!) {
projectByCode(code: $projectCode) {
id
name
Expand All @@ -63,28 +60,26 @@ export async function load(event: PageLoadEvent) {
organizations {
id
}
... on Project @include(if: $userIsMember) {
users {
users {
id
role
user {
id
role
user {
id
name
... on User @include(if: $userIsAdmin) {
locked
username
createdDate
updatedDate
email
localizationCode
lastActive
canCreateProjects
isAdmin
emailVerified
createdBy {
id
name
}
name
... on User @include(if: $userIsAdmin) {
locked
username
createdDate
updatedDate
email
localizationCode
lastActive
canCreateProjects
isAdmin
emailVerified
createdBy {
id
name
}
}
}
Expand Down Expand Up @@ -112,7 +107,7 @@ export async function load(event: PageLoadEvent) {
}
}
`),
{ projectCode, userIsAdmin: user.isAdmin, userIsMember }
{ projectCode, userIsAdmin: user.isAdmin }
);
const changesetResultStore = client
.queryStore(event.fetch,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
export let canManageMember: (member: Member) => boolean;
export let canManageList: boolean;
export let projectId: string;
export let canViewMembers: boolean;
export let canViewOtherMembers: boolean;
const dispatch = createEventDispatcher<{
openUserModal: Member;
Expand Down Expand Up @@ -81,7 +81,7 @@
<div class="text-2xl mb-4 flex items-baseline gap-4 max-sm:flex-col">
<h2>
{$t('project_page.members.title')}
{#if !canViewMembers}
{#if !canViewOtherMembers}
<span
class="tooltip tooltip-warning text-warning shrink-0 leading-0"
data-tip={$t('project_page.members.membership_confidential')}>
Expand Down

0 comments on commit b597b52

Please sign in to comment.