Comparing version 0.0.52 to 0.0.53
@@ -21,3 +21,4 @@ /** | ||
'www', | ||
'ftp' | ||
'ftp', | ||
'open-pages' | ||
]; | ||
@@ -40,3 +41,3 @@ | ||
{ | ||
ROOT : __dirname + '../../www', | ||
ROOT : __dirname + '/../www', | ||
LOGIN_TEMPLATE_PATH: __dirname + '/templates/login-www.jade', | ||
@@ -46,4 +47,4 @@ LOGIN_CSS_PATH: __dirname + '/templates/login.css', | ||
AUTH_FORM_SUBMIT_ROUTE: '/api/v1.0/www-auth-submit', | ||
USERS: { | ||
} | ||
USERS: { | ||
} | ||
} | ||
@@ -57,6 +58,20 @@ /** | ||
LOGIN_CSS_PATH: __dirname + '/templates/login.css', | ||
AUTH_FORM_ROUTE: '/api/v1.0/ftp-auth', | ||
AUTH_FORM_SUBMIT_ROUTE: '/api/v1.0/ftp-auth-submit' | ||
AUTH_FORM_ROUTE: '/api/v1.0/ftp-auth', | ||
AUTH_FORM_SUBMIT_ROUTE: '/api/v1.0/ftp-auth-submit' | ||
} | ||
/** | ||
* Open pages | ||
*/ | ||
exports.openPages = | ||
{ | ||
ENABLED: false, | ||
LOGIN_TEMPLATE_PATH: __dirname + '/templates/login-open-pages.jade', | ||
LOGIN_CSS_PATH: __dirname + '/templates/login.css', | ||
AUTH_FORM_ROUTE: '/api/v1.0/open-pages-auth', | ||
ROOT : __dirname + '/../open-pages', | ||
AUTH_FORM_SUBMIT_ROUTE: '/api/v1.0/open-pages-auth-submit', | ||
SQLLITE_FILE: __dirname + '/../open-pages/db.sql', | ||
OPEN_PAGES_WEB_ROUTE: '/og', // means that /og/{name}/ is serves the user's folder 'name' | ||
} | ||
/** | ||
* dropbox app config | ||
@@ -108,4 +123,19 @@ */ | ||
} | ||
}, | ||
'ftp/':{ | ||
'connect/':{}, | ||
'login/':{}, | ||
'logout/':{}, | ||
'account/':{}, | ||
'exec/':{ | ||
'ls/':{}, | ||
'rm/':{}, | ||
'mkdir/':{}, | ||
'cp/':{}, | ||
'mv/':{}, | ||
'get/':{}, | ||
'put/':{} | ||
} | ||
}, | ||
'ftp/':{ | ||
'open-pages/':{ | ||
'connect/':{}, | ||
@@ -112,0 +142,0 @@ 'login/':{}, |
@@ -75,2 +75,18 @@ /** | ||
} | ||
exports.getRootPath = function(request, path) { | ||
var resolvedPath = pathModule.resolve(exports.config.ROOT + '/' + path); | ||
return resolvedPath; | ||
} | ||
exports.getSessionObject = function(request) { | ||
return request.session.www_user; | ||
} | ||
exports.setSessionObject = function(request, value) { | ||
request.session.www_user = value; | ||
} | ||
/** | ||
@@ -80,5 +96,5 @@ * @return true if the user is logged in (and connected) | ||
exports.isLoggedIn = function (request) { | ||
if (request.session.www_user) | ||
return true; | ||
return false; | ||
if (exports.getSessionObject(request)) | ||
return true; | ||
return false; | ||
} | ||
@@ -89,5 +105,5 @@ /** | ||
exports.isConnected = function (request) { | ||
if (request.session.www_user) | ||
return true; | ||
return false; | ||
if (exports.getSessionObject(request)) | ||
return true; | ||
return false; | ||
} | ||
@@ -100,23 +116,23 @@ | ||
* Call the provided callback with these parameters | ||
* @return {"success": true, authorize_url: "https://www.dropbox.com/1/oauth/authorize?oauth_token=NMCS862sIG1m6P"} | ||
* @return {"success": false, message: Oups!"} | ||
* @return {'success': true, authorize_url: "https://www.dropbox.com/1/oauth/authorize?oauth_token=NMCS862sIG1m6P"} | ||
* @return {'success': false, message: Oups!"} | ||
*/ | ||
exports.connect = function (request, response, next, cbk) { | ||
if (exports.isConnected(request)){ | ||
cbk( | ||
{ | ||
success:true | ||
, message:'Was already connected. You might want to <a href="../logout/">logout</a> before connecting again.' | ||
} | ||
); | ||
} | ||
else{ | ||
cbk( | ||
{ | ||
success:true | ||
, message:'Now connected. You probably want to <a href="'+exports.config.AUTH_FORM_ROUTE+'">authenticate</a> now.' | ||
, authorize_url: exports.config.AUTH_FORM_ROUTE | ||
} | ||
); | ||
} | ||
if (exports.isConnected(request)){ | ||
cbk( | ||
{ | ||
success:true | ||
, message:'Was already connected. You might want to <a href="../logout/">logout</a> before connecting again.' | ||
} | ||
); | ||
} | ||
else{ | ||
cbk( | ||
{ | ||
success:true | ||
, message:'Now connected. You probably want to <a href="'+exports.config.AUTH_FORM_ROUTE+'">authenticate</a> now.' | ||
, authorize_url: exports.config.AUTH_FORM_ROUTE | ||
} | ||
); | ||
} | ||
} | ||
@@ -127,11 +143,11 @@ /** | ||
* Call the provided callback with this data | ||
* status : {"success": true}, | ||
* status : {'success': true}, | ||
*/ | ||
exports.login = function (request, response, next, cbk) { | ||
if (exports.isLoggedIn(request)){ | ||
cbk({success:true}); | ||
} | ||
else{ | ||
cbk({success:false, code: 401, message: 'User not authorized.'}); | ||
} | ||
if (exports.isLoggedIn(request)){ | ||
cbk({success:true}); | ||
} | ||
else{ | ||
cbk({success:false, code: 401, message: 'User not authorized.'}); | ||
} | ||
} | ||
@@ -141,19 +157,19 @@ /** | ||
* Call the provided callback with this data | ||
* status : {"success": true}, | ||
* status : {'success': true}, | ||
*/ | ||
exports.logout = function (request, response, next, cbk) { | ||
if (request.session.www_user){ | ||
request.session.www_user = undefined; | ||
cbk({success:true, message:"Now logged out."}); | ||
} | ||
else{ | ||
cbk({success:true, message:"Was not logged in."}); | ||
} | ||
if (exports.getSessionObject(request)){ | ||
exports.setSessionObject(request, undefined); | ||
cbk({success:true, message:"Now logged out."}); | ||
} | ||
else{ | ||
cbk({success:true, message:"Was not logged in."}); | ||
} | ||
} | ||
exports.errNotLoggedIn = function (cbk) { | ||
cbk({ | ||
success:false, | ||
message:"User not connected yet. You need to call the 'login' service first.", | ||
code: 401 | ||
}); | ||
cbk({ | ||
success:false, | ||
message:"User not connected yet. You need to call the 'login' service first.", | ||
code: 401 | ||
}); | ||
} | ||
@@ -163,18 +179,18 @@ /** | ||
* Call the provided callback with this data | ||
* status : {"success": true}, | ||
* data { | ||
* display_name: "Alexandre Hoyau", | ||
* quota_info: { | ||
* available: 5368709120, | ||
* used: 144201723 | ||
* } | ||
* status : {'success': true}, | ||
* data { | ||
* display_name: "Alexandre Hoyau", | ||
* quota_info: { | ||
* available: 5368709120, | ||
* used: 144201723 | ||
* } | ||
*/ | ||
exports.getAccountInfo = function (request, response, next, cbk) { | ||
if (!exports.isLoggedIn(request)){ | ||
exports.errNotLoggedIn(cbk); | ||
return; | ||
} | ||
cbk({"success": true}, | ||
{ | ||
display_name: request.session.www_user.name | ||
if (!exports.isLoggedIn(request)){ | ||
exports.errNotLoggedIn(cbk); | ||
return; | ||
} | ||
cbk({'success': true}, | ||
{ | ||
'display_name': exports.getSessionObject(request).name | ||
}); | ||
@@ -188,6 +204,6 @@ } | ||
* List the files of a given folder | ||
* @result an object like this one: | ||
* @result an object like this one: | ||
* { | ||
* "status": { | ||
* "success": true | ||
* 'success': true | ||
* }, | ||
@@ -208,3 +224,3 @@ * "data": [ | ||
exports.ls = function (path, request, response, next, cbk) { | ||
if (!exports.isLoggedIn(request)){ | ||
if (!exports.isLoggedIn(request)) { | ||
exports.errNotLoggedIn(cbk); | ||
@@ -214,15 +230,33 @@ return; | ||
var resolvedPath = pathModule.resolve(__dirname, exports.config.ROOT+path) + '/'; | ||
var resolvedPath = pathModule.resolve(__dirname, exports.config.ROOT + path) + '/'; | ||
try{ | ||
try { | ||
var now = Date.now(); | ||
response._headers['etag'] = now; | ||
response._headerNames['etag'] = 'ETag'; | ||
// implement weak ETag support based on directory modification times | ||
var etag = request.headers['if-none-match']; | ||
if (etag) { | ||
var dir_mtime = fs.statSync(resolvedPath).mtime.getTime(); | ||
var browser_mtime = Number(etag); | ||
if (browser_mtime > dir_mtime && browser_mtime < now) { // cache hit | ||
response._headers['etag'] = etag; | ||
response.statusCode = 304; | ||
response.end("", 'utf-8'); | ||
return; | ||
} | ||
} | ||
var filesArray = fs.readdirSync(resolvedPath); | ||
var filesData = []; | ||
for(var idx=0; idx<filesArray.length; idx++){ | ||
var file = fs.statSync(resolvedPath+filesArray[idx]); | ||
filesData.push({ | ||
bytes: file.size, | ||
modified: file.mtime, | ||
name: filesArray[idx].normalize(), | ||
is_dir: file.isDirectory(), | ||
}); | ||
for (var idx = 0; idx < filesArray.length; idx++) { | ||
try { | ||
var file = fs.statSync(resolvedPath + filesArray[idx]); | ||
file.name = filesArray[idx].normalize(); | ||
file.is_dir = file.isDirectory(); | ||
filesData.push(file); | ||
} catch (e) { | ||
var ignorableErrors = ["EPERM", "ENOENT", "EAGAIN", "EACCES"]; | ||
if (ignorableErrors.indexOf(e.code) < 0) throw e; | ||
} | ||
} | ||
@@ -237,69 +271,69 @@ cbk({success:true}, filesData); | ||
* delete a file or folder | ||
* @return an object with this attribute | ||
* @return an object with this attribute | ||
* { | ||
* "status": {"success": true} | ||
* "status": {'success': true} | ||
* } | ||
*/ | ||
exports.rm = function (path, request, response, next, cbk) { | ||
if (!exports.isLoggedIn(request)){ | ||
exports.errNotLoggedIn(cbk); | ||
return; | ||
} | ||
if (!exports.isLoggedIn(request)){ | ||
exports.errNotLoggedIn(cbk); | ||
return; | ||
} | ||
var resolvedPath = pathModule.resolve(__dirname, exports.config.ROOT+path); | ||
fs.unlink(resolvedPath, function (err) { | ||
if (err){ | ||
console.error(err); | ||
cbk({success:false, message: err}); | ||
} | ||
else | ||
cbk({success:true}); | ||
}); | ||
var resolvedPath = exports.getRootPath(request, path); | ||
fs.unlink(resolvedPath, function (err) { | ||
if (err){ | ||
console.error(err); | ||
cbk({success:false, message: err}); | ||
} | ||
else | ||
cbk({success:true}); | ||
}); | ||
} | ||
/** | ||
* create a folder | ||
* @return an object with this attribute | ||
* @return an object with this attribute | ||
* { | ||
* "status": {"success": true} | ||
* "status": {'success': true} | ||
* } | ||
*/ | ||
exports.mkdir = function (path, request, response, next, cbk) { | ||
if (!exports.isLoggedIn(request)){ | ||
exports.errNotLoggedIn(cbk); | ||
return; | ||
} | ||
if (!exports.isLoggedIn(request)){ | ||
exports.errNotLoggedIn(cbk); | ||
return; | ||
} | ||
var resolvedPath = pathModule.resolve(__dirname, exports.config.ROOT+path); | ||
fs.exists(resolvedPath, function (exists) { | ||
if (!exists){ | ||
fs.mkdir(resolvedPath, null, function (error) { | ||
if (error){ | ||
cbk({success:false, message: error.code}); | ||
} | ||
else{ | ||
cbk({success:true}); | ||
} | ||
}); | ||
} | ||
else{ | ||
console.error('mkdir error: folder already exists', resolvedPath); | ||
cbk({success:false, message: 'folder already exists'}); | ||
} | ||
}); | ||
var resolvedPath = exports.getRootPath(request, path); | ||
fs.exists(resolvedPath, function (exists) { | ||
if (!exists){ | ||
fs.mkdir(resolvedPath, null, function (error) { | ||
if (error){ | ||
cbk({success:false, message: error.code}); | ||
} | ||
else{ | ||
cbk({success:true}); | ||
} | ||
}); | ||
} | ||
else{ | ||
console.error('mkdir error: folder already exists', resolvedPath); | ||
cbk({success:false, message: 'folder already exists'}); | ||
} | ||
}); | ||
} | ||
/** | ||
* Create the give file | ||
* @return an object with this attribute | ||
* @return an object with this attribute | ||
* { | ||
* "status": {"success": true} | ||
* "status": {'success': true} | ||
* } | ||
*/ | ||
exports.cp = function (src, dst, request, response, next, cbk) { | ||
if (!exports.isLoggedIn(request)){ | ||
exports.errNotLoggedIn(cbk); | ||
return; | ||
} | ||
if (!exports.isLoggedIn(request)){ | ||
exports.errNotLoggedIn(cbk); | ||
return; | ||
} | ||
var resolvedSrc = pathModule.resolve(__dirname, exports.config.ROOT + src); | ||
var resolvedDst = pathModule.resolve(__dirname, exports.config.ROOT + dst); | ||
var resolvedSrc = exports.getRootPath(request, src); | ||
var resolvedDst = exports.getRootPath(request, dst); | ||
// Check that the file exists | ||
@@ -332,12 +366,12 @@ fs.exists(resolvedSrc, function (exists) { | ||
* Move or rename a file or folder | ||
* @return an object with this attribute | ||
* @return an object with this attribute | ||
* { | ||
* "status": {"success": true} | ||
* "status": {'success': true} | ||
* } | ||
*/ | ||
exports.mv = function (src, dst, request, response, next, cbk) { | ||
if (!exports.isLoggedIn(request)){ | ||
exports.errNotLoggedIn(cbk); | ||
return; | ||
} | ||
if (!exports.isLoggedIn(request)){ | ||
exports.errNotLoggedIn(cbk); | ||
return; | ||
} | ||
exports.cp(src, dst, request, response, next, function(res){ | ||
@@ -355,36 +389,36 @@ if (res.success === false){ | ||
* Create the give file | ||
* @return an object with this attribute | ||
* @return an object with this attribute | ||
* { | ||
* "status": {"success": true} | ||
* "status": {'success': true} | ||
* } | ||
*/ | ||
exports.put = function (path, data, request, response, next, cbk) { | ||
if (!exports.isLoggedIn(request)){ | ||
exports.errNotLoggedIn(cbk); | ||
return; | ||
} | ||
if (!exports.isLoggedIn(request)){ | ||
exports.errNotLoggedIn(cbk); | ||
return; | ||
} | ||
var resolvedPath = pathModule.resolve(__dirname, exports.config.ROOT+path); | ||
var resolvedPath = exports.getRootPath(request, path); | ||
var file = fs.createWriteStream(resolvedPath); | ||
file.write(data); | ||
var file = fs.createWriteStream(resolvedPath); | ||
file.write(data); | ||
cbk({success:true}); | ||
cbk({success:true}); | ||
} | ||
/** | ||
* Get the give file, output its content | ||
* @return the content of the file if there is no error | ||
* @return an object with this attribute | ||
* @return the content of the file if there is no error | ||
* @return an object with this attribute | ||
* { | ||
* "status": {"success": false} | ||
* "status": {'success': false} | ||
* } | ||
*/ | ||
exports.get = function (path, request, response, next, cbk) { | ||
if (!exports.isLoggedIn(request)){ | ||
exports.errNotLoggedIn(cbk); | ||
return; | ||
} | ||
if (!exports.isLoggedIn(request)){ | ||
exports.errNotLoggedIn(cbk); | ||
return; | ||
} | ||
var resolvedPath = pathModule.resolve(__dirname, exports.config.ROOT+path); | ||
cbk(undefined, undefined, undefined, resolvedPath); | ||
var resolvedPath = exports.getRootPath(request, path); | ||
cbk(undefined, undefined, undefined, resolvedPath); | ||
} |
{ | ||
"name": "unifile", | ||
"description": "Express middleware to provide a common API for cloud storage services. ", | ||
"version": "0.0.52", | ||
"version": "0.0.53", | ||
"author": { | ||
@@ -14,2 +14,3 @@ "name": "Alex Hoyau aka lexoyo" | ||
"dependencies": { | ||
"crypto": "0.0.3", | ||
"dbox": "~0.6.3", | ||
@@ -21,2 +22,4 @@ "express": "~4.8.5", | ||
"path": "~0.4.9", | ||
"request": "^2.53.0", | ||
"sqlite3": "^3.1.0", | ||
"unorm": "~1.3.3" | ||
@@ -23,0 +26,0 @@ }, |
@@ -13,4 +13,5 @@ #Unifile, unified access to cloud storage services. | ||
* Dropbox | ||
* local web server | ||
* see instructions bellow to add a service | ||
* local web server: auth and browse a given folder on the server where unifile is running | ||
* self hosting mode: auth with [Mozilla persona](https://www.mozilla.org/en-US/persona/), choose a name and brose a folder on the server where unifile is installed and which is served as `http(s)://the-unifile-server.com/chosen-name/` - this is an experimental feature which still has to be fine tuned | ||
* extend unifile: see instructions bellow to add a service | ||
@@ -190,2 +191,3 @@ Example | ||
* app keys and sensitive info in env vars | ||
* unit tests for get/put/cat | ||
@@ -192,0 +194,0 @@ * pagination for ls commands? |
@@ -23,2 +23,9 @@ /** | ||
// enable open pages | ||
// this is the ""self hosting mode" | ||
// auth with Mozilla persona, choose a name and brose a folder on the server where unifile is installed and which is served as http(s)://the-unifile-server.com/chosen-name/ - this is an experimental feature which still has to be fine tuned | ||
// here you can set all open pages config, see default-config.js | ||
options.openPages.ENABLED = true; | ||
// parse data for file upload | ||
@@ -25,0 +32,0 @@ app.use(options.apiRoot, multipart()); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
139999
37
2983
200
10
10
1
+ Addedcrypto@0.0.3
+ Addedrequest@^2.53.0
+ Addedsqlite3@^3.1.0
+ Addedajv@6.12.6(transitive)
+ Addedasn1@0.2.6(transitive)
+ Addedassert-plus@1.0.0(transitive)
+ Addedasynckit@0.4.0(transitive)
+ Addedaws-sign2@0.7.0(transitive)
+ Addedaws4@1.13.2(transitive)
+ Addedbcrypt-pbkdf@1.0.2(transitive)
+ Addedcaseless@0.12.0(transitive)
+ Addedcombined-stream@1.0.8(transitive)
+ Addedcore-util-is@1.0.2(transitive)
+ Addedcrypto@0.0.3(transitive)
+ Addeddashdash@1.14.1(transitive)
+ Addeddelayed-stream@1.0.0(transitive)
+ Addedecc-jsbn@0.1.2(transitive)
+ Addedextend@3.0.2(transitive)
+ Addedextsprintf@1.3.0(transitive)
+ Addedfast-deep-equal@3.1.3(transitive)
+ Addedfast-json-stable-stringify@2.1.0(transitive)
+ Addedforever-agent@0.6.1(transitive)
+ Addedform-data@2.3.3(transitive)
+ Addedgetpass@0.1.7(transitive)
+ Addedhar-schema@2.0.0(transitive)
+ Addedhar-validator@5.1.5(transitive)
+ Addedhttp-signature@1.2.0(transitive)
+ Addedis-typedarray@1.0.0(transitive)
+ Addedisstream@0.1.2(transitive)
+ Addedjsbn@0.1.1(transitive)
+ Addedjson-schema@0.4.0(transitive)
+ Addedjson-schema-traverse@0.4.1(transitive)
+ Addedjson-stringify-safe@5.0.1(transitive)
+ Addedjsprim@1.4.2(transitive)
+ Addedmime-db@1.52.0(transitive)
+ Addedmime-types@2.1.35(transitive)
+ Addednan@2.7.0(transitive)
+ Addedoauth-sign@0.9.0(transitive)
+ Addedperformance-now@2.1.0(transitive)
+ Addedpsl@1.15.0(transitive)
+ Addedpunycode@2.3.1(transitive)
+ Addedqs@6.5.3(transitive)
+ Addedrequest@2.88.2(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsqlite3@3.1.13(transitive)
+ Addedsshpk@1.18.0(transitive)
+ Addedtough-cookie@2.5.0(transitive)
+ Addedtunnel-agent@0.6.0(transitive)
+ Addedtweetnacl@0.14.5(transitive)
+ Addeduri-js@4.4.1(transitive)
+ Addeduuid@3.4.0(transitive)
+ Addedverror@1.10.0(transitive)