Commit e628921a by Johannes Zellner

Add rename functionality

This also break backwardscompat since PUT is now POST
and PUT is used for renaming
1 parent 4b6cf0ad
...@@ -118,7 +118,7 @@ function put(filePath, otherFilePaths, options) { ...@@ -118,7 +118,7 @@ function put(filePath, otherFilePaths, options) {
var destinationPath = (destination ? '/' + destination : '') + '/' + relativeFilePath; var destinationPath = (destination ? '/' + destination : '') + '/' + relativeFilePath;
console.log('Uploading file %s -> %s', relativeFilePath.cyan, destinationPath.cyan); console.log('Uploading file %s -> %s', relativeFilePath.cyan, destinationPath.cyan);
superagent.put(config.server() + API + destinationPath).query(gQuery).attach('file', file).end(function (error, result) { superagent.post(config.server() + API + destinationPath).query(gQuery).attach('file', file).end(function (error, result) {
if (result && result.statusCode === 403) return callback(new Error('Upload destination ' + destinationPath + ' not allowed')); if (result && result.statusCode === 403) return callback(new Error('Upload destination ' + destinationPath + ' not allowed'));
if (result && result.statusCode !== 201) return callback(new Error('Error uploading file: ' + result.statusCode)); if (result && result.statusCode !== 201) return callback(new Error('Error uploading file: ' + result.statusCode));
if (error) return callback(error); if (error) return callback(error);
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<h5 v-show="deleteData.isFile">Really delete <span style="font-weight: bold;">{{ deleteData.filePath }}</span>?</h5> <h5 v-show="deleteData.isFile">Really delete <span style="font-weight: bold;">{{ deleteData.filePath }}</span>?</h5>
<h5 v-show="deleteData.isDirectory">Really delete directory <span style="font-weight: bold;">{{ deleteData.filePath }}</span> and all its content?</h5> <h5 v-show="deleteData.isDirectory">Really delete folder <span style="font-weight: bold;">{{ deleteData.filePath }}</span> and all its content?</h5>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">No</button> <button type="button" class="btn btn-default" data-dismiss="modal">No</button>
...@@ -51,12 +51,36 @@ ...@@ -51,12 +51,36 @@
</div> </div>
</div> </div>
<div class="modal fade" tabindex="-1" role="dialog" id="modalRename" v-cloak>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Rename {{ renameData.entry.filePath }}</h4>
</div>
<div class="modal-body">
<form v-on:submit.prevent="rename(renameData)">
<div class="form-group" v-bind:class="{ 'has-error': renameData.error }">
<input type="text" class="form-control" v-model="renameData.newFilePath" placeholder="Name" autofocus="true">
<label class="control-label">{{ renameData.error }}</label>
</div>
<button type="submit" style="display: none;"></button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">No</button>
<button type="button" class="btn btn-success" v-on:click="rename(renameData)">Yes</button>
</div>
</div>
</div>
</div>
<div class="modal fade" tabindex="-1" role="dialog" id="modalcreateDirectory" v-cloak> <div class="modal fade" tabindex="-1" role="dialog" id="modalcreateDirectory" v-cloak>
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">New Directory Name</h4> <h4 class="modal-title">New directory name</h4>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form v-on:submit.prevent="createDirectory(createDirectoryData)"> <form v-on:submit.prevent="createDirectory(createDirectoryData)">
...@@ -135,7 +159,7 @@ ...@@ -135,7 +159,7 @@
<a href="{{ part.link }}">{{ part.name }}</a> <a href="{{ part.link }}">{{ part.name }}</a>
</li> </li>
<li>{{ pathParts.slice(-1)[0].name }}</li> <li>{{ pathParts.slice(-1)[0].name }}</li>
<button class="btn btn-default btn-sm pull-right" v-on:click="createDirectoryAsk()">Create Directory</button> <button class="btn btn-default btn-sm pull-right" v-on:click="createDirectoryAsk()">Create Folder</button>
</ol> </ol>
</div> </div>
<div class="col-lg-12"> <div class="col-lg-12">
...@@ -150,6 +174,9 @@ ...@@ -150,6 +174,9 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-show="entries.length === 0">
<th><i>Empty folder</i></th>
</tr>
<tr v-for="entry in entries" v-on:click="open(entry)" class="hand"> <tr v-for="entry in entries" v-on:click="open(entry)" class="hand">
<th> <th>
<img v-bind:src="entry.previewUrl" height="48px" width="48px"/> <img v-bind:src="entry.previewUrl" height="48px" width="48px"/>
...@@ -159,7 +186,7 @@ ...@@ -159,7 +186,7 @@
<th><span v-my-tooltip="foobar" data-toggle="tooltip" title="{{ entry.mtime }}">{{ entry.mtime | prettyDate }}</span></th> <th><span v-my-tooltip="foobar" data-toggle="tooltip" title="{{ entry.mtime }}">{{ entry.mtime | prettyDate }}</span></th>
<th style="text-align: right;"> <th style="text-align: right;">
<span class="entry-toolbar"> <span class="entry-toolbar">
<!-- <button class="btn btn-sm btn-default" v-on:click.stop="renameAsk(entry)" title="Rename"><i class="fa fa-pencil"></i></button> --> <button class="btn btn-sm btn-default" v-on:click.stop="renameAsk(entry)" title="Rename"><i class="fa fa-pencil"></i></button>
<button class="btn btn-sm btn-danger" v-on:click.stop="delAsk(entry)" title="Delete"><i class="fa fa-trash"></i></button> <button class="btn btn-sm btn-danger" v-on:click.stop="delAsk(entry)" title="Delete"><i class="fa fa-trash"></i></button>
</span> </span>
</th> </th>
......
...@@ -141,7 +141,7 @@ function upload() { ...@@ -141,7 +141,7 @@ function upload() {
var formData = new FormData(); var formData = new FormData();
formData.append('file', file); formData.append('file', file);
superagent.put('/api/files' + path).query({ username: app.session.username, password: app.session.password }).send(formData).end(function (error, result) { superagent.post('/api/files' + path).query({ username: app.session.username, password: app.session.password }).send(formData).end(function (error, result) {
if (result && result.statusCode === 401) return logout(); if (result && result.statusCode === 401) return logout();
if (result && result.statusCode !== 201) console.error('Error uploading file: ', result.statusCode); if (result && result.statusCode !== 201) console.error('Error uploading file: ', result.statusCode);
if (error) console.error(error); if (error) console.error(error);
...@@ -149,8 +149,6 @@ function upload() { ...@@ -149,8 +149,6 @@ function upload() {
app.uploadStatus.done += 1; app.uploadStatus.done += 1;
app.uploadStatus.percentDone = Math.round(app.uploadStatus.done / app.uploadStatus.count * 100); app.uploadStatus.percentDone = Math.round(app.uploadStatus.done / app.uploadStatus.count * 100);
console.log(Math.round(app.uploadStatus.done / app.uploadStatus.count * 100))
if (app.uploadStatus.done >= app.uploadStatus.count) { if (app.uploadStatus.done >= app.uploadStatus.count) {
app.uploadStatus = { app.uploadStatus = {
busy: false, busy: false,
...@@ -198,6 +196,33 @@ function del(entry) { ...@@ -198,6 +196,33 @@ function del(entry) {
}); });
} }
function renameAsk(entry) {
app.renameData.entry = entry;
app.renameData.error = null;
app.renameData.newFilePath = entry.filePath;
$('#modalRename').modal('show');
}
function rename(data) {
app.busy = true;
var path = encode(sanitize(app.path + '/' + data.entry.filePath));
var newFilePath = sanitize(app.path + '/' + data.newFilePath);
superagent.put('/api/files' + path).query({ username: app.session.username, password: app.session.password }).send({ newFilePath: newFilePath }).end(function (error, result) {
app.busy = false;
if (result && result.statusCode === 401) return logout();
if (result && result.statusCode !== 200) return console.error('Error renaming file: ', result.statusCode);
if (error) return console.error(error);
refresh();
$('#modalRename').modal('hide');
});
}
function createDirectoryAsk() { function createDirectoryAsk() {
$('#modalcreateDirectory').modal('show'); $('#modalcreateDirectory').modal('show');
app.createDirectoryData = ''; app.createDirectoryData = '';
...@@ -210,7 +235,7 @@ function createDirectory(name) { ...@@ -210,7 +235,7 @@ function createDirectory(name) {
var path = encode(sanitize(app.path + '/' + name)); var path = encode(sanitize(app.path + '/' + name));
superagent.put('/api/files' + path).query({ username: app.session.username, password: app.session.password, directory: true }).end(function (error, result) { superagent.post('/api/files' + path).query({ username: app.session.username, password: app.session.password, directory: true }).end(function (error, result) {
app.busy = false; app.busy = false;
if (result && result.statusCode === 401) return logout(); if (result && result.statusCode === 401) return logout();
...@@ -258,6 +283,11 @@ var app = new Vue({ ...@@ -258,6 +283,11 @@ var app = new Vue({
}, },
loginData: {}, loginData: {},
deleteData: {}, deleteData: {},
renameData: {
entry: {},
error: null,
newFilePath: ''
},
createDirectoryData: '', createDirectoryData: '',
createDirectoryError: null, createDirectoryError: null,
entries: [] entries: []
...@@ -271,6 +301,8 @@ var app = new Vue({ ...@@ -271,6 +301,8 @@ var app = new Vue({
upload: upload, upload: upload,
delAsk: delAsk, delAsk: delAsk,
del: del, del: del,
renameAsk: renameAsk,
rename: rename,
createDirectoryAsk: createDirectoryAsk, createDirectoryAsk: createDirectoryAsk,
createDirectory: createDirectory createDirectory: createDirectory
} }
......
...@@ -24,7 +24,8 @@ var router = new express.Router(); ...@@ -24,7 +24,8 @@ var router = new express.Router();
var multipart = multipart({ maxFieldsSize: 2 * 1024, limit: '512mb', timeout: 3 * 60 * 1000 }); var multipart = multipart({ maxFieldsSize: 2 * 1024, limit: '512mb', timeout: 3 * 60 * 1000 });
router.get ('/api/files/*', auth.verify, files.get); router.get ('/api/files/*', auth.verify, files.get);
router.put ('/api/files/*', auth.verify, multipart, files.put); router.post ('/api/files/*', auth.verify, multipart, files.post);
router.put ('/api/files/*', auth.verify, files.put);
router.delete('/api/files/*', auth.verify, files.del); router.delete('/api/files/*', auth.verify, files.del);
router.get ('/api/healthcheck', function (req, res) { res.status(200).send(); }); router.get ('/api/healthcheck', function (req, res) { res.status(200).send(); });
......
...@@ -17,6 +17,7 @@ exports = module.exports = function (basePath) { ...@@ -17,6 +17,7 @@ exports = module.exports = function (basePath) {
return { return {
get: get, get: get,
put: put, put: put,
post: post,
del: del del: del
}; };
}; };
...@@ -111,22 +112,22 @@ function get(req, res, next) { ...@@ -111,22 +112,22 @@ function get(req, res, next) {
}); });
} }
function put(req, res, next) { function post(req, res, next) {
var filePath = decodeURIComponent(req.params[0]); var filePath = decodeURIComponent(req.params[0]);
if (!(req.files && req.files.file) && !req.query.directory) return next(new HttpError(400, 'missing file or directory')); if (!(req.files && req.files.file) && !req.query.directory) return next(new HttpError(400, 'missing file or directory'));
if ((req.files && req.files.file) && req.query.directory) return next(new HttpError(400, 'either file or directory')); if ((req.files && req.files.file) && req.query.directory) return next(new HttpError(400, 'either file or directory'));
debug('post:', filePath);
var absoluteFilePath = getAbsolutePath(filePath); var absoluteFilePath = getAbsolutePath(filePath);
if (!absoluteFilePath || isProtected(absoluteFilePath)) return next(new HttpError(403, 'Path not allowed')); if (!absoluteFilePath || isProtected(absoluteFilePath)) return next(new HttpError(403, 'Path not allowed'));
fs.stat(absoluteFilePath, function (error, result) { fs.stat(absoluteFilePath, function (error, result) {
if (error && error.code !== 'ENOENT') return next(new HttpError(500, error)); if (error && error.code !== 'ENOENT') return next(new HttpError(500, error));
debug('put', absoluteFilePath);
if (result && req.query.directory) return next(new HttpError(409, 'name already exists')); if (result && req.query.directory) return next(new HttpError(409, 'name already exists'));
if (result && result.isDirectory()) return next(new HttpError(409, 'cannot put on directories')); if (result && result.isDirectory()) return next(new HttpError(409, 'cannot post on directories'));
if (req.query.directory) { if (req.query.directory) {
return createDirectory(absoluteFilePath, function (error) { return createDirectory(absoluteFilePath, function (error) {
...@@ -144,6 +145,30 @@ function put(req, res, next) { ...@@ -144,6 +145,30 @@ function put(req, res, next) {
}); });
} }
function put(req, res, next) {
var oldFilePath = decodeURIComponent(req.params[0]);
if (!req.body || !req.body.newFilePath) return next(new HttpError(400, 'missing newFilePath'));
var newFilePath = decodeURIComponent(req.body.newFilePath);
debug('put: %s -> %s', oldFilePath, newFilePath);
var absoluteOldFilePath = getAbsolutePath(oldFilePath);
if (!absoluteOldFilePath || isProtected(absoluteOldFilePath)) return next(new HttpError(403, 'Path not allowed'));
var absoluteNewFilePath = getAbsolutePath(newFilePath);
if (!absoluteNewFilePath || isProtected(absoluteNewFilePath)) return next(new HttpError(403, 'Path not allowed'));
fs.rename(absoluteOldFilePath, absoluteNewFilePath, function (error) {
if (error) return next (new HttpError(500, error));
debug('put: successful');
return next(new HttpSuccess(200, {}));
});
}
function del(req, res, next) { function del(req, res, next) {
var filePath = decodeURIComponent(req.params[0]); var filePath = decodeURIComponent(req.params[0]);
var recursive = !!req.query.recursive; var recursive = !!req.query.recursive;
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!