Просмотр исходного кода

Merge branch 'wip-v1.6' into support-i18n

Sotaro KARASAWA 9 лет назад
Родитель
Сommit
cc193ff39d

+ 2 - 1
README.md

@@ -30,12 +30,13 @@ More info are [here](https://github.com/crowi/crowi/wiki/Install-and-Configurati
 ### WARNING
 
 Don't use `master` branch because it is unstable but use released tag version expect when you want to contribute the project.
+`master` branch is prepared for v1.6. See [here](https://github.com/crowi/crowi/wiki/Roadmaps-v1.6) to know further info.
 
 
 Dependencies
 -------------
 
-* Node.js (4.x)
+* Node.js (6.x)
 * MongoDB
 * Elasticsearch (optional)
 * Redis (optional)

+ 2 - 2
circle.yml

@@ -5,9 +5,9 @@ machine:
   environment:
     MONGO_URI: mongodb://127.0.0.1/crowi_test
   node:
-      version: 4.6.2
+      version: 6.9.4
   post:
-    - npm install -g npm@3
+    - npm install -g npm@4
 notify:
   webhooks:
     - url: https://webhooks.gitter.im/e/5a035388e3274b621d20

+ 0 - 2
lib/crowi/express-init.js

@@ -4,7 +4,6 @@ module.exports = function(crowi, app) {
   var debug = require('debug')('crowi:crowi:express-init')
     , express        = require('express')
     , bodyParser     = require('body-parser')
-    , multer         = require('multer')
     , cookieParser   = require('cookie-parser')
     , methodOverride = require('method-override')
     , session        = require('express-session')
@@ -95,7 +94,6 @@ module.exports = function(crowi, app) {
   app.use(bodyParser.urlencoded({ extended: true, limit: '50mb' }));
   app.use(bodyParser.json({limit: '50mb'}));
   app.use(cookieParser());
-  app.use(multer());
   app.use(session(crowi.sessionConfig));
   app.use(flash());
 

+ 4 - 4
lib/crowi/index.js

@@ -6,7 +6,6 @@ var debug = require('debug')('crowi:crowi')
   , path = require('path')
   , fs = require('fs')
   , sep = path.sep
-  , Promise = require('bluebird')
 
   , mongoose    = require('mongoose')
 
@@ -55,7 +54,6 @@ function Crowi (rootdir, env)
   };
 
   if (this.node_env == 'development') {
-    Promise.longStackTraces();
   }
 
   //time.tzset('Asia/Tokyo');
@@ -64,7 +62,7 @@ function Crowi (rootdir, env)
 Crowi.prototype.init = function() {
   var self = this;
 
-  return new Promise.resolve()
+  return Promise.resolve()
   .then(function() {
     // setup database server and load all modesl
     return self.setupDatabase();
@@ -143,6 +141,8 @@ Crowi.prototype.event = function(name, event) {
 
 Crowi.prototype.setupDatabase = function() {
   // mongoUri = mongodb://user:password@host/dbname
+  mongoose.Promise = global.Promise;
+
   var mongoUri = this.env.MONGOLAB_URI || // for B.C.
     this.env.MONGODB_URI || // MONGOLAB changes their env name
     this.env.MONGOHQ_URL ||
@@ -328,7 +328,7 @@ Crowi.prototype.buildServer = function() {
     });
   }
 
-  return new Promise.resolve(app);
+  return Promise.resolve(app);
 };
 
 Crowi.prototype.exitOnError = function(err) {

+ 1 - 2
lib/models/attachment.js

@@ -2,7 +2,6 @@ module.exports = function(crowi) {
   var debug = require('debug')('crowi:models:attachment')
     , mongoose = require('mongoose')
     , ObjectId = mongoose.Schema.Types.ObjectId
-    , Promise = require('bluebird')
     , fileUploader = require('../util/fileUploader')(crowi)
   ;
 
@@ -101,7 +100,7 @@ module.exports = function(crowi) {
   };
 
   attachmentSchema.statics.createAttachmentFilePath = function (pageId, fileName, fileType) {
-    var ext = '.' + fileName.match(/(.*)(?:\.([^.]+$))/)[2];
+    var ext = '.' + fileName.match(/(.*)(?:\.([^.]+$))/)[2] || '';
 
     return 'attachment/' + pageId + '/' + generateFileHash(fileName) + ext;
   };

+ 11 - 10
lib/routes/attachment.js

@@ -5,7 +5,6 @@ module.exports = function(crowi, app) {
     , Attachment = crowi.model('Attachment')
     , User = crowi.model('User')
     , Page = crowi.model('Page')
-    , Promise = require('bluebird')
     , config = crowi.getConfig()
     , fs = require('fs')
     , fileUploader = require('../util/fileUploader')(crowi, app)
@@ -68,7 +67,7 @@ module.exports = function(crowi, app) {
 
     debug('id and path are: ', id, path);
 
-    var tmpFile = req.files.file || null;
+    var tmpFile = req.file || null;
     debug('Uploaded tmpFile: ', tmpFile);
     if (!tmpFile) {
       return res.json(ApiResponse.error('File error.'));
@@ -95,7 +94,7 @@ module.exports = function(crowi, app) {
 
       var tmpPath = tmpFile.path,
         originalName = tmpFile.originalname,
-        fileName = tmpFile.name,
+        fileName = tmpFile.filename + tmpFile.originalname,
         fileType = tmpFile.mimetype,
         fileSize = tmpFile.size,
         filePath = Attachment.createAttachmentFilePath(id, fileName, fileType),
@@ -118,19 +117,21 @@ module.exports = function(crowi, app) {
 
           result.page.creator = User.filterToPublicFields(result.page.creator);
           result.attachment.creator = User.filterToPublicFields(result.attachment.creator);
+
+          // delete anyway
+          fs.unlink(tmpPath, function (err) { if (err) { debug('Error while deleting tmp file.'); } });
+
           return res.json(ApiResponse.success(result));
         }).catch(function (err) {
           debug('Error on saving attachment data', err);
           // @TODO
           // Remove from S3
+
+          // delete anyway
+          fs.unlink(tmpPath, function (err) { if (err) { debug('Error while deleting tmp file.'); } });
+
           return res.json(ApiResponse.error('Error while uploading.'));
-        }).finally(function() {
-          fs.unlink(tmpPath, function (err) {
-            if (err) {
-              debug('Error while deleting tmp file.');
-            }
-          });
-        })
+        });
       ;
     }).catch(function(err) {
       debug('Attachement upload error', err);

+ 4 - 2
lib/routes/index.js

@@ -1,5 +1,7 @@
 module.exports = function(crowi, app) {
   var middleware = require('../util/middlewares')
+    , multer    = require('multer')
+    , uploads   = multer({dest: crowi.tmpDir + 'uploads'})
     , form      = require('../form')
     , page      = require('./page')(crowi, app)
     , login     = require('./login')(crowi, app)
@@ -85,7 +87,7 @@ module.exports = function(crowi, app) {
   app.get( '/_api/search'             , accessTokenParser , loginRequired(crowi, app) , search.api.search);
 
   app.get( '/_api/check_username'     , user.api.checkUsername);
-  app.post('/_api/me/picture/upload'  , loginRequired(crowi, app) , me.api.uploadPicture);
+  app.post('/_api/me/picture/upload'  , loginRequired(crowi, app) , uploads.single('userPicture'), me.api.uploadPicture);
   app.get( '/_api/user/bookmarks'     , loginRequired(crowi, app) , user.api.bookmarks);
 
   app.get( '/user/:username([^/]+)/bookmarks'      , loginRequired(crowi, app) , page.userBookmarkList);
@@ -109,7 +111,7 @@ module.exports = function(crowi, app) {
   app.post('/_api/likes.add'          , accessTokenParser , loginRequired(crowi, app) , csrf, page.api.like);
   app.post('/_api/likes.remove'       , accessTokenParser , loginRequired(crowi, app) , csrf, page.api.unlike);
   app.get( '/_api/attachments.list'   , accessTokenParser , loginRequired(crowi, app) , attachment.api.list);
-  app.post('/_api/attachments.add'    , accessTokenParser , loginRequired(crowi, app) , csrf, attachment.api.add);
+  app.post('/_api/attachments.add'    , accessTokenParser , loginRequired(crowi, app) , uploads.single('file'), csrf, attachment.api.add);
   app.post('/_api/attachments.remove' , accessTokenParser , loginRequired(crowi, app) , csrf, attachment.api.remove);
 
   app.get( '/_api/revisions.get'      , accessTokenParser , loginRequired(crowi, app) , revision.api.get);

+ 2 - 2
lib/routes/me.js

@@ -20,7 +20,7 @@ module.exports = function(crowi, app) {
     //var storagePlugin = new pluginService('storage');
     //var storage = require('../service/storage').StorageService(config);
 
-    var tmpFile = req.files.userPicture || null;
+    var tmpFile = req.file || null;
     if (!tmpFile) {
       return res.json({
         'status': false,
@@ -29,7 +29,7 @@ module.exports = function(crowi, app) {
     }
 
     var tmpPath = tmpFile.path;
-    var filePath = User.createUserPictureFilePath(req.user, tmpFile.name);
+    var filePath = User.createUserPictureFilePath(req.user, tmpFile.filename + tmpFile.originalname);
     var acceptableFileType = /image\/.+/;
 
     if (!tmpFile.mimetype.match(acceptableFileType)) {

+ 1 - 0
lib/util/middlewares.js

@@ -43,6 +43,7 @@ exports.csrfVerify = function(crowi, app) {
       return next();
     }
 
+    debug('csrf verification failed. return 403', csrfKey, token);
     return res.sendStatus(403);
   };
 };

+ 1 - 2
local_modules/crowi-fileupload-aws/index.js

@@ -5,7 +5,6 @@ module.exports = function(crowi) {
 
   var aws = require('aws-sdk')
     , debug = require('debug')('crowi:lib:fileUploaderAws')
-    , Promise = require('bluebird')
     , Config = crowi.model('Config')
     , config = crowi.getConfig()
     , lib = {}
@@ -29,7 +28,7 @@ module.exports = function(crowi) {
   lib.uploadFile = function(filePath, contentType, fileStream, options) {
     var awsConfig = getAwsConfig();
     if (!Config.isUploadable(config)) {
-      return new Promise.reject(new Error('AWS is not configured.'));
+      return Promise.reject(new Error('AWS is not configured.'));
     }
 
     aws.config.update({

Разница между файлами не показана из-за своего большого размера
+ 278 - 434
npm-shrinkwrap.json


+ 18 - 19
package.json

@@ -1,6 +1,6 @@
 {
   "name": "crowi",
-  "version": "1.5.3",
+  "version": "1.6.0",
   "description": "The simple & powerful Wiki",
   "tags": [
     "wiki",
@@ -24,19 +24,18 @@
     "url": "https://github.com/crowi/crowi.git"
   },
   "engines": {
-    "node": "4.x",
-    "npm": "3.x"
+    "node": "6.x",
+    "npm": "4.x"
   },
   "dependencies": {
     "async": "~1.5.0",
     "aws-sdk": "~2.2.26",
-    "axios": "0.13.x",
+    "axios": "0.15.x",
     "babel-core": "~6.7.6",
     "babel-loader": "~6.2.4",
     "babel-preset-es2015": "~6.6.0",
     "babel-preset-react": "~6.5.0",
     "basic-auth-connect": "~1.0.0",
-    "bluebird": "~3.0.5",
     "body-parser": "~1.14.1",
     "bootstrap-sass": "~3.3.6",
     "botkit": "~0.1.1",
@@ -45,7 +44,7 @@
     "commander": "~2.9.0",
     "connect-flash": "~0.1.1",
     "connect-redis": "~2.1.0",
-    "consolidate": "~0.11.0",
+    "consolidate": "~0.14.0",
     "cookie-parser": "~1.3.4",
     "csrf": "~3.0.3",
     "debug": "~2.2.0",
@@ -54,21 +53,21 @@
     "elasticsearch": "~11.0.1",
     "emojify.js": "^1.1.0",
     "errorhandler": "~1.3.4",
-    "express": "~4.13.3",
+    "express": "~4.14.0",
     "express-form": "~0.12.0",
-    "express-session": "~1.12.0",
-    "font-awesome": "~4.5.0",
+    "express-session": "~1.14.0",
+    "font-awesome": "~4.7.0",
     "googleapis": "=12.3.0",
     "gulp": "~3.9.0",
     "gulp-concat": "~2.6.0",
     "gulp-cssmin": "~0.1.7",
     "gulp-jshint": "~1.12.0",
     "gulp-rename": "~1.2.2",
-    "gulp-sass": "~3.0.0",
+    "gulp-sass": "~3.1.0",
     "gulp-spawn-mocha": "~2.2.1",
     "gulp-uglify": "~1.4.2",
     "gulp-watch": "~4.3.5",
-    "highlight.js": "~9.0.0",
+    "highlight.js": "~9.9.0",
     "i18next": "~4.1.0",
     "i18next-express-middleware": "~1.0.2",
     "i18next-node-fs-backend": "~0.1.3",
@@ -77,20 +76,20 @@
     "jquery": "~2.1.4",
     "jquery.cookie": "~1.4.1",
     "jshint-stylish": "~2.1.0",
-    "kerberos": "0.0.17",
+    "kerberos": "0.0.22",
     "marked": "~0.3.5",
     "method-override": "~2.3.1",
     "mkdirp": "~0.5.1",
     "moment": "~2.13.0",
-    "mongoose": "4.2.5",
-    "mongoose-paginate": "4.2.0",
-    "morgan": "~1.5.1",
-    "multer": "~0.1.8",
-    "nodemailer": "~1.2.2",
-    "nodemailer-ses-transport": "~1.1.0",
+    "mongoose": "4.7.x",
+    "mongoose-paginate": "5.0.x",
+    "morgan": "~1.7.0",
+    "multer": "~1.2.1",
+    "nodemailer": "~2.7.0",
+    "nodemailer-ses-transport": "~1.5.0",
     "react": "~15.0.1",
     "react-dom": "~15.0.1",
-    "redis": "~0.12.1",
+    "redis": "~2.6.5",
     "reveal.js": "~3.2.0",
     "socket.io": "~1.3.0",
     "socket.io-client": "~1.3.0",

+ 3 - 2
resource/js/components/SeenUserList.js

@@ -15,6 +15,7 @@ export default class SeenUserList extends React.Component {
 
   componentDidMount() {
     const seenUserIds = this.getSeenUserIds();
+
     if (seenUserIds.length > 0) {
       // FIXME: user data cache
       this.crowi.apiGet('/users.list', {user_ids: seenUserIds.join(',')})
@@ -41,12 +42,12 @@ export default class SeenUserList extends React.Component {
 
   render() {
     return (
-      <p className="seen-user-list">
+      <div className="seen-user-list">
         <p className="seen-user-count">
           {this.state.seenUsers.length}
         </p>
         <UserList users={this.state.seenUsers} />
-      </p>
+      </div>
     );
   }
 }

+ 13 - 0
resource/js/components/SeenUserList/UserList.js

@@ -3,7 +3,20 @@ import UserPicture from '../User/UserPicture';
 
 export default class UserList extends React.Component {
 
+  isSeenUserListShown() {
+    const userCount = this.props.users.length;
+    if (0 < userCount && userCount <= 10) {
+      return true;
+    }
+
+    return false;
+  }
+
   render() {
+    if (!this.isSeenUserListShown()) {
+      return null;
+    }
+
     const users = this.props.users.map((user) => {
       return (
         <a key={user._id} data-user-id={user._id} href={'/user/' + user.username} title={user.name}>

+ 8 - 3
resource/js/crowi-form.js

@@ -254,7 +254,10 @@ $(function() {
         }
       }
       //$target.selection('insert', {text: "\n" + listMark, mode: 'before'});
-      insertText(currentLine.start, currentLine.end, "\n" + listMark, 'after');
+      var pos = $target.selection('getPos');
+      insertText(pos.start, pos.start, "\n" + listMark, 'replace');
+      var newPosition = pos.start + ("\n" + listMark).length;
+      $target.selection('setPos', {start: newPosition, end: newPosition});
     } else if (currentLine.text.match(/^(\s*(?:-|\+|\*|\d+\.) )/)) {
       // remove list
       $target.selection('setPos', {start: currentLine.start, end: currentLine.end});
@@ -276,11 +279,13 @@ $(function() {
       var prevLine = getPrevLine(event);
       if (!prevLine || (!currentLine.text.match(/---/) && !prevLine.text.match(/\|/g))) {
         //$target.selection('insert', {text: "\n" + row.join(' --- ') + "\n" + row.join('  '), mode: 'before'});
-        insertText(currentLine.start, currentLine.end, "\n" + row.join(' --- ') + "\n" + row.join('  '), 'after');
+        var pos = $target.selection('getPos');
+        insertText(pos.start, pos.start, "\n" + row.join(' --- ') + "\n" + row.join('  '), 'after');
         $target.selection('setPos', {start: currentLine.caret + 6 * row.length - 1, end: currentLine.caret + 6 * row.length - 1});
       } else {
         //$target.selection('insert', {text: "\n" + row.join('  '), mode: 'before'});
-        insertText(currentLine.start, currentLine.end, "\n" + row.join('  '), 'after');
+        var pos = $target.selection('getPos');
+        insertText(pos.start, pos.end, "\n" + row.join('  '), 'after');
         $target.selection('setPos', {start: currentLine.caret + 3, end: currentLine.caret + 3});
       }
     }

+ 0 - 2
test/bootstrap.js

@@ -1,10 +1,8 @@
 'use strict';
 
 var express = require('express')
-  , async = require('async')
   , ROOT_DIR = __dirname + '/..'
   , MODEL_DIR = __dirname + '/../lib/models'
-  , Promise = require('bluebird')
   , testDBUtil
   ;
 

+ 3 - 1
test/crowi/crowi.test.js

@@ -5,7 +5,6 @@ var chai = require('chai')
   , proxyquire = require('proxyquire')
 
   , path = require('path')
-  , Promise = require('bluebird')
   ;
 chai.use(sinonChai);
 
@@ -38,6 +37,9 @@ describe('Test for Crowi application context', function () {
   });
 
   describe('.setupDatabase', function() {
+    before(function() {
+      mongoose.disconnect(); // avoid error of Trying to open unclosed connection
+    });
     it('setup completed', function(done) {
       var crowi = new Crowi(path.normalize(__dirname + '/../../'), process.env);
       // set

+ 0 - 1
test/models/config.test.js

@@ -2,7 +2,6 @@ var chai = require('chai')
   , expect = chai.expect
   , sinon = require('sinon')
   , sinonChai = require('sinon-chai')
-  , Promise = require('bluebird')
   , utils = require('../utils.js')
   ;
 chai.use(sinonChai);

+ 0 - 1
test/models/page.test.js

@@ -2,7 +2,6 @@ var chai = require('chai')
   , expect = chai.expect
   , sinon = require('sinon')
   , sinonChai = require('sinon-chai')
-  , Promise = require('bluebird')
   , utils = require('../utils.js')
   ;
 chai.use(sinonChai);

+ 0 - 1
test/models/updatePost.test.js

@@ -2,7 +2,6 @@ var chai = require('chai')
   , expect = chai.expect
   , sinon = require('sinon')
   , sinonChai = require('sinon-chai')
-  , Promise = require('bluebird')
   , utils = require('../utils.js')
   ;
 chai.use(sinonChai);

+ 0 - 1
test/models/user.test.js

@@ -2,7 +2,6 @@ var chai = require('chai')
   , expect = chai.expect
   , sinon = require('sinon')
   , sinonChai = require('sinon-chai')
-  , Promise = require('bluebird')
   , utils = require('../utils.js')
   ;
 chai.use(sinonChai);

+ 1 - 0
test/utils.js

@@ -7,6 +7,7 @@ var mongoUri = process.env.MONGOLAB_URI || process.env.MONGOHQ_URL || process.en
   , crowi = new (require(ROOT_DIR + '/lib/crowi'))(ROOT_DIR, process.env)
   ;
 
+mongoose.Promise = global.Promise;
 
 before('Create database connection and clean up', function (done) {
   if (!mongoUri) {

+ 1 - 0
tmp/uploads/.gitignore

@@ -0,0 +1 @@
+*

Некоторые файлы не были показаны из-за большого количества измененных файлов