'How to restrict users to only be able to view a specific folder in a statically served filesystem? Express.js
I have an express application set up to use a filesystem which contains a folder for each user.
app.use(express.static(mainFolder));
The problem is that I can't seem to restrict users from viewing each others files.
In account A, I have a folder for photos
mainFolder > AccountA > Photos > thePhoto.png
However, After I log into account B I can access this photo by typing in
localhost:8080/AccountA/Photos/thePhoto.png
I have already created a middleware to check that the user is logged in and this stops anyone not logged in from viewing the photo. Now I need a to restrict each user from viewing other accounts files/photos etc.
I am aware that I could do
app.use(express.static(mainFolder/accountA));
However I would have to this for each user. Could I put this in the authentication route so that after a user has authenticated the app uses this file?
I have also looked at How to serve user specific static content in Express.js and this does not help.
Here is the code for my middleware:
function checkAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next()
} else if(req.url != "/login" && req.url != "/register" && req.url != "/register?" && req.originalUrl != "/register?" ){
res.redirect('/login');
} else if(req.url === "/login" || req.url === "/register" || req.url === "/register?" || req.originalUrl === "register"){
return next()
}
}
Here is my app.js
//------------------------------------------------------
// STORAGE SITE SERVER SIDE
//------------------------------------------------------
// Matthew Haywood
var path = require("path")
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var fs = require("fs-extra");
var methodOverride = require("method-override");
var passport = require("passport");
var session = require('express-session')
var flash = require('express-flash');
var bcrypt = require('bcryptjs');
var csv = require('csv-parser');
var schedule = require('node-schedule');
const { exec } = require('child_process');
var sanitizer = require('sanitize')();
var os = require('os-utils');
var addScheduledWorkflowFromFile = require('./routes/workflow/workflowRoutes').addScheduledWorkflowFromFile;
var middleware = require("./middleware/index");
var workflowRoutes = require('./routes/workflow/workflowRoutes').router;
var storageRoutes = require('./routes/storage/storageRoutes').router;
var codeRoutes = require('./routes/code/codeRoutes').router;
global.testFolder;
//Configure the app based on whether its development or production
if (process.env.NODE_ENV === 'production') {
testFolder = '/media/pi/ELEMENTS\ B/';
string_len = 22;
production_flag = true
}
if (process.env.NODE_ENV === 'development') {
testFolder = '/Users/matthaywood/Desktop/StorageSite/StorageSite/public/'
string_len = 59;
}
//PASSPORT SETUP
const initializePassport = require('./passport-config');
const { stdout, allowedNodeEnvironmentFlags } = require("process");
const { timeStamp } = require("console");
const { ResultWithContext } = require("express-validator/src/chain");
initializePassport(
passport,
email => users.find(user => user.email === email),
id => users.find(user => user.id === id)
)
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
app.use(flash())
app.use(session({
secret: "Once again rusty is the cutest dog",
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize());
app.use(passport.session());
app.use(methodOverride("_method"));
app.use(function (req, res, next) {
res.locals.currentUser = req.user;
next();
});
function checkAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next()
} else if(req.url != "/login" && req.url != "/register" && req.url != "/register?" && req.originalUrl != "/register?" ){
res.redirect('/login');
} else if(req.url === "/login" || req.url === "/register" || req.url === "/register?" || req.originalUrl === "register"){
return next()
}
}
function checkUser(req,res,next){
if(req.body.currentPath != undefined){
console.log('CheckUser function ' + req.body.currentPath)
var endDir = req.body.currentPath.replace(testFolder, '');
var user = endDir.split('/')[1]
if(user == req.user.name){
console.log("USER " + user + " AUTHORISED FOR " + req.body.currentPath + " DIRECTORY")
return next()
} else {
res.redirect("/Unauthorised");
return "Failed";
}
} else {
next();
}
}
app.use(checkAuthenticated);
app.use(checkUser);
global.users = [];
global.scheduledWorkflows = []
//LOAD USERS IN FROM JSON FILE
var loadedData = JSON.parse(fs.readFileSync("users.json"))
console.log(loadedData.Users)
users = loadedData.Users
addScheduledWorkflowFromFile()
app.use(express.static(__dirname + "/public"));
app.use('/modules', express.static("modules"));
app.use("/", workflowRoutes);
app.use("/", storageRoutes);
app.use("/", codeRoutes);
//----------------------------------------------------------
// ROUTES
//----------------------------------------------------------
app.get("/", function (req, res) {
res.render("clusterHome.ejs");
})
//Settings Route for displaying current connected HDD
app.get("/settings", function (req, res) {
res.render("settings.ejs");
})
//--------------------------------------------------------------------
// ROUTES FOR USERS AND LOGIN
//--------------------------------------------------------------------
//Register
app.get("/register", function (req, res) {
res.render("register.ejs");
})
app.post("/register", function (req, res) {
var password = req.body.password;
// var name = sanitizer.value(req.body.name,String);
var name = req.body.name;
// var email = sanitizer.value(req.body.email,String);
var email = req.body.email;
var the_hash;
console.log('CREATING NEW ACCOUNT')
bcrypt.hash(password, 10, function (err, hash) {
console.log(err)
the_hash = hash;
the_id = Date.now().toString();
users.push({
id: the_id,
name: name,
email: email,
password: hash
})
fs.mkdirSync(testFolder + name);
fs.mkdirSync(testFolder + name + "/" + "Workflows");
fs.mkdirSync(testFolder + name + "/Workflows/Logs" );
fs.mkdirSync(testFolder + name + "/" + "Code");
var data = JSON.parse(fs.readFileSync("users.json"))
data.Users.push({
id: the_id,
name: name,
email: email,
password: hash
})
data = JSON.stringify(data, null, 2)
fs.writeFileSync("users.json", data)
passport.authenticate('local')(req, res, function () {
res.redirect("/");
})
if (err) {
console.log(err)
res.redirect('/register');
}
})
})
//----------------------------------------------------------
// LOGIN/LOGOUT ROUTES
//----------------------------------------------------------
app.get("/login", function (req, res) {
res.render("login.ejs");
})
app.post("/login", passport.authenticate('local'), function (req, res) {
app.use(express.static(testFolder+"/"+req.user.name));
res.redirect("/");
})
//Logout
app.delete("/logout", function (req, res) {
req.logOut();
res.redirect('/login')
})
//Unauthorised Route
app.get("/unauthorized", function(req, res){
res.render("unauthorised.ejs");
})
//----------------------------------------------------------
// LOG ROUTES
//----------------------------------------------------------
app.get("/logs", function (req, res) {
res.render("logs.ejs")
})
app.get("/logs/get-data", function (req, res) {
os.cpuUsage(function (v) {
res.status(200).send({ cpuUsage: v })
});
})
//----------------------------------------------------------
// AUTO GIT PULL SCHEDULE
//----------------------------------------------------------
//Only run this job if in production to pull from github
if (process.env.NODE_ENV === 'production') {
const job = schedule.scheduleJob('*/5 * * * *', function () {
exec('git pull', (err, stdout, stderr) => {
if (err) {
console.log(err);
} else {
console.log("Pulling from git repository")
console.log(stdout)
//Restart server if git has pulled changes
if(!stdout.includes("Already up to date.")){
process.exit(1)
}
}
})
})
}
function serverLog(string){
//function used to log to a file
}
app.listen("8080");
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
