mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-14 17:43:04 +00:00
Memoize access reads per req, cache portfolio index, trim chip revalidates, and shrink RSC payload via catalog-backed labels.
118 lines
3.6 KiB
TypeScript
118 lines
3.6 KiB
TypeScript
// ---------------------------------------------------------------------------
|
|
// Contacts
|
|
// ---------------------------------------------------------------------------
|
|
|
|
import type { Access, PayloadRequest } from 'payload'
|
|
|
|
import { getAccessibleMunicipalityIds } from '@/utilities/access/municipalities'
|
|
import type { CampaignActor, DynamicFind } from '@/utilities/access/shared'
|
|
import {
|
|
getFreshCampaignUser,
|
|
isCampaignUnrestricted,
|
|
isCampaignUser,
|
|
isPayloadAdmin,
|
|
memoizePerRequest,
|
|
} from '@/utilities/access/shared'
|
|
import { relationshipId } from '@/utilities/relationship'
|
|
|
|
type ContactID = number
|
|
|
|
const ACCESSIBLE_CONTACT_IDS_MEMO_KEY = 'campaignAccessibleContactIds'
|
|
|
|
const getAccessibleContactIds = async (
|
|
req: PayloadRequest,
|
|
user: CampaignActor = req.user,
|
|
): Promise<ContactID[]> => {
|
|
const currentUser =
|
|
isCampaignUser(user) && user === req.user ? await getFreshCampaignUser(req, user) : user
|
|
|
|
if (!isCampaignUser(currentUser)) return []
|
|
|
|
return memoizePerRequest(
|
|
req,
|
|
`${ACCESSIBLE_CONTACT_IDS_MEMO_KEY}:${currentUser.id}:${currentUser.role}`,
|
|
async () => {
|
|
const municipalityIDs = await getAccessibleMunicipalityIds(req, currentUser)
|
|
const leadershipWhere =
|
|
currentUser.role === 'leader'
|
|
? {
|
|
and: [
|
|
{ user: { equals: currentUser.id } },
|
|
{ supportStatus: { equals: 'engajado' } },
|
|
],
|
|
}
|
|
: {
|
|
municipalities: {
|
|
in: municipalityIDs ?? [],
|
|
},
|
|
}
|
|
|
|
const find = req.payload.find.bind(req.payload) as unknown as DynamicFind
|
|
const collections = req.payload.collections as Record<string, unknown>
|
|
const contactIDs: ContactID[] = []
|
|
|
|
if (collections.leadership) {
|
|
const leadershipResult = await find({
|
|
collection: 'leadership',
|
|
depth: 0,
|
|
limit: 0,
|
|
overrideAccess: true,
|
|
pagination: false,
|
|
req,
|
|
select: { contact: true },
|
|
where: leadershipWhere,
|
|
})
|
|
for (const doc of leadershipResult.docs) {
|
|
const id = relationshipId(doc.contact)
|
|
if (id !== null) contactIDs.push(id)
|
|
}
|
|
}
|
|
|
|
// Advisors read contacts of supporters in their municipalities; leaders read
|
|
// contacts of the supporters they created — mirroring `canReadSupporter`.
|
|
const supporterWhere =
|
|
currentUser.role === 'advisor'
|
|
? { municipality: { in: municipalityIDs ?? [] } }
|
|
: currentUser.role === 'leader'
|
|
? { createdBy: { equals: currentUser.id } }
|
|
: null
|
|
|
|
if (supporterWhere && collections.supporter) {
|
|
const supporterResult = await find({
|
|
collection: 'supporter',
|
|
depth: 0,
|
|
limit: 0,
|
|
overrideAccess: true,
|
|
pagination: false,
|
|
req,
|
|
select: { contact: true },
|
|
where: supporterWhere,
|
|
})
|
|
for (const doc of supporterResult.docs) {
|
|
const id = relationshipId(doc.contact)
|
|
if (id !== null) contactIDs.push(id)
|
|
}
|
|
}
|
|
|
|
return [...new Set(contactIDs)]
|
|
},
|
|
)
|
|
}
|
|
|
|
export const canReadContacts: Access = async ({ req }) => {
|
|
if (isPayloadAdmin(req.user)) return true
|
|
|
|
const currentUser = await getFreshCampaignUser(req)
|
|
if (isCampaignUnrestricted(currentUser)) return true
|
|
if (!currentUser) return false
|
|
|
|
const ids = await getAccessibleContactIds(req, currentUser)
|
|
|
|
return {
|
|
id: {
|
|
in: ids,
|
|
},
|
|
}
|
|
}
|
|
|
|
export const canManageContacts: Access = ({ req }) => isPayloadAdmin(req.user)
|