diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | frontend/404.html | 19 | ||||
-rw-r--r-- | frontend/js/app.js | 10 | ||||
-rw-r--r-- | frontend/welcome.html | 5 | ||||
-rwxr-xr-x | server.js | 67 |
5 files changed, 85 insertions, 17 deletions
@@ -1,3 +1,4 @@ | |||
1 | node_modules/ | 1 | node_modules/ |
2 | files/ | 2 | files/ |
3 | .users.json | 3 | .users.json |
4 | .config.json | ||
diff --git a/frontend/404.html b/frontend/404.html new file mode 100644 index 0000000..21fd6b4 --- /dev/null +++ b/frontend/404.html | |||
@@ -0,0 +1,19 @@ | |||
1 | <html> | ||
2 | <head> | ||
3 | <title> Surfer - File not found</title> | ||
4 | |||
5 | <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> | ||
6 | |||
7 | <link rel="stylesheet" href="/_admin/css/style.css"> | ||
8 | </head> | ||
9 | <body> | ||
10 | |||
11 | <div class="wrapper"> | ||
12 | <div class="content"> | ||
13 | <h2> Surfer </h2> | ||
14 | <p>File not found</p> | ||
15 | </div> | ||
16 | </div> | ||
17 | |||
18 | </body> | ||
19 | </html> | ||
diff --git a/frontend/js/app.js b/frontend/js/app.js index 57b831e..e9d469b 100644 --- a/frontend/js/app.js +++ b/frontend/js/app.js | |||
@@ -211,7 +211,9 @@ var app = new Vue({ | |||
211 | }, | 211 | }, |
212 | onOptionsMenu: function (command) { | 212 | onOptionsMenu: function (command) { |
213 | if (command === 'folderListing') { | 213 | if (command === 'folderListing') { |
214 | console.log('Not implemented'); | 214 | superagent.put('/api/settings').send({ folderListingEnabled: this.folderListingEnabled }).query({ access_token: localStorage.accessToken }).end(function (error) { |
215 | if (error) console.error(error); | ||
216 | }); | ||
215 | } else if (command === 'about') { | 217 | } else if (command === 'about') { |
216 | this.$msgbox({ | 218 | this.$msgbox({ |
217 | title: 'About Surfer', | 219 | title: 'About Surfer', |
@@ -337,6 +339,12 @@ getProfile(localStorage.accessToken, function (error) { | |||
337 | if (error) return console.error(error); | 339 | if (error) return console.error(error); |
338 | 340 | ||
339 | loadDirectory(window.location.hash.slice(1)); | 341 | loadDirectory(window.location.hash.slice(1)); |
342 | |||
343 | superagent.get('/api/settings').query({ access_token: localStorage.accessToken }).end(function (error, result) { | ||
344 | if (error) console.error(error); | ||
345 | |||
346 | app.folderListingEnabled = !!result.body.folderListingEnabled; | ||
347 | }); | ||
340 | }); | 348 | }); |
341 | 349 | ||
342 | $(window).on('hashchange', function () { | 350 | $(window).on('hashchange', function () { |
diff --git a/frontend/welcome.html b/frontend/welcome.html index d16dcef..ddc9c36 100644 --- a/frontend/welcome.html +++ b/frontend/welcome.html | |||
@@ -1,9 +1,10 @@ | |||
1 | <html> | 1 | <html> |
2 | <head> | 2 | <head> |
3 | <title> Surfer </title> | 3 | <title> Surfer - Welcome</title> |
4 | 4 | ||
5 | <link rel="stylesheet" href="/_admin/css/style.css"> | 5 | <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> |
6 | 6 | ||
7 | <link rel="stylesheet" href="/_admin/css/style.css"> | ||
7 | </head> | 8 | </head> |
8 | <body> | 9 | <body> |
9 | 10 | ||
@@ -7,17 +7,58 @@ var express = require('express'), | |||
7 | morgan = require('morgan'), | 7 | morgan = require('morgan'), |
8 | passport = require('passport'), | 8 | passport = require('passport'), |
9 | path = require('path'), | 9 | path = require('path'), |
10 | fs = require('fs'), | ||
10 | compression = require('compression'), | 11 | compression = require('compression'), |
11 | session = require('express-session'), | 12 | session = require('express-session'), |
12 | bodyParser = require('body-parser'), | 13 | bodyParser = require('body-parser'), |
13 | cookieParser = require('cookie-parser'), | 14 | cookieParser = require('cookie-parser'), |
14 | lastMile = require('connect-lastmile'), | 15 | lastMile = require('connect-lastmile'), |
16 | HttpError = require('connect-lastmile').HttpError, | ||
17 | HttpSuccess = require('connect-lastmile').HttpSuccess, | ||
15 | multipart = require('./src/multipart'), | 18 | multipart = require('./src/multipart'), |
16 | mkdirp = require('mkdirp'), | 19 | mkdirp = require('mkdirp'), |
17 | auth = require('./src/auth.js'), | 20 | auth = require('./src/auth.js'), |
18 | serveIndex = require('serve-index'), | 21 | serveIndex = require('serve-index'), |
19 | files = require('./src/files.js')(path.resolve(__dirname, process.argv[2] || 'files')); | 22 | files = require('./src/files.js')(path.resolve(__dirname, process.argv[2] || 'files')); |
20 | 23 | ||
24 | |||
25 | var rootFolder = path.resolve(__dirname, process.argv[2] || 'files'); | ||
26 | var configFile = path.resolve(__dirname, process.argv[3] || './config.json'); | ||
27 | |||
28 | // Ensure the root folder exists | ||
29 | mkdirp.sync(rootFolder); | ||
30 | |||
31 | var config = { | ||
32 | folderListingEnabled: true | ||
33 | }; | ||
34 | |||
35 | function getSettings(req, res, next) { | ||
36 | res.send({ folderListingEnabled: !!config.folderListingEnabled }); | ||
37 | } | ||
38 | |||
39 | function setSettings(req, res, next) { | ||
40 | if (typeof req.body.folderListingEnabled === 'undefined') return next(new HttpError(400, 'missing folderListingEnabled boolean')); | ||
41 | |||
42 | config.folderListingEnabled = !!req.body.folderListingEnabled; | ||
43 | |||
44 | fs.writeFile(configFile, JSON.stringify(config), function (error) { | ||
45 | if (error) return next(new HttpError(500, 'unable to save settings')); | ||
46 | |||
47 | next(new HttpSuccess(201, {})); | ||
48 | }); | ||
49 | } | ||
50 | |||
51 | // Load the config file | ||
52 | try { | ||
53 | config = require(configFile); | ||
54 | } catch (e) { | ||
55 | if (e.code === 'MODULE_NOT_FOUND') console.log(`Config file ${configFile} not found`); | ||
56 | else console.log(`Cannot load config file ${configFile}`, e); | ||
57 | } | ||
58 | |||
59 | if (typeof config.folderListingEnabled === 'undefined') config.folderListingEnabled = true; | ||
60 | |||
61 | // Setup the express server and routes | ||
21 | var app = express(); | 62 | var app = express(); |
22 | var router = new express.Router(); | 63 | var router = new express.Router(); |
23 | 64 | ||
@@ -25,6 +66,8 @@ var multipart = multipart({ maxFieldsSize: 2 * 1024, limit: '512mb', timeout: 3 | |||
25 | 66 | ||
26 | router.post ('/api/login', auth.login); | 67 | router.post ('/api/login', auth.login); |
27 | router.post ('/api/logout', auth.verify, auth.logout); | 68 | router.post ('/api/logout', auth.verify, auth.logout); |
69 | router.get ('/api/settings', auth.verify, getSettings); | ||
70 | router.put ('/api/settings', auth.verify, setSettings); | ||
28 | router.get ('/api/profile', auth.verify, auth.getProfile); | 71 | router.get ('/api/profile', auth.verify, auth.getProfile); |
29 | router.get ('/api/files/*', auth.verify, files.get); | 72 | router.get ('/api/files/*', auth.verify, files.get); |
30 | router.post ('/api/files/*', auth.verify, multipart, files.post); | 73 | router.post ('/api/files/*', auth.verify, multipart, files.post); |
@@ -32,14 +75,6 @@ router.put ('/api/files/*', auth.verify, files.put); | |||
32 | router.delete('/api/files/*', auth.verify, files.del); | 75 | router.delete('/api/files/*', auth.verify, files.del); |
33 | router.get ('/api/healthcheck', function (req, res) { res.status(200).send(); }); | 76 | router.get ('/api/healthcheck', function (req, res) { res.status(200).send(); }); |
34 | 77 | ||
35 | // welcome screen in case / does not serve up any file yet | ||
36 | function welcomePage(req, res, next) { | ||
37 | if (req.path !== '/') return next(); | ||
38 | res.status(200).sendFile(path.join(__dirname, '/frontend/welcome.html')); | ||
39 | } | ||
40 | |||
41 | var rootFolder = path.resolve(__dirname, process.argv[2] || 'files'); | ||
42 | |||
43 | app.use(morgan('dev')); | 78 | app.use(morgan('dev')); |
44 | app.use(compression()); | 79 | app.use(compression()); |
45 | app.use('/api', bodyParser.json()); | 80 | app.use('/api', bodyParser.json()); |
@@ -51,7 +86,14 @@ app.use('/api', passport.session()); | |||
51 | app.use(router); | 86 | app.use(router); |
52 | app.use('/_admin', express.static(__dirname + '/frontend')); | 87 | app.use('/_admin', express.static(__dirname + '/frontend')); |
53 | app.use('/', express.static(rootFolder)); | 88 | app.use('/', express.static(rootFolder)); |
54 | app.use('/', welcomePage); | 89 | app.use('/', function welcomePage(req, res, next) { |
90 | if (req.path !== '/') return next(); | ||
91 | res.status(200).sendFile(path.join(__dirname, '/frontend/welcome.html')); | ||
92 | }); | ||
93 | app.use('/', function (req, res, next) { | ||
94 | if (config.folderListingEnabled) return next(); | ||
95 | res.sendFile(__dirname + '/frontend/404.html'); | ||
96 | }); | ||
55 | app.use('/', serveIndex(rootFolder, { icons: true })); | 97 | app.use('/', serveIndex(rootFolder, { icons: true })); |
56 | app.use(lastMile()); | 98 | app.use(lastMile()); |
57 | 99 | ||
@@ -59,9 +101,6 @@ var server = app.listen(3000, function () { | |||
59 | var host = server.address().address; | 101 | var host = server.address().address; |
60 | var port = server.address().port; | 102 | var port = server.address().port; |
61 | 103 | ||
62 | var basePath = path.resolve(__dirname, process.argv[2] || 'files'); | 104 | console.log('Surfer listening on http://%s:%s', host, port); |
63 | mkdirp.sync(basePath); | 105 | console.log('Using base path', rootFolder); |
64 | |||
65 | console.log('Surfer listening at http://%s:%s', host, port); | ||
66 | console.log('Using base path', basePath); | ||
67 | }); | 106 | }); |