diff --git a/packages/server/modules/accessrequests/domain/operations.ts b/packages/server/modules/accessrequests/domain/operations.ts index 32b573666..d279b947b 100644 --- a/packages/server/modules/accessrequests/domain/operations.ts +++ b/packages/server/modules/accessrequests/domain/operations.ts @@ -32,6 +32,13 @@ export type GetPendingAccessRequests = ( resourceId: string ) => Promise[]> +export type GetPendingAccessRequest = ( + requestId: string, + resourceType?: T +) => Promise>> + +export type DeleteRequestById = (requestId: string) => Promise + export type GetUserProjectAccessRequest = ( userId: string, projectId: string diff --git a/packages/server/modules/accessrequests/graph/resolvers/index.ts b/packages/server/modules/accessrequests/graph/resolvers/index.ts index 43e09bb52..64449caec 100644 --- a/packages/server/modules/accessrequests/graph/resolvers/index.ts +++ b/packages/server/modules/accessrequests/graph/resolvers/index.ts @@ -3,6 +3,8 @@ import { AccessRequestsEmitter } from '@/modules/accessrequests/events/emitter' import { AccessRequestType, createNewRequestFactory, + deleteRequestByIdFactory, + getPendingAccessRequestFactory, getPendingAccessRequestsFactory, getUsersPendingAccessRequestFactory } from '@/modules/accessrequests/repositories' @@ -11,8 +13,7 @@ import { getPendingStreamRequestsFactory, getUserProjectAccessRequestFactory, getUserStreamAccessRequestFactory, - processPendingProjectRequest, - processPendingStreamRequest, + processPendingStreamRequestFactory, requestProjectAccessFactory, requestStreamAccessFactory } from '@/modules/accessrequests/services/stream' @@ -20,7 +21,10 @@ import { Resolvers } from '@/modules/core/graph/generated/graphql' import { mapStreamRoleToValue } from '@/modules/core/helpers/graphTypes' import { Roles } from '@/modules/core/helpers/mainConstants' import { getStream } from '@/modules/core/repositories/streams' -import { validateStreamAccess } from '@/modules/core/services/streams/streamAccessService' +import { + addOrUpdateStreamCollaborator, + validateStreamAccess +} from '@/modules/core/services/streams/streamAccessService' import { LogicError } from '@/modules/shared/errors' const getUserProjectAccessRequest = getUserProjectAccessRequestFactory({ @@ -50,6 +54,16 @@ const getPendingStreamRequests = getPendingStreamRequestsFactory({ getPendingProjectRequests }) +const processPendingStreamRequest = processPendingStreamRequestFactory({ + getPendingAccessRequest: getPendingAccessRequestFactory({ db }), + validateStreamAccess, + addOrUpdateStreamCollaborator, + deleteRequestById: deleteRequestByIdFactory({ db }), + accessRequestsEmitter: AccessRequestsEmitter.emit +}) + +const processPendingProjectRequest = processPendingStreamRequest + const resolvers: Resolvers = { Mutation: { async streamAccessRequestUse(_parent, args, ctx) { diff --git a/packages/server/modules/accessrequests/repositories/index.ts b/packages/server/modules/accessrequests/repositories/index.ts index 6ca96527d..e9426bc10 100644 --- a/packages/server/modules/accessrequests/repositories/index.ts +++ b/packages/server/modules/accessrequests/repositories/index.ts @@ -1,6 +1,8 @@ import { AccessRecordInput, CreateNewRequest, + DeleteRequestById, + GetPendingAccessRequest, GetPendingAccessRequests, GetUsersPendingAccessRequest } from '@/modules/accessrequests/domain/operations' @@ -85,7 +87,7 @@ export const getPendingAccessRequestsFactory = } export const getPendingAccessRequestFactory = - (deps: { db: Knex }) => + (deps: { db: Knex }): GetPendingAccessRequest => async ( requestId: string, resourceType?: T @@ -102,7 +104,8 @@ export const getPendingAccessRequestFactory = } export const deleteRequestByIdFactory = - (deps: { db: Knex }) => async (requestId: string) => { + (deps: { db: Knex }): DeleteRequestById => + async (requestId: string) => { if (!requestId) { throw new InvalidArgumentError('Request ID missing') } diff --git a/packages/server/modules/accessrequests/services/stream.ts b/packages/server/modules/accessrequests/services/stream.ts index 891080f61..6ab55757a 100644 --- a/packages/server/modules/accessrequests/services/stream.ts +++ b/packages/server/modules/accessrequests/services/stream.ts @@ -6,9 +6,7 @@ import { AccessRequestsEmitter } from '@/modules/accessrequests/events/emitter' import { StreamAccessRequestGraphQLReturn } from '@/modules/accessrequests/helpers/graphTypes' import { AccessRequestType, - deleteRequestByIdFactory, generateId, - getPendingAccessRequestFactory, ServerAccessRequestRecord, StreamAccessRequestRecord } from '@/modules/accessrequests/repositories' @@ -21,10 +19,15 @@ import { validateStreamAccess } from '@/modules/core/services/streams/streamAccessService' import { ensureError } from '@/modules/shared/helpers/errorHelper' -import { MaybeNullOrUndefined, Nullable } from '@/modules/shared/helpers/typeHelper' -import { db } from '@/db/knex' +import { + MaybeNullOrUndefined, + Nullable, + Optional +} from '@/modules/shared/helpers/typeHelper' import { CreateNewRequest, + DeleteRequestById, + GetPendingAccessRequest, GetPendingAccessRequests, GetPendingProjectRequests, GetUserProjectAccessRequest, @@ -159,59 +162,67 @@ export const getPendingStreamRequestsFactory = /** * Accept or decline a pending access request */ -export async function processPendingStreamRequest( - userId: string, - requestId: string, - accept: boolean, - role: StreamRoles = Roles.Stream.Contributor, - resourceAccessRules: MaybeNullOrUndefined -) { - const req = await getPendingAccessRequestFactory({ db })( - requestId, - AccessRequestType.Stream - ) - if (!req) { - throw new AccessRequestProcessingError('No request with this ID exists') - } - - try { - await validateStreamAccess( - userId, - req.resourceId, - Roles.Stream.Owner, - resourceAccessRules +export const processPendingStreamRequestFactory = + (deps: { + getPendingAccessRequest: GetPendingAccessRequest + validateStreamAccess: typeof validateStreamAccess + addOrUpdateStreamCollaborator: typeof addOrUpdateStreamCollaborator + deleteRequestById: DeleteRequestById + accessRequestsEmitter: (typeof AccessRequestsEmitter)['emit'] + }) => + async ( + userId: string, + requestId: string, + accept: boolean, + role: StreamRoles = Roles.Stream.Contributor, + resourceAccessRules: MaybeNullOrUndefined + ) => { + const req: Optional = await deps.getPendingAccessRequest( + requestId, + AccessRequestType.Stream ) - } catch (e: unknown) { - const err = ensureError(e, 'Stream access validation failed') - if (err instanceof StreamInvalidAccessError) { - throw new AccessRequestProcessingError( - 'You must own the stream to process access requests', - { cause: err } - ) - } else { - throw err + if (!req) { + throw new AccessRequestProcessingError('No request with this ID exists') } + + try { + await deps.validateStreamAccess( + userId, + req.resourceId, + Roles.Stream.Owner, + resourceAccessRules + ) + } catch (e: unknown) { + const err = ensureError(e, 'Stream access validation failed') + if (err instanceof StreamInvalidAccessError) { + throw new AccessRequestProcessingError( + 'You must own the stream to process access requests', + { cause: err } + ) + } else { + throw err + } + } + + if (accept) { + await deps.addOrUpdateStreamCollaborator( + req.resourceId, + req.requesterId, + role, + userId, + resourceAccessRules + ) + } + + await deps.deleteRequestById(req.id) + + await deps.accessRequestsEmitter(AccessRequestsEmitter.events.Finalized, { + request: req, + approved: accept ? { role } : undefined, + finalizedBy: userId + }) + + return req } - if (accept) { - await addOrUpdateStreamCollaborator( - req.resourceId, - req.requesterId, - role, - userId, - resourceAccessRules - ) - } - - await deleteRequestByIdFactory({ db })(req.id) - - await AccessRequestsEmitter.emit(AccessRequestsEmitter.events.Finalized, { - request: req, - approved: accept ? { role } : undefined, - finalizedBy: userId - }) - - return req -} - -export const processPendingProjectRequest = processPendingStreamRequest +export const processPendingProjectRequest = processPendingStreamRequestFactory