Merge pull request #3371 from specklesystems/fabians/core-ioc-103
chore(server): core IoC #103 - validatePermissionsReadStream
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
||||
import { ContextResourceAccessRules } from '@/modules/core/helpers/token'
|
||||
import { MaybeNullOrUndefined, Nullable, Optional, StreamRoles } from '@speckle/shared'
|
||||
import { Knex } from 'knex'
|
||||
import type express from 'express'
|
||||
|
||||
export type LegacyGetStreams = (params: {
|
||||
cursor?: string | Date | null | undefined
|
||||
@@ -361,3 +362,11 @@ export type AdminGetProjectList = (args: {
|
||||
items: Stream[]
|
||||
totalCount: number
|
||||
}>
|
||||
|
||||
export type ValidatePermissionsReadStream = (
|
||||
streamId: string,
|
||||
req: express.Request
|
||||
) => Promise<{
|
||||
result: boolean
|
||||
status: number
|
||||
}>
|
||||
|
||||
@@ -4,54 +4,8 @@ const { validateScopes, authorizeResolver } = require('@/modules/shared')
|
||||
const { Roles, Scopes } = require('@speckle/shared')
|
||||
const { throwForNotHavingServerRole } = require('@/modules/shared/authz')
|
||||
const { DatabaseError } = require('@/modules/shared/errors')
|
||||
const { getStreamFactory } = require('@/modules/core/repositories/streams')
|
||||
const { db } = require('@/db/knex')
|
||||
|
||||
module.exports = {
|
||||
async validatePermissionsReadStream(streamId, req) {
|
||||
const getStream = getStreamFactory({ db })
|
||||
const stream = await getStream({ streamId, userId: req.context.userId })
|
||||
if (stream?.isPublic) return { result: true, status: 200 }
|
||||
|
||||
try {
|
||||
await throwForNotHavingServerRole(req.context, Roles.Server.Guest)
|
||||
} catch (e) {
|
||||
if (e instanceof DatabaseError) return { result: false, status: 500 }
|
||||
req.log.info({ err: e }, 'Error while checking stream contributor role')
|
||||
return { result: false, status: 401 }
|
||||
}
|
||||
|
||||
if (!stream) return { result: false, status: 404 }
|
||||
|
||||
if (!stream.isPublic && req.context.auth === false) {
|
||||
req.log.debug('User is not authenticated, so cannot read from non-public stream.')
|
||||
return { result: false, status: 401 }
|
||||
}
|
||||
|
||||
if (!stream.isPublic) {
|
||||
try {
|
||||
await validateScopes(req.context.scopes, Scopes.Streams.Read)
|
||||
} catch (e) {
|
||||
req.log.info({ err: e }, 'Error while validating scopes')
|
||||
return { result: false, status: 401 }
|
||||
}
|
||||
|
||||
try {
|
||||
await authorizeResolver(
|
||||
req.context.userId,
|
||||
streamId,
|
||||
Roles.Stream.Reviewer,
|
||||
req.context.resourceAccessRules
|
||||
)
|
||||
} catch (e) {
|
||||
if (e instanceof DatabaseError) return { result: false, status: 500 }
|
||||
req.log.info({ err: e }, 'Error while checking stream contributor role')
|
||||
return { result: false, status: 401 }
|
||||
}
|
||||
}
|
||||
return { result: true, status: 200 }
|
||||
},
|
||||
|
||||
async validatePermissionsWriteStream(streamId, req) {
|
||||
if (!req.context || !req.context.auth) {
|
||||
req.log.debug('User is not authenticated, so cannot write to stream.')
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
import zlib from 'zlib'
|
||||
import { corsMiddleware } from '@/modules/core/configs/cors'
|
||||
import type { Application } from 'express'
|
||||
import { validatePermissionsReadStream } from '@/modules/core/rest/authUtils'
|
||||
import { SpeckleObjectsStream } from '@/modules/core/rest/speckleObjectsStream'
|
||||
import { pipeline, PassThrough } from 'stream'
|
||||
import { getObjectsStreamFactory } from '@/modules/core/repositories/objects'
|
||||
import { db } from '@/db/knex'
|
||||
import { validatePermissionsReadStreamFactory } from '@/modules/core/services/streams/auth'
|
||||
import { getStreamFactory } from '@/modules/core/repositories/streams'
|
||||
import { authorizeResolver, validateScopes } from '@/modules/shared'
|
||||
|
||||
export default (app: Application) => {
|
||||
const getObjectsStream = getObjectsStreamFactory({ db })
|
||||
const validatePermissionsReadStream = validatePermissionsReadStreamFactory({
|
||||
getStream: getStreamFactory({ db }),
|
||||
validateScopes,
|
||||
authorizeResolver
|
||||
})
|
||||
|
||||
app.options('/api/getobjects/:streamId', corsMiddleware())
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
const zlib = require('zlib')
|
||||
const { corsMiddleware } = require('@/modules/core/configs/cors')
|
||||
|
||||
const { validatePermissionsReadStream } = require('./authUtils')
|
||||
|
||||
const { SpeckleObjectsStream } = require('./speckleObjectsStream')
|
||||
const { pipeline, PassThrough } = require('stream')
|
||||
const { logger } = require('@/logging/logging')
|
||||
@@ -12,9 +10,19 @@ const {
|
||||
getObjectChildrenStreamFactory
|
||||
} = require('@/modules/core/repositories/objects')
|
||||
const { db } = require('@/db/knex')
|
||||
const {
|
||||
validatePermissionsReadStreamFactory
|
||||
} = require('@/modules/core/services/streams/auth')
|
||||
const { getStreamFactory } = require('@/modules/core/repositories/streams')
|
||||
const { validateScopes, authorizeResolver } = require('@/modules/shared')
|
||||
|
||||
const getObject = getFormattedObjectFactory({ db })
|
||||
const getObjectChildrenStream = getObjectChildrenStreamFactory({ db })
|
||||
const validatePermissionsReadStream = validatePermissionsReadStreamFactory({
|
||||
getStream: getStreamFactory({ db }),
|
||||
validateScopes,
|
||||
authorizeResolver
|
||||
})
|
||||
|
||||
module.exports = (app) => {
|
||||
app.options('/objects/:streamId/:objectId', corsMiddleware())
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'use strict'
|
||||
const { Scopes } = require('@/modules/core/helpers/mainConstants')
|
||||
import { Scopes } from '@/modules/core/helpers/mainConstants'
|
||||
|
||||
module.exports = [
|
||||
export default [
|
||||
{
|
||||
name: Scopes.Streams.Read,
|
||||
description:
|
||||
@@ -0,0 +1,57 @@
|
||||
import {
|
||||
GetStream,
|
||||
ValidatePermissionsReadStream
|
||||
} from '@/modules/core/domain/streams/operations'
|
||||
import { throwForNotHavingServerRole } from '@/modules/shared/authz'
|
||||
import { AuthorizeResolver, ValidateScopes } from '@/modules/shared/domain/operations'
|
||||
import { DatabaseError } from '@/modules/shared/errors'
|
||||
import { Roles, Scopes } from '@speckle/shared'
|
||||
|
||||
export const validatePermissionsReadStreamFactory =
|
||||
(deps: {
|
||||
getStream: GetStream
|
||||
validateScopes: ValidateScopes
|
||||
authorizeResolver: AuthorizeResolver
|
||||
}): ValidatePermissionsReadStream =>
|
||||
async (streamId, req) => {
|
||||
const stream = await deps.getStream({ streamId, userId: req.context.userId })
|
||||
if (stream?.isPublic) return { result: true, status: 200 }
|
||||
|
||||
try {
|
||||
await throwForNotHavingServerRole(req.context, Roles.Server.Guest)
|
||||
} catch (e) {
|
||||
if (e instanceof DatabaseError) return { result: false, status: 500 }
|
||||
req.log.info({ err: e }, 'Error while checking stream contributor role')
|
||||
return { result: false, status: 401 }
|
||||
}
|
||||
|
||||
if (!stream) return { result: false, status: 404 }
|
||||
|
||||
if (!stream.isPublic && req.context.auth === false) {
|
||||
req.log.debug('User is not authenticated, so cannot read from non-public stream.')
|
||||
return { result: false, status: 401 }
|
||||
}
|
||||
|
||||
if (!stream.isPublic) {
|
||||
try {
|
||||
await deps.validateScopes(req.context.scopes, Scopes.Streams.Read)
|
||||
} catch (e) {
|
||||
req.log.info({ err: e }, 'Error while validating scopes')
|
||||
return { result: false, status: 401 }
|
||||
}
|
||||
|
||||
try {
|
||||
await deps.authorizeResolver(
|
||||
req.context.userId,
|
||||
streamId,
|
||||
Roles.Stream.Reviewer,
|
||||
req.context.resourceAccessRules
|
||||
)
|
||||
} catch (e) {
|
||||
if (e instanceof DatabaseError) return { result: false, status: 500 }
|
||||
req.log.info({ err: e }, 'Error while checking stream contributor role')
|
||||
return { result: false, status: 401 }
|
||||
}
|
||||
}
|
||||
return { result: true, status: 200 }
|
||||
}
|
||||
Reference in New Issue
Block a user