diff options
author | Johannes Zellner <johannes@cloudron.io> | 2020-03-03 17:57:28 +0100 |
---|---|---|
committer | Johannes Zellner <johannes@cloudron.io> | 2020-03-03 17:57:28 +0100 |
commit | 313dfe99cf8f763b36f333c5072e2430a6b7941f (patch) | |
tree | 520922a7f374b816901345fb087d66868eeff954 | |
parent | 33ee47f3ca0322ccb19153cafa1c1f7b886dc61a (diff) | |
download | Surfer-313dfe99cf8f763b36f333c5072e2430a6b7941f.tar.gz Surfer-313dfe99cf8f763b36f333c5072e2430a6b7941f.tar.zst Surfer-313dfe99cf8f763b36f333c5072e2430a6b7941f.zip |
Use custom public folder listing
-rw-r--r-- | frontend/404.html | 2 | ||||
-rw-r--r-- | frontend/js/public.js | 144 | ||||
-rw-r--r-- | frontend/public.html | 89 | ||||
-rw-r--r-- | package-lock.json | 50 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rwxr-xr-x | server.js | 24 | ||||
-rw-r--r-- | src/auth.js | 17 |
7 files changed, 262 insertions, 65 deletions
diff --git a/frontend/404.html b/frontend/404.html index c660424..15da5c2 100644 --- a/frontend/404.html +++ b/frontend/404.html | |||
@@ -9,7 +9,7 @@ | |||
9 | <body> | 9 | <body> |
10 | 10 | ||
11 | <div class="container-center"> | 11 | <div class="container-center"> |
12 | <p>File not found</p> | 12 | <p>File or directory not found</p> |
13 | </div> | 13 | </div> |
14 | 14 | ||
15 | </body> | 15 | </body> |
diff --git a/frontend/js/public.js b/frontend/js/public.js new file mode 100644 index 0000000..c295a05 --- /dev/null +++ b/frontend/js/public.js | |||
@@ -0,0 +1,144 @@ | |||
1 | (function () { | ||
2 | 'use strict'; | ||
3 | |||
4 | /* global superagent */ | ||
5 | /* global Vue */ | ||
6 | /* global $ */ | ||
7 | /* global filesize */ | ||
8 | |||
9 | function sanitize(filePath) { | ||
10 | filePath = '/' + filePath; | ||
11 | return filePath.replace(/\/+/g, '/'); | ||
12 | } | ||
13 | |||
14 | function encode(filePath) { | ||
15 | return filePath.split('/').map(encodeURIComponent).join('/'); | ||
16 | } | ||
17 | |||
18 | function decode(filePath) { | ||
19 | return filePath.split('/').map(decodeURIComponent).join('/'); | ||
20 | } | ||
21 | |||
22 | var mimeTypes = { | ||
23 | images: [ '.png', '.jpg', '.jpeg', '.tiff', '.gif' ], | ||
24 | text: [ '.txt', '.md' ], | ||
25 | pdf: [ '.pdf' ], | ||
26 | html: [ '.html', '.htm', '.php' ], | ||
27 | video: [ '.mp4', '.mpg', '.mpeg', '.ogg', '.mkv', '.avi', '.mov' ] | ||
28 | }; | ||
29 | |||
30 | function getPreviewUrl(entry, basePath) { | ||
31 | var path = '/_admin/img/'; | ||
32 | |||
33 | if (entry.isDirectory) return path + 'directory.png'; | ||
34 | if (mimeTypes.images.some(function (e) { return entry.filePath.endsWith(e); })) return sanitize(basePath + '/' + entry.filePath); | ||
35 | if (mimeTypes.text.some(function (e) { return entry.filePath.endsWith(e); })) return path +'text.png'; | ||
36 | if (mimeTypes.pdf.some(function (e) { return entry.filePath.endsWith(e); })) return path + 'pdf.png'; | ||
37 | if (mimeTypes.html.some(function (e) { return entry.filePath.endsWith(e); })) return path + 'html.png'; | ||
38 | if (mimeTypes.video.some(function (e) { return entry.filePath.endsWith(e); })) return path + 'video.png'; | ||
39 | |||
40 | return path + 'unknown.png'; | ||
41 | } | ||
42 | |||
43 | // simple extension detection, does not work with double extension like .tar.gz | ||
44 | function getExtension(entry) { | ||
45 | if (entry.isFile) return entry.filePath.slice(entry.filePath.lastIndexOf('.') + 1); | ||
46 | return ''; | ||
47 | } | ||
48 | |||
49 | function loadDirectory() { | ||
50 | app.busy = true; | ||
51 | |||
52 | var filePath = sanitize(window.location.pathname); | ||
53 | |||
54 | app.path = filePath; | ||
55 | |||
56 | superagent.get('/api/files/' + encode(filePath)).query({ access_token: localStorage.accessToken }).end(function (error, result) { | ||
57 | app.busy = false; | ||
58 | |||
59 | if (result && result.statusCode === 401) return logout(); | ||
60 | if (error) return console.error(error); | ||
61 | |||
62 | result.body.entries.sort(function (a, b) { return a.isDirectory && b.isFile ? -1 : 1; }); | ||
63 | app.entries = result.body.entries.map(function (entry) { | ||
64 | entry.previewUrl = getPreviewUrl(entry, filePath); | ||
65 | entry.extension = getExtension(entry); | ||
66 | entry.rename = false; | ||
67 | entry.filePathNew = entry.filePath; | ||
68 | return entry; | ||
69 | }); | ||
70 | app.path = filePath; | ||
71 | app.pathParts = decode(filePath).split('/').filter(function (e) { return !!e; }).map(function (e, i, a) { | ||
72 | return { | ||
73 | name: e, | ||
74 | link: '#' + sanitize('/' + a.slice(0, i).join('/') + '/' + e) | ||
75 | }; | ||
76 | }); | ||
77 | }); | ||
78 | } | ||
79 | |||
80 | function open(row, column, event) { | ||
81 | var fullPath = encode(sanitize(app.path + '/' + row.filePath)); | ||
82 | |||
83 | if (row.isDirectory) return window.location.href = fullPath; | ||
84 | |||
85 | app.activeEntry = row; | ||
86 | app.activeEntry.fullPath = fullPath; | ||
87 | app.previewDrawerVisible = true | ||
88 | |||
89 | // need to wait for DOM element to exist | ||
90 | setTimeout(function () { | ||
91 | $('iframe').on('load', function (e) { | ||
92 | if (!e.target.contentWindow.document.body) return; | ||
93 | |||
94 | e.target.contentWindow.document.body.style.display = 'flex' | ||
95 | e.target.contentWindow.document.body.style.justifyContent = 'center' | ||
96 | }); | ||
97 | }, 0); | ||
98 | } | ||
99 | |||
100 | var app = new Vue({ | ||
101 | el: '#app', | ||
102 | data: { | ||
103 | ready: false, | ||
104 | busy: false, | ||
105 | path: '', | ||
106 | previewDrawerVisible: false, | ||
107 | activeEntry: {}, | ||
108 | entries: [] | ||
109 | }, | ||
110 | methods: { | ||
111 | onDownload: function (entry) { | ||
112 | if (entry.isDirectory) return; | ||
113 | window.location.href = encode('/api/files/' + sanitize(this.path + '/' + entry.filePath)) + '?access_token=' + localStorage.accessToken; | ||
114 | }, | ||
115 | prettyDate: function (row, column, cellValue, index) { | ||
116 | var date = new Date(cellValue), | ||
117 | diff = (((new Date()).getTime() - date.getTime()) / 1000), | ||
118 | day_diff = Math.floor(diff / 86400); | ||
119 | |||
120 | if (isNaN(day_diff) || day_diff < 0) | ||
121 | return; | ||
122 | |||
123 | return day_diff === 0 && ( | ||
124 | diff < 60 && 'just now' || | ||
125 | diff < 120 && '1 minute ago' || | ||
126 | diff < 3600 && Math.floor( diff / 60 ) + ' minutes ago' || | ||
127 | diff < 7200 && '1 hour ago' || | ||
128 | diff < 86400 && Math.floor( diff / 3600 ) + ' hours ago') || | ||
129 | day_diff === 1 && 'Yesterday' || | ||
130 | day_diff < 7 && day_diff + ' days ago' || | ||
131 | day_diff < 31 && Math.ceil( day_diff / 7 ) + ' weeks ago' || | ||
132 | day_diff < 365 && Math.round( day_diff / 30 ) + ' months ago' || | ||
133 | Math.round( day_diff / 365 ) + ' years ago'; | ||
134 | }, | ||
135 | prettyFileSize: function (row, column, cellValue, index) { | ||
136 | return filesize(cellValue); | ||
137 | }, | ||
138 | loadDirectory: loadDirectory, | ||
139 | open: open, | ||
140 | } | ||
141 | }); | ||
142 | |||
143 | loadDirectory(); | ||
144 | })(); \ No newline at end of file | ||
diff --git a/frontend/public.html b/frontend/public.html new file mode 100644 index 0000000..2ddf543 --- /dev/null +++ b/frontend/public.html | |||
@@ -0,0 +1,89 @@ | |||
1 | <html> | ||
2 | <head> | ||
3 | <title> Surfer </title> | ||
4 | |||
5 | <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> | ||
6 | |||
7 | <link rel="icon" type="image/png" href="/_admin/img/logo.png"> | ||
8 | |||
9 | <link rel="stylesheet" href="/_admin/css/theme-chalk_2.11.1.css"> | ||
10 | <link rel="stylesheet" href="/_admin/css/style.css"> | ||
11 | |||
12 | <script src="/_admin/js/jquery-1.12.1.min.js"></script> | ||
13 | <script src="/_admin/js/vue.min.js"></script> | ||
14 | <script src="/_admin/js/element-ui_2.11.1.min.js"></script> | ||
15 | <script src="/_admin/js/element-ui_en_2.11.1.min.js"></script> | ||
16 | <script src="/_admin/js/filesize.min.js"></script> | ||
17 | <script src="/_admin/js/superagent.js"></script> | ||
18 | |||
19 | </head> | ||
20 | <body> | ||
21 | |||
22 | <div id="app"> | ||
23 | |||
24 | <el-container> | ||
25 | <el-header> | ||
26 | <el-row type="flex" justify="space-between"> | ||
27 | <div style="flex-grow: 2; padding: 0 7px;"> | ||
28 | <p style="font-size: 24px; margin: 4px 0;">{{ path }}</p> | ||
29 | </div> | ||
30 | <div> | ||
31 | <a href="/_admin"> | ||
32 | <el-button type="primary" icon="el-icon-user" size="small">Login</el-button> | ||
33 | </a> | ||
34 | </div> | ||
35 | </el-row> | ||
36 | </el-header> | ||
37 | <el-main> | ||
38 | |||
39 | <div v-show="busy"> | ||
40 | <center><h1><i class="el-icon-loading"></i></h1></center> | ||
41 | </div> | ||
42 | |||
43 | <div v-show="!busy && entries.length" v-cloak> | ||
44 | <center> | ||
45 | <el-table :data="entries" style="max-width: 1280px; width: 100%" height="100%" empty-text="Folder is emtpy" :default-sort="{ prop: 'filePath', order: 'descending' }" @row-click="open"> | ||
46 | <el-table-column prop="previewUrl" label="Type" width="80px" sortable> | ||
47 | <template slot-scope="scope"> | ||
48 | <el-image v-bind:src="scope.row.previewUrl" class="list-icon" style="width: 32px; height: 32px" fit="cover"></el-image> | ||
49 | </template> | ||
50 | </el-table-column> | ||
51 | <el-table-column prop="filePath" label="Name" sortable></el-table-column> | ||
52 | <el-table-column prop="size" label="Size" width="150px" sortable :formatter="prettyFileSize"></el-table-column> | ||
53 | <el-table-column prop="mtime" label="Modified" width="150px" sortable :formatter="prettyDate"></el-table-column> | ||
54 | <el-table-column label="Actions" align="right" width="200px" class-name="list-actions"> | ||
55 | <template slot-scope="scope"> | ||
56 | <el-button size="small" icon="el-icon-download" type="text" plain circle v-show="scope.row.isFile" @click.stop="onDownload(scope.row)"></el-button> | ||
57 | </template> | ||
58 | </el-table-column> | ||
59 | </el-table> | ||
60 | </center> | ||
61 | </div> | ||
62 | |||
63 | <div v-show="!busy && !entries.length"> | ||
64 | <center> | ||
65 | Folder is empty | ||
66 | </center> | ||
67 | </div> | ||
68 | |||
69 | <el-drawer :title="activeEntry.filePath":with-header="false" :visible.sync="previewDrawerVisible" direction="rtl" size="50%"> | ||
70 | <div style="display: flex; flex-direction: column; height: 100%;"> | ||
71 | <iframe :src="activeEntry.fullPath" style="width: 100%; height: 100%; border: none; margin: 10px;"></iframe> | ||
72 | <center> | ||
73 | <el-button size="small" icon="el-icon-download" style="margin: 10px;" @click.stop="onDownload(activeEntry)">Download</el-button> | ||
74 | <a :href="activeEntry.fullPath" target="_blank"> | ||
75 | <el-button size="small" icon="el-icon-link" style="margin: 10px;">Open</el-button> | ||
76 | </a> | ||
77 | </center> | ||
78 | </div> | ||
79 | </el-drawer> | ||
80 | |||
81 | </el-main> | ||
82 | </el-container> | ||
83 | |||
84 | </div> | ||
85 | |||
86 | <script src="/_admin/js/public.js"></script> | ||
87 | |||
88 | </body> | ||
89 | </html> | ||
diff --git a/package-lock.json b/package-lock.json index ca6666b..f1d69fb 100644 --- a/package-lock.json +++ b/package-lock.json | |||
@@ -160,11 +160,6 @@ | |||
160 | } | 160 | } |
161 | } | 161 | } |
162 | }, | 162 | }, |
163 | "batch": { | ||
164 | "version": "0.6.1", | ||
165 | "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", | ||
166 | "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" | ||
167 | }, | ||
168 | "bcrypt-pbkdf": { | 163 | "bcrypt-pbkdf": { |
169 | "version": "1.0.1", | 164 | "version": "1.0.1", |
170 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", | 165 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", |
@@ -1997,51 +1992,6 @@ | |||
1997 | } | 1992 | } |
1998 | } | 1993 | } |
1999 | }, | 1994 | }, |
2000 | "serve-index": { | ||
2001 | "version": "1.9.1", | ||
2002 | "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", | ||
2003 | "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", | ||
2004 | "requires": { | ||
2005 | "accepts": "~1.3.4", | ||
2006 | "batch": "0.6.1", | ||
2007 | "debug": "2.6.9", | ||
2008 | "escape-html": "~1.0.3", | ||
2009 | "http-errors": "~1.6.2", | ||
2010 | "mime-types": "~2.1.17", | ||
2011 | "parseurl": "~1.3.2" | ||
2012 | }, | ||
2013 | "dependencies": { | ||
2014 | "depd": { | ||
2015 | "version": "1.1.1", | ||
2016 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", | ||
2017 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" | ||
2018 | }, | ||
2019 | "http-errors": { | ||
2020 | "version": "1.6.2", | ||
2021 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", | ||
2022 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", | ||
2023 | "requires": { | ||
2024 | "depd": "1.1.1", | ||
2025 | "inherits": "2.0.3", | ||
2026 | "setprototypeof": "1.0.3", | ||
2027 | "statuses": ">= 1.3.1 < 2" | ||
2028 | } | ||
2029 | }, | ||
2030 | "mime-db": { | ||
2031 | "version": "1.33.0", | ||
2032 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", | ||
2033 | "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" | ||
2034 | }, | ||
2035 | "mime-types": { | ||
2036 | "version": "2.1.18", | ||
2037 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", | ||
2038 | "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", | ||
2039 | "requires": { | ||
2040 | "mime-db": "~1.33.0" | ||
2041 | } | ||
2042 | } | ||
2043 | } | ||
2044 | }, | ||
2045 | "serve-static": { | 1995 | "serve-static": { |
2046 | "version": "1.13.1", | 1996 | "version": "1.13.1", |
2047 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", | 1997 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", |
diff --git a/package.json b/package.json index 9c8c6c5..49f20c1 100644 --- a/package.json +++ b/package.json | |||
@@ -40,7 +40,6 @@ | |||
40 | "readline-sync": "^1.4.9", | 40 | "readline-sync": "^1.4.9", |
41 | "request": "^2.83.0", | 41 | "request": "^2.83.0", |
42 | "safetydance": "^0.1.1", | 42 | "safetydance": "^0.1.1", |
43 | "serve-index": "^1.9.1", | ||
44 | "superagent": "^5.1.3", | 43 | "superagent": "^5.1.3", |
45 | "underscore": "^1.8.3", | 44 | "underscore": "^1.8.3", |
46 | "uuid": "^3.2.1", | 45 | "uuid": "^3.2.1", |
@@ -16,7 +16,6 @@ var express = require('express'), | |||
16 | multipart = require('./src/multipart'), | 16 | multipart = require('./src/multipart'), |
17 | mkdirp = require('mkdirp'), | 17 | mkdirp = require('mkdirp'), |
18 | auth = require('./src/auth.js'), | 18 | auth = require('./src/auth.js'), |
19 | serveIndex = require('serve-index'), | ||
20 | webdav = require('webdav-server').v2, | 19 | webdav = require('webdav-server').v2, |
21 | files = require('./src/files.js')(path.resolve(__dirname, process.argv[2] || 'files')); | 20 | files = require('./src/files.js')(path.resolve(__dirname, process.argv[2] || 'files')); |
22 | 21 | ||
@@ -49,7 +48,7 @@ function setSettings(req, res, next) { | |||
49 | 48 | ||
50 | // Load the config file | 49 | // Load the config file |
51 | try { | 50 | try { |
52 | console.log(`Using config file: ${CONFIG_FILE}`); | 51 | console.log(`Using config file at: ${CONFIG_FILE}`); |
53 | config = require(CONFIG_FILE); | 52 | config = require(CONFIG_FILE); |
54 | } catch (e) { | 53 | } catch (e) { |
55 | if (e.code === 'MODULE_NOT_FOUND') console.log(`Config file ${CONFIG_FILE} not found`); | 54 | if (e.code === 'MODULE_NOT_FOUND') console.log(`Config file ${CONFIG_FILE} not found`); |
@@ -68,7 +67,7 @@ var webdavServer = new webdav.WebDAVServer({ | |||
68 | }); | 67 | }); |
69 | 68 | ||
70 | webdavServer.setFileSystem('/', new webdav.PhysicalFileSystem(ROOT_FOLDER), function (success) { | 69 | webdavServer.setFileSystem('/', new webdav.PhysicalFileSystem(ROOT_FOLDER), function (success) { |
71 | console.log(`Mounting ${ROOT_FOLDER} as webdav resource`, success); | 70 | if (success) console.log(`Mounting webdav resource from: ${ROOT_FOLDER}`); |
72 | }); | 71 | }); |
73 | 72 | ||
74 | var multipart = multipart({ maxFieldsSize: 2 * 1024, limit: '512mb', timeout: 3 * 60 * 1000 }); | 73 | var multipart = multipart({ maxFieldsSize: 2 * 1024, limit: '512mb', timeout: 3 * 60 * 1000 }); |
@@ -81,7 +80,7 @@ router.get ('/api/tokens', auth.verify, auth.getTokens); | |||
81 | router.post ('/api/tokens', auth.verify, auth.createToken); | 80 | router.post ('/api/tokens', auth.verify, auth.createToken); |
82 | router.delete('/api/tokens/:token', auth.verify, auth.delToken); | 81 | router.delete('/api/tokens/:token', auth.verify, auth.delToken); |
83 | router.get ('/api/profile', auth.verify, auth.getProfile); | 82 | router.get ('/api/profile', auth.verify, auth.getProfile); |
84 | router.get ('/api/files/*', auth.verify, files.get); | 83 | router.get ('/api/files/*', auth.verifyIfNeeded, files.get); |
85 | router.post ('/api/files/*', auth.verify, multipart, files.post); | 84 | router.post ('/api/files/*', auth.verify, multipart, files.post); |
86 | router.put ('/api/files/*', auth.verify, files.put); | 85 | router.put ('/api/files/*', auth.verify, files.put); |
87 | router.delete('/api/files/*', auth.verify, files.del); | 86 | router.delete('/api/files/*', auth.verify, files.del); |
@@ -101,17 +100,22 @@ app.use('/', function welcomePage(req, res, next) { | |||
101 | if (config.folderListingEnabled || req.path !== '/') return next(); | 100 | if (config.folderListingEnabled || req.path !== '/') return next(); |
102 | res.status(200).sendFile(path.join(__dirname, '/frontend/welcome.html')); | 101 | res.status(200).sendFile(path.join(__dirname, '/frontend/welcome.html')); |
103 | }); | 102 | }); |
104 | app.use('/', function (req, res, next) { | 103 | app.use('/', function (req, res) { |
105 | if (config.folderListingEnabled) return next(); | 104 | if (!config.folderListingEnabled) return res.status(404).sendFile(__dirname + '/frontend/404.html'); |
106 | res.status(404).sendFile(__dirname + '/frontend/404.html'); | 105 | |
106 | if (!fs.existsSync(path.join(ROOT_FOLDER, req.path))) return res.status(404).sendFile(__dirname + '/frontend/404.html'); | ||
107 | |||
108 | res.status(200).sendFile(__dirname + '/frontend/public.html'); | ||
107 | }); | 109 | }); |
108 | app.use('/', serveIndex(ROOT_FOLDER, { icons: true })); | ||
109 | app.use(lastMile()); | 110 | app.use(lastMile()); |
110 | 111 | ||
111 | var server = app.listen(3000, function () { | 112 | var server = app.listen(3000, function () { |
112 | var host = server.address().address; | 113 | var host = server.address().address; |
113 | var port = server.address().port; | 114 | var port = server.address().port; |
114 | 115 | ||
115 | console.log('Surfer listening on http://%s:%s', host, port); | 116 | console.log(`Base path: ${ROOT_FOLDER}`); |
116 | console.log('Using base path', ROOT_FOLDER); | 117 | console.log(); |
118 | console.log(`Listening on http://${host}:${port}`); | ||
119 | |||
120 | auth.init(config); | ||
117 | }); | 121 | }); |
diff --git a/src/auth.js b/src/auth.js index a885d49..5f4c777 100644 --- a/src/auth.js +++ b/src/auth.js | |||
@@ -19,11 +19,13 @@ const LOGIN_TOKEN_PREFIX = 'login-'; | |||
19 | const API_TOKEN_PREFIX = 'api-'; | 19 | const API_TOKEN_PREFIX = 'api-'; |
20 | 20 | ||
21 | if (AUTH_METHOD === 'ldap') { | 21 | if (AUTH_METHOD === 'ldap') { |
22 | console.log('Use ldap auth'); | 22 | console.log('Using ldap auth'); |
23 | } else { | 23 | } else { |
24 | console.log(`Use local auth file ${LOCAL_AUTH_FILE}`); | 24 | console.log(`Using local auth file at: ${LOCAL_AUTH_FILE}`); |
25 | } | 25 | } |
26 | 26 | ||
27 | var gConfig = {}; | ||
28 | |||
27 | var tokenStore = { | 29 | var tokenStore = { |
28 | data: {}, | 30 | data: {}, |
29 | save: function () { | 31 | save: function () { |
@@ -53,7 +55,7 @@ var tokenStore = { | |||
53 | 55 | ||
54 | // load token store data if any | 56 | // load token store data if any |
55 | try { | 57 | try { |
56 | console.log(`Using tokenstore file: ${TOKENSTORE_FILE}`); | 58 | console.log(`Using tokenstore file at: ${TOKENSTORE_FILE}`); |
57 | tokenStore.data = JSON.parse(fs.readFileSync(TOKENSTORE_FILE, 'utf-8')); | 59 | tokenStore.data = JSON.parse(fs.readFileSync(TOKENSTORE_FILE, 'utf-8')); |
58 | } catch (e) { | 60 | } catch (e) { |
59 | // start with empty token store | 61 | // start with empty token store |
@@ -103,6 +105,10 @@ function verifyUser(username, password, callback) { | |||
103 | } | 105 | } |
104 | } | 106 | } |
105 | 107 | ||
108 | exports.init = function (config) { | ||
109 | gConfig = config; | ||
110 | }; | ||
111 | |||
106 | exports.login = function (req, res, next) { | 112 | exports.login = function (req, res, next) { |
107 | verifyUser(req.body.username, req.body.password, function (error, user) { | 113 | verifyUser(req.body.username, req.body.password, function (error, user) { |
108 | if (error) return next(new HttpError(401, 'Invalid credentials')); | 114 | if (error) return next(new HttpError(401, 'Invalid credentials')); |
@@ -130,6 +136,11 @@ exports.verify = function (req, res, next) { | |||
130 | 136 | ||
131 | }; | 137 | }; |
132 | 138 | ||
139 | exports.verifyIfNeeded = function (req, res, next) { | ||
140 | if (!gConfig.folderListingEnabled) return exports.verify(req, res, next); | ||
141 | next(); | ||
142 | }; | ||
143 | |||
133 | exports.logout = function (req, res, next) { | 144 | exports.logout = function (req, res, next) { |
134 | var accessToken = req.query.access_token || req.body.accessToken; | 145 | var accessToken = req.query.access_token || req.body.accessToken; |
135 | 146 | ||