Kaynağa Gözat

Feature: Activate invited user

Sotaro KARASAWA 11 yıl önce
ebeveyn
işleme
0e3cbdfd2a
6 değiştirilmiş dosya ile 173 ekleme ve 1 silme
  1. 1 0
      form/invited.js
  2. 21 0
      models/user.js
  3. 1 1
      routes/admin.js
  4. 2 0
      routes/index.js
  5. 38 0
      routes/login.js
  6. 110 0
      views/invited.html

+ 1 - 0
form/invited.js

@@ -5,6 +5,7 @@ var form = require('express-form')
 
 module.exports = form(
   field('invitedForm.username').required().is(/^[\da-zA-Z\-_]+$/),
+  field('invitedForm.name').required(),
   field('invitedForm.password').required().is(/^[\da-zA-Z@#$%-_&\+\*\?]{6,64}$/)
 );
 

+ 21 - 0
models/user.js

@@ -130,6 +130,15 @@ module.exports = function(app, models) {
     return this.updateGoogleId(null, callback);
   };
 
+  userSchema.methods.activateInvitedUser = function(username, name, password, callback) {
+    this.setPassword(password);
+    this.name = name;
+    this.username = username;
+    this.status = STATUS_ACTIVE;
+    this.save(function(err, userData) {
+      return callback(err, userData);
+    });
+  };
 
   userSchema.methods.removeFromAdmin = function(callback) {
     debug('Remove from admin', this);
@@ -265,6 +274,18 @@ module.exports = function(app, models) {
     });
   };
 
+  userSchema.statics.isRegisterableUsername = function(username, callback) {
+    var User = this;
+    var usernameUsable = true;
+
+    this.findOne({username: username}, function (err, userData) {
+      if (userData) {
+        usernameUsable = false;
+      }
+      return callback(usernameUsable);
+    });
+  };
+
   userSchema.statics.isRegisterable = function(email, username, callback) {
     var User = this;
     var emailUsable = true;

+ 1 - 1
routes/admin.js

@@ -247,7 +247,7 @@ module.exports = function(app) {
     smtpClient.sendMail({
       to: req.user.email,
       subject: 'Wiki管理設定のアップデートによるメール通知',
-      text: 'このメールのWikiSMTPメール送信設定のアップデートにより送信されています。'
+      text: 'このメールは、WikiのSMTP設定のアップデートにより送信されています。'
     }, callback);
   }
 

+ 2 - 0
routes/index.js

@@ -17,6 +17,8 @@ module.exports = function(app) {
 
   app.get('/login/error/:reason'     , login.error);
   app.get('/login'                   , middleware.applicationInstalled()    , login.login);
+  app.get('/login/invited'           , login.invited);
+  app.post('/login/activateInvited'  , form.invited                         , login.invited);
   app.post('/login'                  , form.login                           , login.login);
   app.post('/register'               , form.register                        , login.register);
   app.get('/register'                , middleware.applicationInstalled()    , login.register);

+ 38 - 0
routes/login.js

@@ -234,5 +234,43 @@ module.exports = function(app) {
     });
   };
 
+  actions.invited = function(req, res) {
+    if (!req.user) {
+      return res.redirect('/login');
+    }
+
+    if (req.method == 'POST' && req.form.isValid) {
+      var user = req.user;
+      var invitedForm = req.form.invitedForm || {};
+      var username = invitedForm.username;
+      var name = invitedForm.name;
+      var password = invitedForm.password;
+
+      User.isRegisterableUsername(username, function(creatable) {
+        if (creatable) {
+          user.activateInvitedUser(username, name, password, function(err, data) {
+            if (err) {
+              req.flash('warningMessage', 'アクティベートに失敗しました。');
+              return res.render('invited');
+            } else {
+              return res.redirect('/');
+            }
+          });
+        } else {
+          req.flash('warningMessage', '利用できないユーザーIDです。');
+          debug('username', username);
+          return res.render('invited');
+        }
+      });
+    } else {
+      return res.render('invited', {
+      });
+    }
+  };
+
+  actions.updateInvitedUser = function(req, res) {
+    return res.redirect('/');
+  };
+
   return actions;
 };

+ 110 - 0
views/invited.html

@@ -0,0 +1,110 @@
+{% extends 'layout/single-nologin.html' %}
+
+{% block html_title %}Registration · {% endblock %}
+
+{% block content_main %}
+
+<h1 class="login-page">
+  {% if config.crowi['app:title'] == 'Crowi' %}
+    <img src="/logo/135x32.png" alt="Crowi">
+  {% else %}
+    {{ config.crowi['app:title'] }}<br>
+    <img src="/logo/100x11_w.png" alt="powered by Crowi">
+  {% endif %}
+</h1>
+
+<div class="login-dialog-container flip-container col-md-5">
+
+<div class="login-dialog" id="login-dialog">
+
+  <div class="login-dialog-inner front">
+    <h2>ユーザー情報入力</h2>
+
+    <p>
+    ようこそ!<br>
+    はじめに、あなたのことを教えて下さい。
+    </p>
+
+    <div id="login-form-errors">
+      {% set message = req.flash('warningMessage') %}
+      {% if message.length %}
+      <div class="alert alert-danger">
+        {{ message }}
+      </div>
+      {% endif %}
+
+      {% if req.form.errors.length > 0 %}
+      <div class="alert alert-danger">
+        <ul>
+        {% for error in req.form.errors %}
+          <li>{{ error }}</li>
+        {% endfor %}
+        </ul>
+      </div>
+      {% endif %}
+    </div>
+    <form role="form" id="invited-form" action="/login/activateInvited" method="post">
+
+      <label>メールアドレス</label>
+      <div class="input-group">
+        <span class="input-group-addon"><i class="fa fa-envelope"></i></span>
+        <input type="text" class="form-control" disabled value="{{ user.email }}">
+      </div>
+      <p class="help-block">
+      このメールアドレスで招待を受け取っています。
+      </p>
+
+      <label>ユーザーID</label>
+      <div class="input-group" id="input-group-username">
+        <span class="input-group-addon"><strong>@</strong></span>
+        <input type="text" class="form-control" placeholder="記入例: taroyama" name="invitedForm[username]" value="{{ req.body.invitedForm.username }}" required>
+      </div>
+      <p class="help-block">
+      <span id="help-block-username" class="text-danger"></span>
+      ユーザーIDは、ユーザーページのURLなどに利用されます。半角英数字と一部の記号のみ利用できます。
+      </p>
+
+      <label>名前</label>
+      <div class="input-group">
+        <span class="input-group-addon"><i class="fa fa-user"></i></span>
+        <input type="text" class="form-control" placeholder="記入例: 山田 太郎" name="invitedForm[name]" value="{{ req.body.invitedForm.name }}" required>
+      </div>
+
+      <label>パスワード</label>
+      <div class="input-group">
+        <span class="input-group-addon"><i class="fa fa-key"></i></span>
+        <input type="password" class="form-control" placeholder="Password" name="invitedForm[password]" required>
+      </div>
+      <p class="help-block">
+      現在、仮パスワードでログインしています。新しいパスワードを決定してください。<br>
+      パスワードは6文字以上の半角英数字または記号
+      </p>
+
+      <input type="submit" class="btn btn-primary btn-lg btn-block" value="登録を完了">
+    </form>
+
+    <hr>
+
+  </div>
+</div>
+
+<script>
+$(function() {
+  $('#invited-form input[name="invitedForm[username]"]').change(function(e) {
+    var username = $(this).val();
+    $('#input-group-username').removeClass('has-error');
+    $('#help-block-username').html("");
+
+    $.getJSON('/_api/check_username', {username: username}, function(json) {
+      if (!json.valid) {
+        $('#help-block-username').html('<i class="fa fa-warning"></i>このユーザーIDは利用できません。<br>');
+        $('#input-group-username').addClass('has-error');
+      }
+    });
+  });
+});
+</script>
+</div>
+
+{% endblock %}
+