Files
Kristaps Fabians Geikins 4b06f42db7 chore(server): run TS files directly (no compilation) (#5134)
* sort of works

* type fixes

* added option to run old way too
2025-07-23 11:20:40 +02:00

122 lines
3.7 KiB
TypeScript

import type {
AddOrUpdateStreamCollaborator,
GetStream
} from '@/modules/core/domain/streams/operations'
import { StreamInvalidAccessError } from '@/modules/core/errors/stream'
import { isResourceAllowed } from '@/modules/core/helpers/token'
import { ProjectInviteResourceType } from '@/modules/serverinvites/domain/constants'
import { InviteFinalizingError } from '@/modules/serverinvites/errors'
import type {
ProcessFinalizedResourceInvite,
ValidateResourceInviteBeforeFinalization
} from '@/modules/serverinvites/services/operations'
import { InviteFinalizationAction } from '@/modules/serverinvites/services/operations'
import { Roles } from '@speckle/shared'
type ValidateProjectInviteBeforeFinalizationFactoryDeps = {
getProject: GetStream
}
export const validateProjectInviteBeforeFinalizationFactory =
(
deps: ValidateProjectInviteBeforeFinalizationFactoryDeps
): ValidateResourceInviteBeforeFinalization =>
async (params) => {
const { getProject } = deps
const { invite, finalizerUserId, action, finalizerResourceAccessLimits } = params
if (invite.resource.resourceType !== ProjectInviteResourceType) {
throw new InviteFinalizingError(
'Attempting to finalize non-project invite as project invite',
{ info: { invite, finalizerUserId } }
)
}
// If decline, skip all further validation
if (action === InviteFinalizationAction.DECLINE) {
return
}
const project = await getProject({
streamId: invite.resource.resourceId,
userId: finalizerUserId
})
if (!project) {
throw new InviteFinalizingError(
'Attempting to finalize invite to a non-existant project'
)
}
if (action === InviteFinalizationAction.CANCEL) {
if (project.role !== Roles.Stream.Owner) {
throw new InviteFinalizingError(
'Attempting to cancel invite to a project that the user does not own'
)
}
} else {
if (project.role) {
throw new InviteFinalizingError(
'Attempting to finalize invite to a project that the user already has access to'
)
}
}
if (
!isResourceAllowed({
resourceId: project.id,
resourceType: 'project',
resourceAccessRules: finalizerResourceAccessLimits
})
) {
throw new InviteFinalizingError(
'You are not allowed to process an invite for this project'
)
}
}
type ProcessFinalizedProjectInviteFactoryDeps = {
getProject: GetStream
addProjectRole: AddOrUpdateStreamCollaborator
}
export const processFinalizedProjectInviteFactory =
(deps: ProcessFinalizedProjectInviteFactoryDeps): ProcessFinalizedResourceInvite =>
async (params) => {
const { getProject, addProjectRole } = deps
const { invite, finalizerUserId, action } = params
const project = await getProject({ streamId: invite.resource.resourceId })
if (action === InviteFinalizationAction.DECLINE) {
// Skip validation so user can get rid of the invite regardless
return
}
if (!project) {
throw new InviteFinalizingError(
'Attempting to finalize invite to a non-existant project'
)
}
if (action === InviteFinalizationAction.ACCEPT) {
try {
await addProjectRole(
project.id,
finalizerUserId,
invite.resource.role || Roles.Stream.Contributor,
invite.inviterId,
null,
{ fromInvite: invite }
)
} catch (e) {
if (!(e instanceof StreamInvalidAccessError)) {
throw e
}
throw new InviteFinalizingError(
'Original inviter no longer has the rights to invite you to this project'
)
}
}
}