Files
speckle-server/packages/server/modules/previews/index.ts
T
2024-10-09 10:39:00 +03:00

179 lines
5.3 KiB
TypeScript

/* istanbul ignore file */
'use strict'
import { validateScopes, authorizeResolver } from '@/modules/shared'
import {
getCommitsByStreamId,
getCommitsByBranchName
} from '@/modules/core/services/commits'
import { makeOgImage } from '@/modules/previews/ogImage'
import { moduleLogger } from '@/logging/logging'
import { listenForPreviewGenerationUpdatesFactory } from '@/modules/previews/services/resultListener'
import cors from 'cors'
import { db } from '@/db/knex'
import {
getObjectPreviewBufferOrFilepathFactory,
sendObjectPreviewFactory,
checkStreamPermissionsFactory
} from '@/modules/previews/services/management'
import { getObject } from '@/modules/core/services/objects'
import {
getObjectPreviewInfoFactory,
createObjectPreviewFactory,
getPreviewImageFactory
} from '@/modules/previews/repository/previews'
import { publish } from '@/modules/shared/utils/subscriptions'
import {
getCommitFactory,
getObjectCommitsWithStreamIdsFactory
} from '@/modules/core/repositories/commits'
import { SpeckleModule } from '@/modules/shared/helpers/typeHelper'
import { getStreamFactory } from '@/modules/core/repositories/streams'
const httpErrorImage = (httpErrorCode: number) =>
require.resolve(`#/assets/previews/images/preview_${httpErrorCode}.png`)
const noPreviewImage = require.resolve('#/assets/previews/images/no_preview.png')
export const init: SpeckleModule['init'] = (app, isInitial) => {
if (process.env.DISABLE_PREVIEWS) {
moduleLogger.warn('📸 Object preview module is DISABLED')
} else {
moduleLogger.info('📸 Init object preview module')
}
const getStream = getStreamFactory({ db })
const getObjectPreviewBufferOrFilepath = getObjectPreviewBufferOrFilepathFactory({
getObject,
getObjectPreviewInfo: getObjectPreviewInfoFactory({ db }),
createObjectPreview: createObjectPreviewFactory({ db }),
getPreviewImage: getPreviewImageFactory({ db })
})
const sendObjectPreview = sendObjectPreviewFactory({
getStream,
getObjectPreviewBufferOrFilepath,
makeOgImage
})
const checkStreamPermissions = checkStreamPermissionsFactory({
validateScopes,
authorizeResolver,
getStream
})
app.options('/preview/:streamId/:angle?', cors())
app.get('/preview/:streamId/:angle?', cors(), async (req, res) => {
const { hasPermissions, httpErrorCode } = await checkStreamPermissions(req)
if (!hasPermissions) {
// return res.status( httpErrorCode ).end()
return res.sendFile(httpErrorImage(httpErrorCode))
}
const { commits } = await getCommitsByStreamId({
streamId: req.params.streamId,
limit: 1,
ignoreGlobalsBranch: true,
cursor: undefined
})
if (!commits || commits.length === 0) {
return res.sendFile(noPreviewImage)
}
const lastCommit = commits[0]
return sendObjectPreview(
req,
res,
req.params.streamId,
lastCommit.referencedObject,
req.params.angle
)
})
app.options('/preview/:streamId/branches/:branchName/:angle?', cors())
app.get(
'/preview/:streamId/branches/:branchName/:angle?',
cors(),
async (req, res) => {
const { hasPermissions, httpErrorCode } = await checkStreamPermissions(req)
if (!hasPermissions) {
// return res.status( httpErrorCode ).end()
return res.sendFile(httpErrorImage(httpErrorCode))
}
let commitsObj
try {
commitsObj = await getCommitsByBranchName({
streamId: req.params.streamId,
branchName: req.params.branchName,
limit: 1,
cursor: undefined
})
} catch {
commitsObj = {}
}
const { commits } = commitsObj
if (!commits || commits.length === 0) {
return res.sendFile(noPreviewImage)
}
const lastCommit = commits[0]
return sendObjectPreview(
req,
res,
req.params.streamId,
lastCommit.referencedObject,
req.params.angle
)
}
)
app.options('/preview/:streamId/commits/:commitId/:angle?', cors())
app.get('/preview/:streamId/commits/:commitId/:angle?', cors(), async (req, res) => {
const { hasPermissions, httpErrorCode } = await checkStreamPermissions(req)
if (!hasPermissions) {
// return res.status( httpErrorCode ).end()
return res.sendFile(httpErrorImage(httpErrorCode))
}
const getCommit = getCommitFactory({ db })
const commit = await getCommit(req.params.commitId, {
streamId: req.params.streamId
})
if (!commit) return res.sendFile(noPreviewImage)
return sendObjectPreview(
req,
res,
req.params.streamId,
commit.referencedObject,
req.params.angle
)
})
app.options('/preview/:streamId/objects/:objectId/:angle?', cors())
app.get('/preview/:streamId/objects/:objectId/:angle?', cors(), async (req, res) => {
const { hasPermissions } = await checkStreamPermissions(req)
if (!hasPermissions) {
return res.status(403).end()
}
return sendObjectPreview(
req,
res,
req.params.streamId,
req.params.objectId,
req.params.angle
)
})
if (isInitial) {
const listenForPreviewGenerationUpdates = listenForPreviewGenerationUpdatesFactory({
getObjectCommitsWithStreamIds: getObjectCommitsWithStreamIdsFactory({ db }),
publish
})
listenForPreviewGenerationUpdates()
}
}
export const finalize = () => {}