340 lines
8.3 KiB
JavaScript
340 lines
8.3 KiB
JavaScript
|
'use strict'
|
||
|
|
||
|
const http = require( 'http' )
|
||
|
, https = require( 'https' )
|
||
|
, fs = require( 'fs' )
|
||
|
, path = require( 'path' )
|
||
|
, express = require( 'express' )
|
||
|
, bodyParser = require( 'body-parser' )
|
||
|
, formidable = require( 'formidable' )
|
||
|
, compression = require( 'compression' )
|
||
|
, minify = require( 'express-minify' )
|
||
|
, morgan = require( 'morgan' )
|
||
|
, range = require( 'range-2018.js' )
|
||
|
|
||
|
const DB = require( './lib/db.js' )
|
||
|
, Photos = require( './lib/photos.js' )
|
||
|
, Now = require( './lib/readable-timestamp.js' )
|
||
|
, Config = require( './config.js' )
|
||
|
|
||
|
let app = express( )
|
||
|
|
||
|
app.all( '*', ( req, res, next ) =>
|
||
|
{ if( /:\/\/baidu\.com\//i.test( req.url ) )
|
||
|
{ return res.sendStatus( 403 ).end( ) }
|
||
|
|
||
|
// if( ( 'http' == req.protocol )
|
||
|
// || /^www\./i.test( req.hostname )
|
||
|
// )
|
||
|
// { return res.redirect( 301,
|
||
|
// [ 'https://'
|
||
|
// , req.hostname.replace( /^(www\.)+/i, '' )
|
||
|
// , ':'
|
||
|
// , Config.ENV.SSLPORT
|
||
|
// , req.url
|
||
|
// ].join('') )
|
||
|
// }
|
||
|
|
||
|
next( )
|
||
|
})
|
||
|
|
||
|
|
||
|
app.use( bodyParser.json( ) )
|
||
|
.use( bodyParser.urlencoded({ extended: false }) )
|
||
|
.use( compression( ) )
|
||
|
.use( minify( ) )
|
||
|
.use( express.static( './static' ) )
|
||
|
|
||
|
if( Config.ENV.PRODUCTION )
|
||
|
{ app.use( morgan
|
||
|
( 'combined'
|
||
|
, { skip: ( req, res ) =>
|
||
|
/\.(jpg|png|svg|ico|css|js)$/i.test( req.url )
|
||
|
, stream: fs.createWriteStream
|
||
|
( path.join( __dirname, 'log.txt' ), { flags: 'a' } )
|
||
|
}
|
||
|
) )
|
||
|
}
|
||
|
|
||
|
|
||
|
app.get( '/photos/:search', ( req, res ) =>
|
||
|
{ res.redirect( 302, '/photos/#'+req.params.search ) })
|
||
|
|
||
|
|
||
|
app.post( '/api/photos/variant', async ( req, res ) =>
|
||
|
{ // create a Variant
|
||
|
if( !req.query
|
||
|
|| !req.query.SKU
|
||
|
|| !req.query.Variant
|
||
|
)
|
||
|
{ res.sendStatus( 400 )
|
||
|
.end( 'not enough params to create a variant' )
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
let { SKU, Variant, CopyOf } = req.query
|
||
|
Photos.createVariant({ SKU, Variant, CopyOf })
|
||
|
|
||
|
res.sendStatus( 200 )
|
||
|
.end( )
|
||
|
})
|
||
|
|
||
|
|
||
|
app.put( '/api/photos/setDefaultVariant', ( req, res ) =>
|
||
|
{ if( !req.query
|
||
|
|| !req.query.SKU
|
||
|
|| !req.query.Variant
|
||
|
|| !req.query.oldVarinatRenamedTo
|
||
|
)
|
||
|
{ res.sendStatus( 400 )
|
||
|
.end( 'not enough params to set a default variant'
|
||
|
+ '(PUT /api/photos/setDefaultVariant)'
|
||
|
)
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
let { SKU, Variant, oldVarinatRenamedTo } = req.query
|
||
|
|
||
|
// set Variant as Default
|
||
|
Photos.setDefaultVariant({ SKU, Variant, oldVarinatRenamedTo })
|
||
|
|
||
|
res.sendStatus( 200 )
|
||
|
.end( )
|
||
|
})
|
||
|
|
||
|
app.put( '/api/photos/renumber', async ( req, res ) =>
|
||
|
{ if( !req.query.SKU
|
||
|
|| !req.query.Variant
|
||
|
|| !req.query.OldNr
|
||
|
|| !req.query.NewNr
|
||
|
)
|
||
|
{ res.sendStatus( 400 )
|
||
|
.end( 'not enough params to renumber photos'
|
||
|
+ '(PUT /api/photos/renumber)'
|
||
|
)
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// re-arraged the Photos
|
||
|
const { SKU, Variant, OldNr, NewNr } = req.query
|
||
|
const _success = await Photos.Renumber(
|
||
|
{ SKU
|
||
|
, Variant
|
||
|
, OldNr
|
||
|
, NewNr
|
||
|
})
|
||
|
|
||
|
res.sendStatus( _success && 200 || 500 )
|
||
|
.end( )
|
||
|
})
|
||
|
|
||
|
|
||
|
app.delete( '/api/photos/variant', async ( req, res ) =>
|
||
|
{ if( !req.query
|
||
|
|| !req.query.SKU
|
||
|
|| !req.query.Variant
|
||
|
)
|
||
|
{ res.sendStatus( 400 )
|
||
|
.end( 'not enough parameters to delete variant' )
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
const { SKU, Variant } = req.query
|
||
|
res.sendStatus( 200 )
|
||
|
.end( await Photos.removeVariant({ SKU, Variant }) )
|
||
|
})
|
||
|
|
||
|
app.delete( '/api/photos', async ( req, res ) =>
|
||
|
{ if( !req.query
|
||
|
|| !req.query.SKU
|
||
|
|| !req.query.Variant
|
||
|
|| !req.query.Nr
|
||
|
)
|
||
|
{ res.sendStatus( 400 )
|
||
|
.end( 'not enough query parameters to delete a photo' )
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
const { SKU, Variant, Hash, Nr } = req.query
|
||
|
const _success = await Photos.removeOne(
|
||
|
{ SKU
|
||
|
, Variant
|
||
|
, Nr
|
||
|
})
|
||
|
|
||
|
res.sendStatus( _success && 200 || 500 )
|
||
|
.end( )
|
||
|
})
|
||
|
|
||
|
app.post( '/api/photos', async ( req, res ) =>
|
||
|
{ if( !req.query
|
||
|
|| !req.query.SKU
|
||
|
|| !req.query.Variant
|
||
|
)
|
||
|
{ res.sendStatus( 400 )
|
||
|
.end( 'not enough params to upload photo(s)' )
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
let { SKU, Variant, Nr } = req.query
|
||
|
, UploadingMultiplePhotos = false
|
||
|
|
||
|
if( 0 == Nr )
|
||
|
{ // uploading multiple photos
|
||
|
UploadingMultiplePhotos = true
|
||
|
|
||
|
const CurrentPhotos = await Photos.getHashmap(
|
||
|
{ SKU
|
||
|
, Variant
|
||
|
, arrNumbers : range( 1,10 )
|
||
|
})
|
||
|
|
||
|
if( CurrentPhotos )
|
||
|
{ Object.keys( CurrentPhotos ).every( _Photo =>
|
||
|
{ if( !CurrentPhotos[ _Photo ] )
|
||
|
{ Nr = Number( _Photo )
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
})
|
||
|
}
|
||
|
else
|
||
|
{ Nr = 1 }
|
||
|
}
|
||
|
else
|
||
|
{ // replacing single photo
|
||
|
await Photos.deletePhotoFiles({ SKU, Nr })
|
||
|
}
|
||
|
|
||
|
let form = new formidable.IncomingForm( )
|
||
|
form.uploadDir = path.join( __dirname, 'uploads' )
|
||
|
form.encoding = 'binary'
|
||
|
|
||
|
form.addListener( 'file', async ( name, file ) =>
|
||
|
{ if( UploadingMultiplePhotos
|
||
|
&& ( 10 <= Nr )
|
||
|
)
|
||
|
{ return false }
|
||
|
|
||
|
console.info
|
||
|
( Now( )
|
||
|
, `recieving photo "${SKU}" /`
|
||
|
, `"${Variant}" / "${Nr}"`
|
||
|
)
|
||
|
|
||
|
Photos.Process
|
||
|
({ FilePath : file.path
|
||
|
, SKU
|
||
|
, Variant
|
||
|
, Nr : Nr++
|
||
|
})
|
||
|
})
|
||
|
|
||
|
form.addListener( 'end', ( ) =>
|
||
|
{ res.sendStatus( 200 )
|
||
|
.end( '<script>window.close( )</script>' )
|
||
|
})
|
||
|
|
||
|
form.parse( req, ( err, fields, files ) =>
|
||
|
{ if( err )
|
||
|
{ console.error( Now( ), { err, fields, files } ) }
|
||
|
})
|
||
|
})
|
||
|
|
||
|
|
||
|
app.put( '/api/photos/assignVariantToAccount', async ( req, res ) =>
|
||
|
{ // assigning Variant to Account
|
||
|
if( !req.query
|
||
|
|| !req.query.SKU
|
||
|
|| !req.query.Variant
|
||
|
|| !req.query.Account
|
||
|
)
|
||
|
{ res.sendStatus( 400 )
|
||
|
.end( 'not enough params to assigning Variant to Account '
|
||
|
+ '[POST /api/photos/assignVariantToAccount]'
|
||
|
)
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
const { SKU, Variant, Account } = req.query
|
||
|
const _success = await Photos.assignVariantToAccount(
|
||
|
{ SKU
|
||
|
, Variant
|
||
|
, Account
|
||
|
})
|
||
|
|
||
|
res.sendStatus( _success && 200 || 500 )
|
||
|
.end( )
|
||
|
})
|
||
|
|
||
|
|
||
|
app.get( '/api/photos', async ( req, res ) =>
|
||
|
{ // get Photos_Ordered(since lastUpdated) table
|
||
|
// console.log('GET: /api/photos\nQUERY:', req.query )
|
||
|
res.send( await Photos.get_Photos_Since( req.query.since ) )
|
||
|
})
|
||
|
|
||
|
|
||
|
app.get( '/api/photos/baseURL', async ( req, res ) =>
|
||
|
{ // get the httpURL of photos dir
|
||
|
res.end( Config.Paths.imgGlobal )
|
||
|
})
|
||
|
|
||
|
app.get( '/api/photos/accounts', async ( req, res ) =>
|
||
|
{ // get all the Accounts for the photos
|
||
|
res.end( Config.Accounts.join( '\n' ) )
|
||
|
})
|
||
|
|
||
|
|
||
|
// http (for redirects only)
|
||
|
const httpURL = _ => `\n http://${ _ }:${ Config.ENV.PORT }`
|
||
|
|
||
|
//console.log( Config, Config.ENV )
|
||
|
|
||
|
http.createServer( app )
|
||
|
.listen( Config.ENV.PORT, Config.ENV.IP )
|
||
|
|
||
|
if( '::' == Config.ENV.IP )
|
||
|
{ console.info( Now( ), httpURL( '[::1]' ) ) }
|
||
|
else
|
||
|
{ http.createServer( app )
|
||
|
.listen( Config.ENV.PORT, Config.ENV.IP6 )
|
||
|
|
||
|
console.info
|
||
|
( Now( )
|
||
|
, httpURL( 'localhost' )
|
||
|
, httpURL( Config.ENV.HOST )
|
||
|
, httpURL( Config.ENV.IP )
|
||
|
, httpURL( `[${ Config.ENV.IP6 }]` )
|
||
|
)
|
||
|
}
|
||
|
|
||
|
// SSL
|
||
|
// const sslURL = _ => `\n https://${ _ }:${ Config.ENV.SSLPORT }`
|
||
|
// try
|
||
|
// { const SSLCerts =
|
||
|
// { cert: fs.readFileSync( path.join( __dirname, 'ssl', 'cert.pem' ) )
|
||
|
// , key: fs.readFileSync( path.join( __dirname, 'ssl', 'key.pem' ) )
|
||
|
// }
|
||
|
|
||
|
// https.createServer( SSLCerts, app )
|
||
|
// .listen( Config.ENV.SSLPORT, Config.ENV.IP )
|
||
|
|
||
|
// if( '::' == Config.ENV.IP )
|
||
|
// { console.info( Now( ), sslURL( '[::1]' ) ) }
|
||
|
// else
|
||
|
// { https.createServer( SSLCerts, app )
|
||
|
// .listen( Config.ENV.SSLPORT, Config.ENV.IP6 )
|
||
|
|
||
|
// console.info
|
||
|
// ( Now( )
|
||
|
// , sslURL( 'localhost' )
|
||
|
// , sslURL( Config.ENV.HOST )
|
||
|
// , sslURL( Config.ENV.IP )
|
||
|
// , sslURL( `[${ Config.ENV.IP6 }]` )
|
||
|
// )
|
||
|
// }
|
||
|
// }
|
||
|
// catch( err )
|
||
|
// { console.warn( Now( ), 'no SSL:', err ) }
|