Files
speckle-server/packages/server/modules/previews/index.js
T
2021-04-29 15:11:22 +03:00

103 lines
3.5 KiB
JavaScript

/* istanbul ignore file */
'use strict'
const debug = require( 'debug' )
const express = require( 'express' )
const appRoot = require( 'app-root-path' )
const cors = require( 'cors' )
const { matomoMiddleware } = require( `${appRoot}/logging/matomoHelper` )
const { contextMiddleware, validateScopes, authorizeResolver } = require( `${appRoot}/modules/shared` )
const { getStream } = require( '../core/services/streams' )
const { getObject } = require( '../core/services/objects' )
const { getPreviewImage, createObjectPreview, getObjectPreviewInfo } = require( './services/previews' )
exports.init = ( app, options ) => {
if ( process.env.DISABLE_PREVIEWS ) {
debug( 'speckle:modules' )( '📸 Object preview module is DISABLED' )
} else {
debug( 'speckle:modules' )( '📸 Init object preview module' )
}
let sendObjectPreview = async ( req, res, streamId, objectId ) => {
if ( process.env.DISABLE_PREVIEWS ) {
return res.sendFile( `${appRoot}/modules/previews/assets/no_preview.png` )
}
// Check if objectId is valid
const dbObj = await getObject( { streamId, objectId } )
if ( !dbObj ) {
return res.sendFile( `${appRoot}/modules/previews/assets/preview_error.png` )
}
// Get existing preview metadata
let previewInfo = await getObjectPreviewInfo( { streamId, objectId } )
if ( !previewInfo ) {
await createObjectPreview( { streamId, objectId, priority: 0 } )
}
let timestampStart = Date.now()
// Try for 10 sec of wall-clock to get the image (wait for preview generation)
while ( Date.now() < timestampStart + 10*1000 ) {
previewInfo = await getObjectPreviewInfo( { streamId, objectId } )
if ( previewInfo.previewStatus == 2 && previewInfo.preview ) {
break
}
await new Promise( ( resolve ) => {
setTimeout( resolve, 500 )
} )
}
if ( previewInfo.previewStatus != 2 || !previewInfo.preview ) {
return res.sendFile( `${appRoot}/modules/previews/assets/no_preview.png` )
}
let previewImgId = previewInfo.preview[req.params.angle]
if ( !previewImgId ) {
debug( 'speckle:errors' )( `Error: Preview angle '${req.params.angle}' not found for object ${streamId}:${objectId}` )
return res.sendFile( `${appRoot}/modules/previews/assets/preview_error.png` )
}
let previewImg = await getPreviewImage( { previewId: previewImgId } )
if ( !previewImg ) {
debug( 'speckle:errors' )( `Error: Preview image not found: ${previewImgId}` )
return res.sendFile( `${appRoot}/modules/previews/assets/preview_error.png` )
}
res.contentType( 'image/png' )
res.send( previewImg )
}
app.get( '/preview/:streamId/objects/:objectId/:angle', contextMiddleware, matomoMiddleware, async ( req, res ) => {
const stream = await getStream( { streamId: req.params.streamId, userId: req.context.userId } )
if ( !stream ) {
return res.status( 404 ).end()
}
if ( !stream.isPublic && req.context.auth === false ) {
return res.status( 401 ).end( )
}
if ( !stream.isPublic ) {
try {
await validateScopes( req.context.scopes, 'streams:read' )
} catch ( err ) {
return res.status( 401 ).end( )
}
try {
await authorizeResolver( req.context.userId, req.params.streamId, 'stream:reviewer' )
} catch ( err ) {
return res.status( 401 ).end( )
}
}
return sendObjectPreview( req, res, req.params.streamId, req.params.objectId )
} )
}
exports.finalize = () => {}