]> git.immae.eu Git - perso/Immae/Projets/Nodejs/Surfer.git/commitdiff
Add rename functionality
authorJohannes Zellner <johannes@cloudron.io>
Tue, 7 Feb 2017 15:26:17 +0000 (16:26 +0100)
committerJohannes Zellner <johannes@cloudron.io>
Tue, 7 Feb 2017 15:26:19 +0000 (16:26 +0100)
This also break backwardscompat since PUT is now POST
and PUT is used for renaming

cli/actions.js
frontend/index.html
frontend/js/app.js
server.js
src/files.js

index 69ffa10329e225d7592791468e9c51e284369b13..ea2a3a1d1e5b6280151bf3ea7076b31da54c902d 100644 (file)
@@ -118,7 +118,7 @@ function put(filePath, otherFilePaths, options) {
         var destinationPath = (destination ? '/' + destination : '') + '/' + relativeFilePath;
         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 !== 201) return callback(new Error('Error uploading file: ' + result.statusCode));
             if (error) return callback(error);
index e9775e808e63ad289210c99c5e7543fc8a7499c5..cbbd85e75460d62d37bbcd2023651ccb501ea200 100644 (file)
@@ -41,7 +41,7 @@
                 </div>
                 <div class="modal-body">
                     <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 class="modal-footer">
                     <button type="button" class="btn btn-default" data-dismiss="modal">No</button>
         </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-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">New Directory Name</h4>
+                    <h4 class="modal-title">New directory name</h4>
                 </div>
                 <div class="modal-body">
                     <form v-on:submit.prevent="createDirectory(createDirectoryData)">
                         <a href="{{ part.link }}">{{ part.name }}</a>
                     </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>
             </div>
             <div class="col-lg-12">
                         </tr>
                     </thead>
                     <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">
                             <th>
                                 <img v-bind:src="entry.previewUrl" height="48px" width="48px"/>
                             <th><span v-my-tooltip="foobar" data-toggle="tooltip" title="{{ entry.mtime }}">{{ entry.mtime | prettyDate }}</span></th>
                             <th style="text-align: right;">
                                 <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>
                                 </span>
                             </th>
index e0464f8191906afd0c57334f49461b9d93ad3ce8..078473a9516e55901bdcd621bdbb76ef0e433009 100644 (file)
@@ -141,7 +141,7 @@ function upload() {
             var formData = new FormData();
             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 !== 201) console.error('Error uploading file: ', result.statusCode);
                 if (error) console.error(error);
@@ -149,8 +149,6 @@ function upload() {
                 app.uploadStatus.done += 1;
                 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) {
                     app.uploadStatus = {
                         busy: false,
@@ -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() {
     $('#modalcreateDirectory').modal('show');
     app.createDirectoryData = '';
@@ -210,7 +235,7 @@ function createDirectory(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;
 
         if (result && result.statusCode === 401) return logout();
@@ -258,6 +283,11 @@ var app = new Vue({
         },
         loginData: {},
         deleteData: {},
+        renameData: {
+            entry: {},
+            error: null,
+            newFilePath: ''
+        },
         createDirectoryData: '',
         createDirectoryError: null,
         entries: []
@@ -271,6 +301,8 @@ var app = new Vue({
         upload: upload,
         delAsk: delAsk,
         del: del,
+        renameAsk: renameAsk,
+        rename: rename,
         createDirectoryAsk: createDirectoryAsk,
         createDirectory: createDirectory
     }
index edd8a752ef381efe547af4b726978d64b27d674b..67cbd915851c530659e4ed7f0e6d881f2b6ed8ba 100755 (executable)
--- a/server.js
+++ b/server.js
@@ -24,7 +24,8 @@ var router = new express.Router();
 var multipart = multipart({ maxFieldsSize: 2 * 1024, limit: '512mb', timeout: 3 * 60 * 1000 });
 
 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.get   ('/api/healthcheck', function (req, res) { res.status(200).send(); });
 
index 747acf7cf1cf5b586af88e32ed3741094ae00577..876ff4e96798b938708cec8dfca372b8e39b56d5 100644 (file)
@@ -17,6 +17,7 @@ exports = module.exports = function (basePath) {
     return {
         get: get,
         put: put,
+        post: post,
         del: del
     };
 };
@@ -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]);
 
     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'));
 
+    debug('post:', filePath);
+
     var absoluteFilePath = getAbsolutePath(filePath);
     if (!absoluteFilePath || isProtected(absoluteFilePath)) return next(new HttpError(403, 'Path not allowed'));
 
     fs.stat(absoluteFilePath, function (error, result) {
         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 && 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) {
             return createDirectory(absoluteFilePath, function (error) {
@@ -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) {
     var filePath = decodeURIComponent(req.params[0]);
     var recursive = !!req.query.recursive;