· 8 years ago · Aug 01, 2018, 03:42 PM
1var fs = require("fs");
2var pg = require('pg').native;
3var program = require('commander');
4var client;
5var util = require('util');
6var exec = require('child_process').exec;
7var child;
8var rails_env; // Will be set to "development" or "production" on start
9var shell = require('shelljs');
10
11// Dictionary mapping usernames to account information
12var users = {};
13var dbFile = 'userdb.json';
14var uid = '';
15
16
17
18function addUser(name, password) {
19 var validate = validateNewUser(name, password);
20
21 if(!validate.valid) {
22 return validate.message;
23 }
24
25 fs.mkdir("users", 0777);
26 fs.mkdir("users/" + name, 0777);
27
28 users[name] = { password : password };
29
30 if (rails_env == "development") {
31 storeUserData_JSON();
32 }
33 else {
34 storeUserData_postgres();
35 }
36 return "Created user " + name + ".";
37};
38
39
40exports.authenticate = function(req, res) {
41 var result;
42
43 if(!users[req.body.username]) {
44 result = 'User ' + req.body.username + ' not found.';
45 }
46 else if(users[req.body.username].password === req.body.password) {
47 req.session.username = req.body.username;
48 uid = req.body.username;
49 res.redirect('/index');
50 return;
51 }
52 else {
53 result = 'Incorrect password.';
54 }
55
56 res.redirect('home');
57};
58
59
60// Configures the postgres DB
61// This method is not destructive and can be run without issue
62function bootstrapDB() {
63 // Create the sequence number for the uid field of users
64 client.query("CREATE SEQUENCE users_uid_seq", function(err, result) {
65 if (err == "Error: relation \"users_uid_seq\" already exists") {
66 console.log("This db is already bootstrapped 1/2");
67 }
68 else if (err) {
69 console.error("Recieved error in bootstrap: " + err);
70 }
71 });
72
73 // Create the 'users' database
74 client.query("CREATE TABLE users (uid int not null default nextval('users_uid_seq'), name varchar(20), password varchar(50), primary key (uid))", function(err, result) {
75 if (err == "Error: relation \"users\" already exists") {
76 console.log("This db is already bootstrapped 2/2");
77 }
78 else if (err) {
79 console.error("Recieved error in bootstrap: " + err);
80 }
81 });
82};
83
84
85// Decides what action to take when a user clicks a file/folder
86exports.click = loginRequired(function(req, res) {
87 // if (file is a folder)
88 var filesAsHTML = ls(req.session.currentdir + req.body.path)
89 res.send({ files: filesAsHTML });
90 // else
91 // var file = downloadFile(req.session.currentdir + req.body.path);
92 // res.sent({ files: file });
93});
94
95
96// Streams a file to the user
97function downloadFile(req, res, filepath) {
98
99};
100
101
102// Returns the classes of a file, such as clickable
103function getClasses(filepath) {
104 return 'class="clickable" ';
105};
106
107
108// Returns the image used to represent the given file
109function getImage(filepath) {
110 var mime = getMimeType(filepath);
111 //console.log(mime);
112 var imgpath = "";
113
114 //audio
115 if (mime === 'audio'){
116 imgpath = "images/audio_basic.png";
117 }
118 //image
119 else if (mime === 'image'){
120 imgpath = "images/image.png";
121 }
122 //text
123 else if (mime === 'text'){
124 imgpath = "images/text_plain.png";
125 }
126 //video
127 else if (mime === 'video'){
128 imgpath = "images/video_x_generic.png";
129 }
130 //application
131 else if (mime === 'application'){
132 imgpath = "images/application_octet_stream.png";
133 }
134 //other
135 else imgpath = "images/folder.png";
136 return '<img src=' + imgpath + '>';
137};
138
139// Returns a file's mime type
140function getMimeType(filepath) {
141 var mimetype;
142 mimetype = (shell.exec("file --mime-type '" + filepath + "'", {silent:true}).output);
143 mimetype = mimetype.substring(mimetype.indexOf(": "), mimetype.length);
144 mimetype = mimetype.substring(2, mimetype.indexOf("/"));
145 return mimetype;
146
147
148}
149
150/* Returns a file's mime type
151function getMimeType(filepath) {
152 asyncblock(function(flow) {
153 var mimetype;
154 child = exec("file --mime-type '" + filepath + "'",
155 function (error, stdout, stderr) {
156 mimetype = stdout.substring(stdout.indexOf(": "), stdout.length);
157 mimetype = mimetype.substring(2, mimetype.indexOf("/"));
158
159 if (error !== null) {
160 console.log('exec error: ' + error);
161 }
162
163 }), flow.set('contents1');
164 console.log('this is: ' + flow.get('contents1'));
165 });
166}
167*/
168
169// Renders the homepage. If a user is logged in, redirects them to /index
170exports.homepage = function(req, res) {
171 if(req.session && req.session.username) {
172 res.redirect('/index');
173 }
174 else {
175 res.render('home', { title: 'Homepage' });
176 }
177};
178
179
180exports.index = loginRequired(function(req, res) {
181 req.session.currentdir = "users/" + req.session.username + "/";
182
183 res.render('index', { title: 'Bag of Holding',
184 username: req.session.username });
185});
186
187
188// This is the JSON version of the DB, used for development
189exports.loadDB_JSON = function() {
190 fs.readFile(dbFile, function(err, data) {
191 if (err) {
192 console.error("Unable to load file: " + dbFile);
193 }
194 else {
195 try {
196 users = JSON.parse(data);
197 }
198 catch(e) {
199 console.error('Unable to parse JSON from file:\n' + dbFile + '\nDue to error:\n' + e);
200 }
201 }
202 if(!users) {
203 console.error("Data in " + dbFile + " is invalid. Reinitializing user records.");
204 users = {};
205 }
206 });
207};
208
209
210// This is the postgres version of the DB, used for production
211exports.loadDB_postgres = function() {
212 program.prompt('User: ', function (user) {
213 program.password('Password: ', '*', function (pass) {
214 var db = user;
215 if (pass) {
216 user = user + ":" + pass;
217 }
218
219 var conString = "tcp://" + user + "@db-edlab.cs.umass.edu:7391/" + db;
220 client = new pg.Client(conString);
221 client.connect();
222
223 bootstrapDB();
224
225 var query = client.query("SELECT name, password FROM users");
226 query.on('row', function(row) {
227 users[row.name] = { password : row.password}
228 });
229 });
230 });
231}
232
233
234function loginRequired(routeFunction) {
235 return function(req, res){
236 if(!req.session || !req.session.username) {
237 res.redirect('/');
238 return;
239 }
240 else {
241 routeFunction(req, res);
242 }
243 };
244};
245
246
247exports.logout = loginRequired(function(req, res) {
248 if(req.session.username){
249 req.session.destroy();
250 }
251 res.redirect('home');
252});
253
254
255function ls(path) {
256 var myfiles = '', filenames = fs.readdirSync(path);
257 console.log("filenameslength: " + filenames.length);
258
259 for (i = 0; i < filenames.length; i++) {
260 myfiles += '<a id="' + filenames[i] + '" ' +
261 getClasses(path + filenames[i]) + 'href="#">' +
262 getImage(path + filenames[i]) + '<br />' + filenames[i] + '</a>';
263 }
264
265 return myfiles;
266};
267
268
269exports.newUser = function(req, res) {
270 var result = addUser(req.body.username, req.body.password);
271
272 res.redirect('home');
273};
274
275
276exports.setEnv = function(env) {
277 rails_env = env;
278};
279
280
281function storeUserData_JSON(cb) {
282 fs.writeFile(dbFile, JSON.stringify(users), function(err) {
283 if(err) {
284 console.error("Unable to write file: " + dbFile);
285 }
286 if(cb) {
287 cb();
288 }
289 });
290};
291
292
293function storeUserData_postgres(cb) {
294 for(x in users) {
295 client.query("INSERT INTO users VALUES (default, $1, $2)", [x, users[x].password]);
296 }
297};
298
299
300// Uploads a file
301exports.upload = loginRequired(function(req, res) {
302 var file = req.files.file;
303 console.log("Got file " + file.name);
304
305 var movePath = "users/" + req.session.username + "/" + file.name;
306
307 fs.rename(file.path, movePath, function(err) {
308 if(err) {
309 console.error("Unable to write file: " + file.name);
310 }
311 else {
312 console.log("Moved file, " + file.name + ", to " + movePath);
313 }
314 });
315
316 res.send({}); // Send an empty response so the connection can be closed
317});
318
319
320function validateNewUser(name, password) {
321 var result = { valid : true,
322 message : '' };
323
324 if(!name || !password){
325 result.message = 'Must specify both name and password.\n';
326 return result;
327 }
328
329 if(name.length === 0){
330 result.valid = false;
331 result.message += 'Name can not have zero-length.\n';
332 }
333
334 if(password.length === 0){
335 result.valid = false;
336 result.message += 'Password cannot have zero-length.\n';
337 }
338
339 if(users.name){
340 result.valid = false;
341 result.message += "User " + name + " already exists.\n" +
342 "You must specify a different user name.\n";
343 }
344
345 return result;
346};