Ryu Sato 7 лет назад
Родитель
Сommit
8d9b6f057d

+ 10 - 0
lib/form/admin/importer.js

@@ -0,0 +1,10 @@
+'use strict';
+
+var form = require('express-form')
+  , field = form.field;
+
+module.exports = form(
+  field('settingForm[importer:esa:access_token]').required(),
+  field('settingForm[importer:esa:team_name]').required()
+);
+

+ 1 - 0
lib/form/index.js

@@ -36,5 +36,6 @@ module.exports = {
     slackIwhSetting: require('./admin/slackIwhSetting'),
     slackSetting: require('./admin/slackSetting'),
     userGroupCreate: require('./admin/userGroupCreate'),
+    importer: require('./admin/importer'),
   },
 };

+ 10 - 1
lib/locales/en-US/translation.json

@@ -458,6 +458,15 @@
     "your_own":"You cannot deactivate your own account",
     "Administrator menu":"Administrator menu",
     "cannot_remove":"You cannot remove yourself from administrator"
-  }
+  },
 
+  "importer_management": {
+    "esa_settings": {
+      "title": "Settings of esa importer",
+      "team_name": "Team name",
+      "access_token": "Access token"
+    },
+    "import": "Import",
+    "test_connection": "Test connection to esa"
+  }
 }

+ 11 - 1
lib/locales/ja/translation.json

@@ -91,6 +91,7 @@
   "External Account management": "外部アカウント管理",
   "UserGroup management": "グループ管理",
   "Full Text Search management": "全文検索管理",
+  "Importer management": "インポータ管理",
   "Basic settings": "基本設定",
   "Basic authentication": "Basic認証",
   "Guest users access": "ゲストユーザーのアクセス",
@@ -474,6 +475,15 @@
     "your_own": "自分自身のアカウントを停止することはできません",
     "Administrator menu": "管理者メニュー",
     "cannot_remove": "自分自身を管理者から外すことはできません"
-  }
+  },
 
+  "importer_management": {
+    "esa_settings": {
+      "title": "esaインポータ設定",
+      "team_name": "チーム名",
+      "access_token": "アクセストークン"
+    },
+    "import": "インポート",
+    "test_connection": "接続テスト"
+  }
 }

+ 3 - 0
lib/models/config.js

@@ -97,6 +97,9 @@ module.exports = function(crowi) {
       'customize:isEnabledTimeline' : true,
       'customize:isSavedStatesOfTabChanges' : true,
       'customize:isEnabledAttachTitleHeader' : false,
+
+      'importer:esa:team_name': '',
+      'importer:esa:access_token': '',
     };
     /* eslint-enable */
   }

+ 35 - 0
lib/routes/admin.js

@@ -873,6 +873,18 @@ module.exports = function(crowi, app) {
 
   };
 
+  // Importer management
+  actions.importer = {};
+  actions.importer.index = function(req, res) {
+
+    var settingForm;
+    settingForm = Config.setupCofigFormData('crowi', req.config);
+
+    return res.render('admin/importer', {
+      settingForm: settingForm,
+    });
+  }
+
   actions.api = {};
   actions.api.appSetting = function(req, res) {
     var form = req.form.settingForm;
@@ -1070,6 +1082,29 @@ module.exports = function(crowi, app) {
     });
   };
 
+  /**
+   * save settings, update config cache, and response json
+   *
+   * @param {*} req
+   * @param {*} res
+   */
+  actions.api.importerSetting = function(req, res) {
+    const form = req.form.settingForm;
+
+    if (req.form.isValid) {
+      debug('form content', form);
+      return saveSetting(req, res, form);
+    }
+    else {
+      return res.json({status: false, message: req.form.errors.join('\n')});
+    }
+  };
+
+  // app.get('/_api/importer/testEsaAPI');
+  actions.api.testEsaAPI = function(req, res) {
+    return res.json(ApiResponse.error());
+  }
+
   /**
    * save settings, update config cache, and response json
    *

+ 5 - 0
lib/routes/index.js

@@ -134,6 +134,11 @@ module.exports = function(crowi, app) {
   app.post('/admin/user-group-relation/create', loginRequired(crowi, app), middleware.adminRequired(), csrf, admin.userGroupRelation.create);
   app.post('/admin/user-group-relation/:id/remove-relation/:relationId', loginRequired(crowi, app), middleware.adminRequired(), csrf, admin.userGroupRelation.remove);
 
+  // importer management admin
+  app.get('/admin/importer'                , loginRequired(crowi, app) , middleware.adminRequired() , admin.importer.index);
+  app.post('/_api/admin/settings/importer' , loginRequired(crowi, app) , middleware.adminRequired() , csrf , form.admin.importer , admin.api.importerSetting);
+  app.post('/_api/imoprt/testEsaAPI'       , loginRequired(crowi, app) , form.admin.importer ,        admin.api.testEsaAPI);
+
   app.get('/me'                       , loginRequired(crowi, app) , me.index);
   app.get('/me/password'              , loginRequired(crowi, app) , me.password);
   app.get('/me/apiToken'              , loginRequired(crowi, app) , me.apiToken);

+ 170 - 0
lib/views/admin/importer.html

@@ -0,0 +1,170 @@
+{% extends '../layout/admin.html' %}
+
+{% block html_title %}{{ customTitle(t('Importer management')) }}{% endblock %}
+
+{% block content_header %}
+<div class="header-wrap">
+  <header id="page-header">
+    <h1 class="title" id="">{{ t('Importer management') }}</h1>
+  </header>
+</div>
+{% endblock %}
+
+{% block content_main %}
+<div class="content-main">
+
+  <div class="row">
+    <div class="col-md-3">
+      {% include './widget/menu.html' with {current: 'importer'} %}
+    </div>
+    <div class="col-md-9">
+
+      {% set smessage = req.flash('successMessage') %}
+      {% if smessage.length %}
+      <div class="alert alert-success">
+        {% for e in smessage %}
+          {{ e }}<br>
+        {% endfor %}
+      </div>
+      {% endif %}
+
+      {% set emessage = req.flash('errorMessage') %}
+      {% if emessage.length %}
+      <div class="alert alert-danger">
+        {% for e in emessage %}
+        {{ e }}<br>
+        {% endfor %}
+      </div>
+      {% endif %}
+
+      <form action="/_api/admin/settings/importer" method="post" class="form-horizontal" id="importerSettingForm" role="form">
+        <fieldset>
+          <!-- esa importer -->
+          <div class="form-group">
+            <legend>{{ t('importer_management.esa_settings.title') }}</legend>
+            <div class="form-group">
+              <label for="settingForm[importer:esa:team_name]" class="col-xs-3 control-label">{{ t('importer_management.esa_settings.team_name') }}</label>
+              <div class="col-xs-6">
+                <input class="form-control" type="text" name="settingForm[importer:esa:team_name]" value="{{ settingForm['importer:esa:team_name'] | default('') }}">
+              </div>
+            </div>
+            <div class="form-group">
+              <label for="settingForm[importer:esa:access_token]" class="col-xs-3 control-label">{{ t('importer_management.esa_settings.access_token') }}</label>
+              <div class="col-xs-6">
+                <input class="form-control" type="text" name="settingForm[importer:esa:access_token]" value="{{ settingForm['importer:esa:access_token'] | default('') }}">
+              </div>
+            </div>
+          </div>
+
+          <div class="form-group">
+            <div class="col-xs-offset-3 col-xs-6">
+            <button type="button" class="btn btn-primary" click="importFromEsa">
+              {{ t("importer_management.import") }}
+            </button>
+            <button type="submit" class="btn btn-secondary">{# the first element is the default button to submit #}
+              <input type="hidden" name="_csrf" value="{{ csrf() }}">
+              {{ t('Update') }}
+            </button>
+            <button type="button"
+                class="btn btn-default" click="test-connection-to-esa" data-toggle="modal">
+              {{ t("importer_management.test_connection") }}
+            </button>
+            </div>
+          </div>
+        </fieldset>
+      </form>
+    </div>
+  </div>
+
+</div>
+
+<script>
+  /**
+   * test connection to esa
+   */
+  function testConnectionToEsa() {
+    var $form = $('#importerSettingForm');
+    var $action = '/_api/import/testEsaAPI';
+    var jqxhr = $.post($action, $form.serialize(), function(data)
+      {
+        if (!data.status) {
+          alert("import failed");
+        }
+        else {
+          alert("import success");
+        }
+      })
+      .fail(function() {
+        alert("failed");
+      })
+      .always(function() {
+        $button.prop('disabled', false);
+      });
+    return false;
+  }
+
+  /**
+   * import from esa
+   */
+  function importFromEsa() {
+    alert('importFromEsa');
+  }
+
+  /**
+   * Handle submit button
+   */
+  $('#importerSettingForm').each(function() {
+    $(this).submit(function()
+    {
+      function showMessage(formId, msg, status) {
+        $('#' + formId + ' .alert').remove();
+
+        if (!status) {
+          status = 'success';
+        }
+        var $message = $('<p class="alert"></p>');
+        $message.addClass('alert-' + status);
+        $message.html(msg.replace('\n', '<br>'));
+        $message.insertAfter('#' + formId + ' legend');
+
+        if (status == 'success') {
+          setTimeout(function()
+          {
+            $message.fadeOut({
+              complete: function() {
+                $message.remove();
+              }
+            });
+          }, 5000);
+        }
+      }
+
+      var $form = $(this);
+      var $id = $form.attr('id');
+      var $button = $('button', this);
+      $button.attr('disabled', 'disabled');
+      var jqxhr = $.post($form.attr('action'), $form.serialize(), function(data)
+        {
+          if (data.status) {
+            showMessage($id, '更新しました');
+          } else {
+            showMessage($id, data.message, 'danger');
+          }
+        })
+        .fail(function() {
+          showMessage($id, 'エラーが発生しました', 'danger');
+        })
+        .always(function() {
+          $button.prop('disabled', false);
+      });
+      return false;
+    });
+  });
+
+
+</script>
+
+{% endblock content_main %}
+
+{% block content_footer %}
+{% endblock content_footer %}

+ 1 - 0
lib/views/admin/widget/menu.html

@@ -11,4 +11,5 @@
   <li class="{% if current == 'user' || current == 'external-account' %}active{% endif %}"><a href="/admin/users"><i class="icon-fw icon-user"></i> {{ t('User management') }}</a></li>
   <li class="{% if current == 'user-group'%}active{% endif %}"><a href="/admin/user-groups"><i class="icon-fw icon-people"></i> {{ t('UserGroup management') }}</a></li>
   <li class="{% if current == 'search'%}active{% endif %}"><a href="/admin/search"><i class="icon-fw icon-magnifier"></i> {{ t('Full Text Search management') }}</a></li>
+  <li class="{% if current == 'importer'%}active{% endif %}"><a href="/admin/importer"><i class="icon-fw icon-cloud-download"></i> {{ t('Importer management') }}</a></li>
 </ul>

+ 1 - 0
package.json

@@ -71,6 +71,7 @@
     "elasticsearch": "^15.0.0",
     "entities": "^1.1.1",
     "env-cmd": "^8.0.1",
+    "esa-nodejs": "^0.0.7",
     "escape-string-regexp": "^1.0.5",
     "express": "^4.16.1",
     "express-bunyan-logger": "^1.3.3",

+ 80 - 10
yarn.lock

@@ -533,7 +533,7 @@ async-limiter@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
 
-async@1.5.2:
+async@1.5.2, async@^1.4.0:
   version "1.5.2"
   resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
 
@@ -2038,10 +2038,14 @@ component-bind@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
 
-component-emitter@1.2.1, component-emitter@^1.2.1:
+component-emitter@1.2.1, component-emitter@^1.2.1, component-emitter@~1.2.0:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
 
+component-ie@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/component-ie/-/component-ie-1.0.0.tgz#0f9582ccb078a687592cc29eb46b3186e6fe637f"
+
 component-inherit@0.0.3:
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
@@ -2144,6 +2148,10 @@ cookie@0.3.1:
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
 
+cookiejar@2.0.6:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.0.6.tgz#0abf356ad00d1c5a219d88d44518046dd026acfe"
+
 cookies@0.7.1:
   version "0.7.1"
   resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.7.1.tgz#7c8a615f5481c61ab9f16c833731bcb8f663b99b"
@@ -2415,6 +2423,12 @@ debounce@^1.0.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.1.0.tgz#6a1a4ee2a9dc4b7c24bb012558dbcdb05b37f408"
 
+debug@2, debug@2.6.9, debug@^2.0.0, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6, debug@~2.6.9:
+  version "2.6.9"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+  dependencies:
+    ms "2.0.0"
+
 debug@2.6.4:
   version "2.6.4"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.4.tgz#7586a9b3c39741c0282ae33445c4e8ac74734fe0"
@@ -2427,12 +2441,6 @@ debug@2.6.8:
   dependencies:
     ms "2.0.0"
 
-debug@2.6.9, debug@^2.0.0, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6, debug@~2.6.9:
-  version "2.6.9"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
-  dependencies:
-    ms "2.0.0"
-
 debug@3.1.0, debug@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
@@ -2853,6 +2861,13 @@ es6-promise@3.2.1:
   version "3.2.1"
   resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4"
 
+esa-nodejs@^0.0.7:
+  version "0.0.7"
+  resolved "https://registry.yarnpkg.com/esa-nodejs/-/esa-nodejs-0.0.7.tgz#c4749412605ad430d5da17aa4928291927561b42"
+  dependencies:
+    superagent "^1.2.0"
+    superagent-no-cache "^0.1.0"
+
 escape-html@~1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
@@ -3133,6 +3148,10 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
     assign-symbols "^1.0.0"
     is-extendable "^1.0.1"
 
+extend@3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4"
+
 extend@^3.0.0, extend@^3.0.1, extend@~3.0.0, extend@~3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
@@ -3375,6 +3394,14 @@ forever-agent@~0.6.1:
   version "0.6.1"
   resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
 
+form-data@1.0.0-rc3:
+  version "1.0.0-rc3"
+  resolved "https://registry.yarnpkg.com/form-data/-/form-data-1.0.0-rc3.tgz#d35bc62e7fbc2937ae78f948aaa0d38d90607577"
+  dependencies:
+    async "^1.4.0"
+    combined-stream "^1.0.5"
+    mime-types "^2.1.3"
+
 form-data@~2.1.1:
   version "2.1.4"
   resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
@@ -3391,6 +3418,10 @@ form-data@~2.3.1:
     combined-stream "^1.0.5"
     mime-types "^2.1.12"
 
+formidable@~1.0.14:
+  version "1.0.17"
+  resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.0.17.tgz#ef5491490f9433b705faa77249c99029ae348559"
+
 forwarded@~0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
@@ -5142,7 +5173,7 @@ method-override@^2.3.10:
     parseurl "~1.3.2"
     vary "~1.1.2"
 
-methods@~1.1.2:
+methods@~1.1.1, methods@~1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
 
@@ -5207,7 +5238,7 @@ mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.16,
   dependencies:
     mime-db "~1.30.0"
 
-mime-types@~2.1.18:
+mime-types@^2.1.3, mime-types@~2.1.18:
   version "2.1.18"
   resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8"
   dependencies:
@@ -6674,6 +6705,10 @@ q@^1.0.1, q@^1.1.2:
   version "1.5.1"
   resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
 
+qs@2.3.3:
+  version "2.3.3"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-2.3.3.tgz#e9e85adbe75da0bbe4c8e0476a086290f863b404"
+
 qs@6.2.1:
   version "6.2.1"
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.1.tgz#ce03c5ff0935bc1d9d69a9f14cbd18e568d67625"
@@ -6909,6 +6944,15 @@ read-pkg@^3.0.0:
     string_decoder "~1.1.1"
     util-deprecate "~1.0.1"
 
+readable-stream@1.0.27-1:
+  version "1.0.27-1"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.27-1.tgz#6b67983c20357cefd07f0165001a16d710d91078"
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.1"
+    isarray "0.0.1"
+    string_decoder "~0.10.x"
+
 readable-stream@1.1.x:
   version "1.1.14"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
@@ -6980,6 +7024,10 @@ redis@^2.1.0:
     redis-commands "^1.2.0"
     redis-parser "^2.6.0"
 
+reduce-component@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/reduce-component/-/reduce-component-1.0.1.tgz#e0c93542c574521bea13df0f9488ed82ab77c5da"
+
 reduce-css-calc@^1.2.6:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716"
@@ -8021,6 +8069,28 @@ style-loader@^0.21.0:
     loader-utils "^1.1.0"
     schema-utils "^0.4.5"
 
+superagent-no-cache@^0.1.0:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/superagent-no-cache/-/superagent-no-cache-0.1.1.tgz#58ed8de9aeff053a9c98ae01dec4fde4b9f85fda"
+  dependencies:
+    component-ie "^1.0.0"
+
+superagent@^1.2.0:
+  version "1.8.5"
+  resolved "https://registry.yarnpkg.com/superagent/-/superagent-1.8.5.tgz#1c0ddc3af30e80eb84ebc05cb2122da8fe940b55"
+  dependencies:
+    component-emitter "~1.2.0"
+    cookiejar "2.0.6"
+    debug "2"
+    extend "3.0.0"
+    form-data "1.0.0-rc3"
+    formidable "~1.0.14"
+    methods "~1.1.1"
+    mime "1.3.4"
+    qs "2.3.3"
+    readable-stream "1.0.27-1"
+    reduce-component "1.0.1"
+
 supports-color@4.4.0:
   version "4.4.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e"