diff --git a/modules/configure-json-file.js b/modules/configure-json-file.js index 5a1c3ad..5fbf68e 100644 --- a/modules/configure-json-file.js +++ b/modules/configure-json-file.js @@ -2,74 +2,62 @@ const fs = require('fs'); // File System const fe = require('path'); -exports.setup = function(args, rootDir){ - let loadJson; - try{ - if(fe.extname(args[args.length-1]) === '.json' && fs.statSync(args[args.length-1]).isFile()){ - loadJson = JSON.parse(fs.readFileSync(args[args.length-1], 'utf8')); - }else{ - return require('./configure-commander.js').setup(args); - } - }catch(error){ - console.log(error); - return {error:"Failed to parse JSON file"}; - } - - +exports.setup = function(loadJson, rootDir){ + // TODO REDO THIS WHOLE THING + var errorArray = []; + // Check for port if(!loadJson.port){ loadJson.port = 5050; } - if(!isInt(loadJson.port) || loadJson.port < 0 || loadJson.port > 65535){ - return {error:"BAD PORT, WILL ABORT"}; + + // Check for UI + if(!loadJson.userinterface){ + loadJson.userinterface = 'public'; } - // TODO: Add comprehensive DB checks - if(!loadJson.database_plugin){ - return {error:"Please Configure DB"}; + if(!loadJson.database_plugin || !loadJson.database_plugin.dbPath){ + loadJson.database_plugin.dbPath = 'mstream.db'; } - if(loadJson.userinterface){ - if(!fs.statSync( fe.join(rootDir, loadJson.userinterface) ).isDirectory()){ - return {error:"Could not find userinterface"}; + if(!loadJson.folders || typeof loadJson.folders !== 'object'){ + errorArray.push('No Folders'); + loadJson.error = errorArray; + return loadJson; + } + + for(let folder in loadJson.folders){ + if(typeof loadJson.folders[folder] === 'string'){ + let folderString = loadJson.folders[folder]; + loadJson.folders[folder] = { + root: folderString + }; + } + + // Verify path is real + if(!loadJson.folders[folder].root || !fs.statSync( loadJson.folders[folder].root).isDirectory()){ + errorArray.push(loadJson.folders[folder].root + ' is not a real path'); } } - - // Normalize for all OS - // Make sure it's a directory - // Loop through and makeure all user Dirs are real - if(loadJson.users){ - for (let username in loadJson.users) { - // TODO: Check usernames for forbidden chars - - // TODO: Make sure all music directories are unique - // TODO: No subsets/super-sets/duplicates - if( !fs.statSync( loadJson.users[username].musicDir ).isDirectory()){ - return {error:loadJson.users[username].username + " music directory could not be found"}; - } - } + console.log(loadJson.users) + if(!loadJson.users || typeof loadJson.users !== 'object'){ + errorArray.push('No Users'); + loadJson.error = errorArray; + return loadJson; } - // TODO: Preform a full range of checks - if(loadJson.tunnel){ - if(loadJson.tunnel.refreshInterval && !isInt(loadJson.tunnel.refreshInterval)){ - return {error:"Refresh interval must be an integer"}; + for(let user in loadJson.users){ + if(typeof loadJson.users[user].vpaths === 'string'){ + loadJson.users[user].vpaths = [loadJson.users[user].vpaths]; } + } + if(errorArray.length > 0){ + loadJson.error = errorArray; + } // Export JSON return loadJson; } - - -function isInt(value) { - if (isNaN(value)) { - return false; - } - var x = parseFloat(value); - return (x | 0) === x; -} - -// TODO: This should sum up all errors before returing to user diff --git a/modules/db-read/database-public-sqlite.js b/modules/db-read/database-public-sqlite.js deleted file mode 100644 index 95b04ae..0000000 --- a/modules/db-read/database-public-sqlite.js +++ /dev/null @@ -1,337 +0,0 @@ -const sqlite3 = require('sqlite3').verbose(); -const fe = require('path'); -const crypto = require('crypto'); - -var db; - - -function getFileType(filename){ - return filename.split(".").pop(); -} - -exports.getNumberOfFiles = function(username, callback){ - db.get("SELECT Count(*) FROM items WHERE user = ?;", [username], function(err, row){ - if(err){ - console.log('SQL ERROR!'); - console.log(err); - } - callback(row['Count(*)']); - }); -} - -exports.setup = function (mstream, dbSettings){ - db = new sqlite3.Database(dbSettings.dbPath); - - // Setup DB - // TODO: Add the following cols - // rating - var itemsSql = "CREATE TABLE IF NOT EXISTS items ( \ - id INTEGER PRIMARY KEY AUTOINCREMENT, \ - title varchar DEFAULT NULL, \ - artist varchar DEFAULT NULL, \ - year int DEFAULT NULL, \ - album varchar DEFAULT NULL, \ - path TEXT NOT NULL, \ - format VARCHAR, \ - track INTEGER, \ - disk INTEGER, \ - user VARCHAR, \ - filesize INTEGER, \ - file_created_date INTEGER, \ - file_modified_date INTEGER, \ - hash VARCHAR, \ - album_art_file TEXT, \ - timestamp DATETIME DEFAULT CURRENT_TIMESTAMP \ - );"; - - var playlistSql = "CREATE TABLE IF NOT EXISTS mstream_playlists ( \ - id INTEGER PRIMARY KEY AUTOINCREMENT, \ - playlist_name varchar, \ - filepath varchar, \ - hide int DEFAULT 0, \ - user VARCHAR, \ - created DATETIME DEFAULT CURRENT_TIMESTAMP \ - );"; - - // Create tables - db.run(itemsSql, function() {}); - db.run(playlistSql, function() {}); - - - // Metadata lookup - mstream.post('/db/metadata', function (req, res){ - var relativePath = req.body.filepath; - var fullpath = fe.join(req.user.musicDir, relativePath); - - // Find entry matching path - db.get("SELECT * FROM items WHERE path = ?", [fullpath], function(err, row){ - if(err || !row){ - res.status(500).json({ error: 'DB Error' }); - return; - } - - // Return metadata - res.json({ - "filepath":relativePath, - "metadata":{ - "artist":row.artist, - "hash": row.hash, - "album":row.album, - "track":row.track, - "title":row.title, - "year":row.year, - "album-art":row.album_art_file - } - }); - - }); - }); - - - // TODO: This needs to be tested to see if it works on extra large playlists (think thousands of entries) - // TODO: Ban saving playlists that are > 10,000 items long - mstream.post('/playlist/save', function (req, res){ - var title = req.body.title; - var songs = req.body.songs; - - // Check if this playlist already exists - db.all("SELECT id FROM mstream_playlists WHERE playlist_name = ? AND user = ?;", [title, req.user.username], function(err, rows) { - db.serialize(function() { - // We need to delete anys existing entries - if(rows && rows.length > 0){ - db.run("DELETE FROM mstream_playlists WHERE playlist_name = ? AND user = ?;", [title, req.user.username]); - } - - // Now we add the new entries - var sql2 = "insert into mstream_playlists (playlist_name, filepath, user) values "; - var sqlParser = []; - - while(songs.length > 0) { - var song = songs.shift(); - - sql2 += "(?, ?, ?), "; - sqlParser.push(title); - sqlParser.push( fe.join(req.user.musicDir, song) ); - sqlParser.push( req.user.username ); - } - - sql2 = sql2.slice(0, -2); - sql2 += ";"; - - db.run(sql2, sqlParser, function(){ - res.json({success: true}); - }); - - }); - }); - }); - - - // Attach API calls to functions - mstream.get('/playlist/getall', function (req, res){ - // TODO: In V2 we need to change this to ignore hidden playlists - // TODO: db.all("SELECT DISTINCT playlist_name FROM mstream_playlists WHERE hide=0;", function(err, rows){ - db.all("SELECT DISTINCT playlist_name FROM mstream_playlists WHERE user = ?", [req.user.username], function(err, rows){ - var playlists = []; - - // loop through files - for (var i = 0; i < rows.length; i++) { - if(rows[i].playlist_name){ - playlists.push({name: rows[i].playlist_name}); - } - } - - res.json(playlists); - }); - }); - - mstream.post('/playlist/load', function (req, res){ - var playlist = req.body.playlistname; - - db.all("SELECT * FROM mstream_playlists WHERE playlist_name = ? AND user = ? ORDER BY id COLLATE NOCASE ASC", [playlist, req.user.username], function(err, rows){ - var returnThis = []; - - for (var i = 0; i < rows.length; i++) { - - // var tempName = rows[i].filepath.split('/').slice(-1)[0]; - var tempName = fe.basename(rows[i].filepath); - var extension = getFileType(rows[i].filepath); - var filepath = fe.relative(req.user.musicDir, rows[i].filepath); - filepath = filepath.replace(/\\/g, '/'); - - returnThis.push({filepath: filepath, metadata:'' }); - } - - res.json(returnThis); - }); - }); - mstream.post('/playlist/delete', function(req, res){ - var playlistname = req.body.playlistname; - - // Handle a soft delete - if(req.body.hide && parseInt(req.body.hide) == true ){ - db.run("UPDATE mstream_playlists SET hide = 1 WHERE playlist_name = ? AND user = ?;", [playlistname, req.user.username], function(){ - res.json({success: true}); - }); - }else{ - // Delete playlist from DB - db.run("DELETE FROM mstream_playlists WHERE playlist_name = ? AND user = ?;", [playlistname, req.user.username], function(){ - res.json({success: true}); - }); - } - }); - - - mstream.post('/db/search', function(req, res){ - var searchTerm = "%" + req.body.search + "%" ; - - var returnThis = {"albums":[], "artists":[]}; - - // TODO: Combine SQL calls into one - db.serialize(function() { - - var sqlAlbum = "SELECT DISTINCT album FROM items WHERE items.album LIKE ? AND user = ? ORDER BY album COLLATE NOCASE ASC;"; - db.all(sqlAlbum, [searchTerm, req.user.username], function(err, rows) { - if(err){ - res.status(500).json({ error: 'DB Error' }); - return; - } - - for (var i = 0; i < rows.length; i++) { - if(rows[i].album){ - returnThis.albums.push(rows[i].album); - } - } - }); - - - var sqlArtist = "SELECT DISTINCT artist FROM items WHERE items.artist LIKE ? AND user = ? ORDER BY artist COLLATE NOCASE ASC;"; - db.all(sqlArtist, [searchTerm, req.user.username], function(err, rows) { - if(err){ - res.status(500).json({ error: 'DB Error' }); - return; - } - - for (var i = 0; i < rows.length; i++) { - if(rows[i].artist){ - returnThis.artists.push(rows[i].artist); - } - } - - res.json(returnThis); - }); - }); - }); - - mstream.get('/db/artists', function (req, res) { - var artists = {"artists":[]}; - - var sql = "SELECT DISTINCT artist FROM items WHERE user = ? ORDER BY artist COLLATE NOCASE ASC;"; - db.all(sql, [req.user.username], function(err, rows) { - if(err){ - res.status(500).json({ error: 'DB Error' }); - return; - } - - var returnArray = []; - for (var i = 0; i < rows.length; i++) { - if(rows[i].artist){ - artists.artists.push(rows[i].artist); - } - } - - res.json(artists); - }); - }); - - mstream.post('/db/artists-albums', function (req, res) { - var albums = {"albums":[]}; - - // TODO: Make a list of all songs without null albums and add them to the response - var sql = "SELECT album, album_art_file FROM items WHERE artist = ? AND user = ? GROUP BY album ORDER BY album COLLATE NOCASE ASC;"; - var searchTerms = []; - searchTerms.push(req.body.artist); - searchTerms.push(req.user.username); - - db.all(sql, searchTerms, function(err, rows) { - if(err){ - res.status(500).json({ error: 'DB Error' }); - return; - } - - for (let row of rows){ - if(row.album){ - albums.albums.push({ - name: row.album, - album_art_file: row.album_art_file - }); - } - } - - res.json(albums); - }); - }); - - mstream.get('/db/albums', function (req, res) { - var albums = {"albums":[]}; - - // TODO: Seperate albums with same name by different artists - var sql = "SELECT album, album_art_file FROM items WHERE user = ? GROUP BY album ORDER BY album COLLATE NOCASE ASC;"; - db.all(sql, req.user.username, function(err, rows) { - if(err){ - res.status(500).json({ error: 'DB Error' }); - return; - } - - for (var i = 0; i < rows.length; i++) { - if(rows[i].album){ - albums.albums.push({ - name: rows[i].album, - album_art_file: rows[i].album_art_file - }); - } - } - - res.json(albums); - }); - }); - - mstream.post('/db/album-songs', function (req, res) { - var sql = "SELECT title, album_art_file, artist, album, hash, format, year, cast(path as TEXT), track FROM items WHERE album = ? AND user = ? ORDER BY track ASC;"; - var searchTerms = []; - searchTerms.push(req.body.album); - searchTerms.push(req.user.username); - - db.all(sql, searchTerms, function(err, rows) { - if(err){ - res.status(500).json({ error: 'DB Error' }); - return; - } - - var songs = []; - // Format data for API - for(var i in rows ){ - var path = String(rows[i]['cast(path as TEXT)']); - var relativePath = fe.relative(req.user.musicDir, path); - relativePath = relativePath.replace(/\\/g, '/'); - - songs.push({ - "filepath": relativePath, - "metadata": { - "hash": rows[i].hash, - "artist": rows[i].artist, - "album": rows[i].album, - "track": rows[i].track, - "title": rows[i].title, - "year": rows[i].year, - "album-art": rows[i].album_art_file, - "filename": fe.basename( path ) - } - }) - } - - res.json(songs); - }); - }); - -} diff --git a/modules/db-write/database-default-sqlite.js b/modules/db-write/database-default-sqlite.js deleted file mode 100644 index fd015d8..0000000 --- a/modules/db-write/database-default-sqlite.js +++ /dev/null @@ -1,104 +0,0 @@ -// functions that store data into the SQLite DB - // These functions will take in JSON arrays of song data and then save that dat to the DB -var sqlite3; - -try{ - sqlite3 = require('sqlite3').verbose(); -}catch(e){ - console.log(e); -} -var db; - -exports.setup = function(dbPath){ - try{ - db = new sqlite3.Database(dbPath); - }catch(e){ - console.log(e); - } -} - -exports.getUserFiles = function(thisUser, callback){ - db.all("SELECT path, file_modified_date FROM items WHERE user = ?;", thisUser.username, function(err, rows){ - // Format results - if(!rows){ - rows = []; - } - // callback function - callback(rows); - }); -} - -/** - * @param arrayOfSongs - * @param username - * @return Promise - */ -exports.insertEntries = function(arrayOfSongs, username){ - var sql2 = "insert into items (title,artist,year,album,path,format, track, disk, user, filesize, file_modified_date, file_created_date, hash, album_art_file) values "; - var sqlParser = []; - - while(arrayOfSongs.length > 0) { - var song = arrayOfSongs.pop(); - - var songTitle = null; - var songYear = null; - var songAlbum = null; - var artistString = null; - - if(song.artist && song.artist.length > 0){ - artistString = song.artist; - } - if(song.title && song.title.length > 0){ - songTitle = song.title; - } - if(song.year){ - songYear = song.year; - } - if(song.album && song.album.length > 0){ - songAlbum = song.album; - } - - sql2 += "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?), "; - sqlParser.push(songTitle); - sqlParser.push(artistString); - sqlParser.push(songYear); - sqlParser.push(songAlbum); - sqlParser.push(song.filePath); - sqlParser.push(song.format); - sqlParser.push(song.track.no); - sqlParser.push(song.disk.no); - sqlParser.push(username); - sqlParser.push(song.filesize); - sqlParser.push(song.modified); - sqlParser.push(song.created); - sqlParser.push(song.hash); - sqlParser.push(song.albumArtFilename); - } - - sql2 = sql2.slice(0, -2); - sql2 += ";"; - - return new Promise(function(resolve, reject) { - db.run(sql2, sqlParser, function(err) { - if(err) - reject(err); - else - resolve(); - }); - }); -} - - - -// TODO: Function that removes all files from the given DB -exports.purgeDB = function(){ - -} - - -exports.deleteFile = function(path, user, callback){ - let sql = "DELETE FROM items WHERE path = ? AND user = ?;"; - db.run(sql, [path, user], function() { - callback(); - }); -} diff --git a/modules/download.js b/modules/download.js index a3ffd41..0615d9c 100644 --- a/modules/download.js +++ b/modules/download.js @@ -23,10 +23,8 @@ exports.setup = function(mstream, program){ //streaming magic archive.pipe(res); - var fileArray; - - // Get the POSTed files + var fileArray; if(req.allowedFiles){ fileArray = allowedFiles; }else{ @@ -35,10 +33,12 @@ exports.setup = function(mstream, program){ for(var i in fileArray) { // TODO: Confirm each item in posted data is a real file - var fileString = fileArray[i]; - - // TODO: Add file by ataching user's musicdir to the relative directory supplied - archive.file(fe.join( req.user.musicDir, fileString), { name: fe.basename(fileString) }); + let pathInfo = program.getVPathInfo(fileArray[i]); + if(pathInfo == false){ + console.log('Bad Path'); + continue; + } + archive.file(pathInfo.fullPath, { name: fe.basename(fileArray[i]) }); } archive.finalize(); diff --git a/modules/file-explorer.js b/modules/file-explorer.js index 4c07250..6008ad6 100644 --- a/modules/file-explorer.js +++ b/modules/file-explorer.js @@ -9,14 +9,39 @@ exports.setup = function(mstream, program){ var directories = []; var filesArray = []; - var directory = ''; - if(req.body.dir){ - directory = req.body.dir; + // Return vpaths if no path is given + if(req.body.dir === '' || req.body.dir === '/' ){ + for(let dir of req.user.vpaths){ + directories.push({ + type:"directory", + name: dir + }) + } + return res.json( { path: '/', contents: directories} ); } - var path = fe.join(req.user.musicDir, directory); + var directory = req.body.dir; + console.log(directory) + + + + let pathInfo = program.getVPathInfo(directory); + console.log(pathInfo) + if(pathInfo == false){ + res.status(500).json({ error: 'Could not find file' }); + return; + } + + // Make sure the user has access to the given vpath and that the vapth exists + if(!req.user.vpaths.includes(pathInfo.vpath) ){ + res.status(500).json({ error: 'Access Denied' }); + return; + } + + var path = pathInfo.fullPath; + // Make sure it's a directory - if(!fs.statSync( path).isDirectory()){ + if(!fs.statSync(path).isDirectory()){ res.status(500).json({ error: 'Not a directory' }); return; } diff --git a/modules/login.js b/modules/login.js index c7d627d..7acd787 100644 --- a/modules/login.js +++ b/modules/login.js @@ -1,8 +1,10 @@ exports.setup = function(mstream, program, express){ - const jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens - const uuidV4 = require('uuid/v4'); + const jwt = require('jsonwebtoken'); const crypto = require('crypto'); + // Convenience variable + var Users = program.users; + // Crypto Config var hashConfig = { // size of the generated hash @@ -14,64 +16,37 @@ exports.setup = function(mstream, program, express){ encoding : 'base64' }; - // TODO: Add New user functionality - // Check for root user and password - // Add credentials to user array // TODO: Need a way to store and use already hashed passwords - + // TODO: Add/delete user functionality // TODO: password change function - mstream.post('/change-password-request', function (req, res) { - // Get email address from request - // validate email against user array - // Generate change password token - // Invalidate all other change password tokens - // Email the user the token - res.status(500).json( {error: 'Coming Soon'} ); - }); - - mstream.post('/change-password', function (req, res){ - // Check token - // Get new password - // Hash password and update user array - - res.status(500).json( {error: 'Coming Soon'} ); - }); - - mstream.post('/sunset-user', function(req,res){ - // Removes all user info - res.status(500).json( {error: 'Coming Soon'} ); - }); - - mstream.post('/add-user', function(req,res){ - // Add a user - res.status(500).json( {error: 'Coming Soon'} ); - }); - - - // Create the user array - var Users = program.users; - var permissionsMap = {}; + // mstream.post('/change-password-request', function (req, res) { + // // Get email address from request + // // validate email against user array + // // Generate change password token + // // Invalidate all other change password tokens + // // Email the user the token + // res.status(500).json( {error: 'Coming Soon'} ); + // }); + // mstream.post('/change-password', function (req, res){ + // // Check token + // // Get new password + // // Hash password and update user array + // res.status(500).json( {error: 'Coming Soon'} ); + // }); + // mstream.post('/sunset-user', function(req,res){ + // // Removes all user info + // res.status(500).json( {error: 'Coming Soon'} ); + // }); + // mstream.post('/add-user', function(req,res){ + // // Add a user + // res.status(500).json( {error: 'Coming Soon'} ); + // }); + // Loop through users and setup passwords for (let username in Users) { - // Setup user password generateSaltedPassword(username, Users[username]["password"]); - - // If dir has not been added yet - if ( !(Users[username].musicDir in permissionsMap) ){ - // Generate unique vPath if necessary - // The best way is to store the vPath in the JSON file - if(!Users[username].vPath){ - Users[username].vPath = uuidV4(); - } - - // Add to permissionsMap - permissionsMap[Users[username].musicDir] = Users[username].vPath; - }else{ - Users[username].vPath = permissionsMap[Users[username].musicDir]; - } - } @@ -104,10 +79,6 @@ exports.setup = function(mstream, program, express){ res.status(598).json({error:'Access Denied'}); }); - mstream.get('/guest-access-denied', function (req, res) { - res.status(597).json({error:'Access Denied'}); - }); - // Authenticate User mstream.post('/login', function(req, res) { if(!req.body.username || !req.body.password){ @@ -130,14 +101,10 @@ exports.setup = function(mstream, program, express){ return res.redirect('/login-failed'); } - var vPath = Users[username].vPath; - // return the information including token as JSON res.json( { - success: true, - message: 'Welcome To mStream', - vPath: vPath, + vpaths: Users[username].vpaths, token: jwt.sign({username: username}, program.secret) // Make the token } ); @@ -162,12 +129,8 @@ exports.setup = function(mstream, program, express){ // User may access those files and no others if(decoded.shareToken && decoded.shareToken === true){ // We limit the endpoints to download and anythign in the allowedFiles array - // TODO: There's gotta be a better way to handle vpaths - // TODO: Add vpath to allowedFiles when it's created ??? - - // TODO: fix this hacky shit. vPAths aren't gauranteed to be 38 chars long - if(req.path !== '/download' && decoded.allowedFiles.indexOf(decodeURIComponent(req.path.substring(38))) === -1){ // The substring is to cut out the vPath - return res.redirect('/guest-access-denied'); + if(req.path !== '/download' && decoded.allowedFiles.indexOf(decodeURIComponent(req.path)) === -1){ + return res.redirect('/access-denied'); } req.allowedFiles = decoded.allowedFiles; next(); @@ -176,20 +139,14 @@ exports.setup = function(mstream, program, express){ // Check for any hardcoded restrictions baked right into token if(decoded.restrictedFunctions && decoded.restrictedFunctions.indexOf(req.path) != -1){ - return res.redirect('/guest-access-denied'); + return res.redirect('/access-denied'); } - // TODO: Verify that users in token exist and vPath matches - // TODO: Longterm goal - use vPath from request variable instead of having the user manually add it + // Setup User variable for api endpoints to access req.user = Users[decoded.username]; req.user.username = decoded.username; next(); }); }); - - // Setup Music Dirs here so they are protected by middleware - for (var key in permissionsMap) { - mstream.use( '/' + permissionsMap[key] + '/' , express.static( key )); - } } diff --git a/mstream-command-line-boot-wrapper.js b/mstream-command-line-boot-wrapper.js index 62884c5..7f6f5ab 100755 --- a/mstream-command-line-boot-wrapper.js +++ b/mstream-command-line-boot-wrapper.js @@ -1,16 +1,40 @@ #!/usr/bin/env node "use strict"; +const fe = require('path'); +const fs = require('fs'); +// Check if we are in an electron enviroment if(process.versions['electron']){ + // off to a seperate electron boot enviroment require('./mstream-electron.js'); -}else{ - // Get the server config - const program = require('./modules/configure-json-file.js').setup(process.argv, __dirname); - if(program.error){ - console.log(program.error); - process.exit(); - } - - const serve = require('./mstream.js'); - serve.serveit(program); + return; } + +var program; +try{ + console.log(fs.readFileSync(process.argv[process.argv.length-1], "utf8")) + if(fe.extname(process.argv[process.argv.length-1]) === '.json' && fs.statSync(process.argv[process.argv.length-1]).isFile()){ + let loadJson = JSON.parse(fs.readFileSync(process.argv[process.argv.length-1], 'utf8')); + program = require('./modules/configure-json-file.js').setup(loadJson, __dirname); + }else{ + // User did not provide a JSON file + program = require('./modules/configure-commander.js').setup(process.argv); + } +}catch(error){ + // This condition is hit only if the user entered a json file as an argument and the file did not exist or is invalid JSON + console.log("ERROR: Failed to parse JSON file"); + console.log(error); + process.exit(1); +} +console.log(program) + +// Check for errors +if(program.error){ + console.log(program) + console.log(program.error); + process.exit(1); +} + +// Boot the server +const serve = require('./mstream.js'); +serve.serveit(program); diff --git a/mstream.js b/mstream.js index 59313a4..533f2d3 100755 --- a/mstream.js +++ b/mstream.js @@ -69,6 +69,41 @@ exports.serveit = function (program, callback) { // Move to after login systm mstream.use( '/album-art', express.static(program.albumArtDir )); + // This is a convenience function. It gets the vPath from any url string + program.getVPathInfo = function(url){ + // remove leading slashes + if(url.charAt(0) === '/'){ + url = url.substr(1); + } + + var fileArray = url.split('/'); + console.log(fileArray) + var vpath = fileArray.shift(); + console.log(fileArray) + + // Make sure the path exists + if(!program.folders[vpath]){ + return false; + } + var baseDir = program.folders[vpath].root; + var newPath = ''; + for(var dir of fileArray){ + if(dir === ''){ + continue; + } + console.log(dir) + newPath += dir + '/' ; + } + + console.log(newPath) + var fullpath = fe.join( baseDir, newPath) + return { + vpath: vpath, + basePath: baseDir, + relativePath: newPath, + fullPath: fullpath + }; + } // Setup Secret for JWT try{ @@ -101,27 +136,30 @@ exports.serveit = function (program, callback) { require('./modules/login.js').setup(mstream, program, express); program.auth = true; }else{ - // Store the vPath incase any of the plugins need it - program.vPath = 'music-vpath'; - - program.users= { + program.users = { "mstream-user":{ - musicDir: program.musicDir, - vPath: program.vPath, - username: "mstream-user" + vpaths: [], + username: "mstream-user", + admin: true } } - // Fill in the necessary data + // Fill iin user vpaths + for (var key in program.folders) { + program.users['mstream-user'].vpaths.push(key); + } + + // Fill in the necessary middleware mstream.use(function(req, res, next) { - req.user = { - username:"mstream-user", - musicDir:program.musicDir, - vPath: program.vPath - }; + req.user = program.users['mstream-user']; next(); }); + } - mstream.use( '/' + program.vPath + '/' , express.static( program.musicDir )); + // Setup all folders with express static + for (var key in program.folders) { + console.log(key) + console.log(program.folders[key]) + mstream.use( '/' + key + '/' , express.static( program.folders[key].root )); } // Test function @@ -129,7 +167,7 @@ exports.serveit = function (program, callback) { mstream.get('/ping', function(req, res){ // TODO: Guest status res.json({ - vPath: req.user.vPath, + vpaths: req.user.vpaths, guest: false }); });