mirror of
https://github.com/supabase/supabase.git
synced 2026-05-11 19:29:04 -04:00
4a0bb36ca8
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
110 lines
3.7 KiB
TypeScript
110 lines
3.7 KiB
TypeScript
import type {
|
|
OrganizationRole,
|
|
OrganizationRolesResponse,
|
|
} from '@/data/organization-members/organization-roles-query'
|
|
import type { OrganizationMember } from '@/data/organizations/organization-members-query'
|
|
|
|
export interface ProjectAccessMember {
|
|
id: string
|
|
displayName?: string
|
|
email: string
|
|
role?: string
|
|
}
|
|
|
|
interface SummarizeProjectAccessParams {
|
|
organizationMembers: OrganizationMember[]
|
|
roles: OrganizationRolesResponse | undefined
|
|
projectRef?: string
|
|
hasLimitedVisibility: boolean
|
|
currentUserId?: string
|
|
maxVisibleMembers?: number
|
|
}
|
|
|
|
export interface ProjectAccessSummary {
|
|
projectMembers: ProjectAccessMember[]
|
|
visibleMembers: ProjectAccessMember[]
|
|
hiddenMembersCount: number
|
|
projectMemberCount: number
|
|
organizationMemberCount: number
|
|
shouldShowOrgComparison: boolean
|
|
hasOrganizationWideAccess: boolean
|
|
}
|
|
|
|
const getRoleDisplayName = (roleName: string | undefined) => {
|
|
if (!roleName) return undefined
|
|
return roleName.split('_')[0]
|
|
}
|
|
|
|
const roleAppliesToProject = (role: OrganizationRole | undefined, projectRef?: string) => {
|
|
if (!role) return false
|
|
if (role.projects.length === 0) return true
|
|
if (!projectRef) return false
|
|
return role.projects.some((project) => project.ref === projectRef)
|
|
}
|
|
|
|
export const summarizeProjectAccess = ({
|
|
organizationMembers,
|
|
roles,
|
|
projectRef,
|
|
hasLimitedVisibility,
|
|
currentUserId,
|
|
maxVisibleMembers = 12,
|
|
}: SummarizeProjectAccessParams): ProjectAccessSummary => {
|
|
const allRoles = [...(roles?.org_scoped_roles ?? []), ...(roles?.project_scoped_roles ?? [])]
|
|
const rolesById = new Map(allRoles.map((role) => [role.id, role]))
|
|
|
|
const normalizedMembers = organizationMembers.filter(
|
|
(member) => !member.invited_id && typeof member.gotrue_id === 'string' && !!member.primary_email
|
|
)
|
|
|
|
const membersWithProjectAccess = normalizedMembers
|
|
.filter((member) =>
|
|
member.role_ids.some((roleId) => roleAppliesToProject(rolesById.get(roleId), projectRef))
|
|
)
|
|
.sort((a, b) => {
|
|
const isCurrentUserA = !!currentUserId && a.gotrue_id === currentUserId
|
|
const isCurrentUserB = !!currentUserId && b.gotrue_id === currentUserId
|
|
|
|
if (isCurrentUserA && !isCurrentUserB) return -1
|
|
if (!isCurrentUserA && isCurrentUserB) return 1
|
|
return (a.primary_email ?? '').localeCompare(b.primary_email ?? '')
|
|
})
|
|
|
|
const projectMembers = membersWithProjectAccess.map((member) => {
|
|
const matchingRoleNames = member.role_ids
|
|
.map((roleId) => rolesById.get(roleId))
|
|
.filter((role) => roleAppliesToProject(role, projectRef))
|
|
.map((role) => getRoleDisplayName(role?.name))
|
|
.filter((name): name is string => typeof name === 'string' && name.length > 0)
|
|
|
|
const uniqueRoleNames = [...new Set(matchingRoleNames)]
|
|
const hasDisplayName =
|
|
typeof member.username === 'string' &&
|
|
typeof member.primary_email === 'string' &&
|
|
member.username !== member.primary_email
|
|
|
|
return {
|
|
id: member.gotrue_id as string,
|
|
displayName: hasDisplayName ? member.username : undefined,
|
|
email: member.primary_email as string,
|
|
role: uniqueRoleNames.length > 0 ? uniqueRoleNames.join(', ') : undefined,
|
|
}
|
|
})
|
|
|
|
const projectMemberCount = projectMembers.length
|
|
const organizationMemberCount = normalizedMembers.length
|
|
const shouldShowOrgComparison = !hasLimitedVisibility && organizationMemberCount > 0
|
|
const hasOrganizationWideAccess =
|
|
shouldShowOrgComparison && projectMemberCount === organizationMemberCount
|
|
|
|
return {
|
|
projectMembers,
|
|
visibleMembers: projectMembers.slice(0, maxVisibleMembers),
|
|
hiddenMembersCount: Math.max(projectMemberCount - maxVisibleMembers, 0),
|
|
projectMemberCount,
|
|
organizationMemberCount,
|
|
shouldShowOrgComparison,
|
|
hasOrganizationWideAccess,
|
|
}
|
|
}
|