Files
speckle-server/packages/frontend-2/middleware/requireValidProject.ts
T
Gergő Jedlicska f501cc4ad5 gergo/web 2888 workspace project cancreate (#4294)
* WIP can create project

* WIP can create project more work

* complete body, stencil tests

* feat(shared): move workspace plan types into shared

* test progress wip

* feat(shared): add more logic to canCreateWorkspaceProject

* a few more tests, as a treat

* chore(authz): round out tests

* fixed loaders, new GQL checks, dataLoaders in auth loaders

* fix(authz): get workspace limits loader

* chore(authz): update loaders

* frontend fixed up to snuff

* fix(authz): fix workspace plans for tests

* fix(authz): classic

* fix(authz): 0 counts

---------

Co-authored-by: Chuck Driesler <chuck@speckle.systems>
Co-authored-by: Kristaps Fabians Geikins <fabis94@live.com>
2025-04-01 16:38:20 +01:00

66 lines
2.1 KiB
TypeScript

import type { Optional } from '@speckle/shared'
import { useApolloClientFromNuxt } from '~/lib/common/composables/graphql'
import { errorsToAuthResult } from '~/lib/common/helpers/graphql'
import { projectAccessCheckQuery } from '~/lib/projects/graphql/queries'
import { WorkspaceSsoErrorCodes } from '~/lib/workspaces/helpers/types'
/**
* Used in project page to validate that project ID refers to a valid project and redirects to 404 if not
*/
export default defineNuxtRouteMiddleware(async (to) => {
const projectId = to.params.id as string
const client = useApolloClientFromNuxt()
const { data, errors } = await client
.query({
query: projectAccessCheckQuery,
variables: { id: projectId },
context: {
skipLoggingErrors: true
},
fetchPolicy: 'network-only'
})
.catch(convertThrowIntoFetchResult)
// we may not even get to the authResult because of project() resolver errors, hence the mapping
// from errors to authResult
const authResult = data?.project.permissions.canRead || errorsToAuthResult({ errors })
if (!authResult.authorized) {
switch (authResult.code) {
case WorkspaceSsoErrorCodes.SESSION_MISSING_OR_EXPIRED: {
// Redirect to the SSO error page
const payload = authResult.payload as Optional<{
workspaceSlug: string
}>
const workspaceSlug = payload?.workspaceSlug
if (workspaceSlug) {
return navigateTo(`/workspaces/${workspaceSlug}/sso/session-error`)
}
}
// eslint-disable-next-line no-fallthrough
case 'FORBIDDEN':
return abortNavigation(
createError({
statusCode: 403,
message: authResult.message
})
)
case 'STREAM_NOT_FOUND':
return abortNavigation(
createError({
statusCode: 404,
message: authResult.message
})
)
default:
return abortNavigation(
createError({
statusCode: 500,
message: authResult.message
})
)
}
}
})