OSDN Git Service

implement /newuser/password API
authorhylom <hylom@users.sourceforge.jp>
Tue, 30 Oct 2018 11:41:51 +0000 (20:41 +0900)
committerhylom <hylom@users.sourceforge.jp>
Tue, 30 Oct 2018 11:41:51 +0000 (20:41 +0900)
src/newslash_web/lib/Newslash/Web.pm
src/newslash_web/lib/Newslash/Web/Controller/API/User.pm
src/newslash_web/lib/Newslash/Web/Controller/Login.pm
src/newslash_web/public/js/newslash.js
src/newslash_web/public/js/update-password.js [new file with mode: 0644]
src/newslash_web/templates/login/activation.html.tt2

index b90fff2..9030eee 100644 (file)
@@ -351,6 +351,7 @@ sub startup {
 
     $api->post('/newuser/validate')->to('API::User#validate_new_user');
     $api->post('/newuser/create')->to('API::User#create_new_user');
+    $api->post('/newuser/password')->to('API::User#update_password');
 
     $api->get('/sidebar/item')->to('API::SidebarItem#get', seclev => 1);
 
index a09a5b9..01a49f5 100644 (file)
@@ -220,6 +220,27 @@ sub post {
     return;
 }
 
+sub update_password {
+    my $c = shift;
+    my $params = $c->req->json;
+
+    if ($params->{token}) {
+        # token mode
+        if(!$c->users->update_password_by_token($params->{nickname},
+                                                $params->{token},
+                                                $params->{password})) {
+            $c->render(json => { error => $c->users->last_error || 1 });
+            $c->rendered(400);
+            return;
+        }
+        $c->render(json => {});
+        return;
+    }
+    $c->render(json => { error => 1 });
+    $c->rendered(400);
+    return;
+}
+
 sub validate_new_user {
     my $c = shift;
     my $params = $c->req->json;
@@ -229,14 +250,11 @@ sub validate_new_user {
 
     my $nick_regex = qr/^[a-zA-Z_][ a-zA-Z0-9\$_.+!*\\'(),-]{0,19}$/;
 
-    my ($id_error, $email_error) = $c->users->validate_new_user($nickname, $email);
-
-    if ($id_error || $email_error) {
-        $id_error ||= "";
-        $email_error ||= "";
+    if (!$c->users->validate_new_user($nickname, $email)) {
+        my $error = $c->users->last_error;
         $c->render(json => { error => 1,
-                             id_error => $id_error,
-                             email_error => $email_error,
+                             id_error => $error->{id_error} || "",
+                             email_error => $error->{email_error} || "",
                              nickname => $nickname,
                              email => $email });
         $c->rendered(400);
@@ -265,12 +283,12 @@ sub create_new_user {
 
     $email =~ s/\s//g; # strip whitespace
 
-    my ($uid, $error) = $c->users->create_new_user($nickname, $email, $options);
-
-    if ($error) {
+    my $uid = $c->users->create_new_user($nickname, $email, $options);
+    if(!$uid) {
+        my $error = $c->users->last_error;
         $c->render(json => { error => 1,
-                             id_error => $error->{id_error} || 0,
-                             email_error => $error->{email_error} || 0,
+                             id_error => $error->{id_error} || "",
+                             email_error => $error->{email_error} || "",
                              nickname => $nickname,
                              email => $email });
         $c->rendered(400);
index 1769c96..fac027c 100644 (file)
@@ -60,6 +60,7 @@ sub activation {
     my $cancel = $c->param("cancel");
 
     my $the_user = $users->select(nickname => $nickname);
+    my $prefs = { nickname => $nickname, token => $token };
 
     # check if token is correct
     if (!$the_user || !$token) {
@@ -76,19 +77,15 @@ sub activation {
     }
 
     # check if token is valid
-    my $rs = $users->activation($nickname, $token);
+    my $rs = $c->users->activation($nickname, $token);
     if (!$rs) {
-        $c->res->code(500);
-        return;
-    }
-    if ($rs->{error}) {
-        $c->render(activation_succeed => 0, error => $rs->{error});
+        $c->render(activation_succeed => 0, error => $c->users->last_error);
         $c->res->code(400);
         return;
     }
 
     # ok
-    $c->render(nickname => $nickname, activation_succeed => 1, error => 0);
+    $c->render(prefs => $prefs, activation_succeed => 1, error => "");
     return;
 }
 
index 3f69a84..7df714a 100644 (file)
@@ -122,6 +122,18 @@ function _initNewslash() {
     return this.post(url, data);
   };
 
+  /* user API */
+  Newslash.prototype.updatePasswordByToken = function (username, token, password, options) {
+    options = options || {};
+    var url = "/newuser/password";
+    var data = { nickname: username,
+                 token: token,
+                 password: password,
+                 options: options,
+               };
+    return this.post(url, data);
+  };
+
   /* comments API */
   Newslash.prototype.getComments = function getComments (discussionID, parentID) {
     if (!discussionID) return this.fail();
diff --git a/src/newslash_web/public/js/update-password.js b/src/newslash_web/public/js/update-password.js
new file mode 100644 (file)
index 0000000..6c73e45
--- /dev/null
@@ -0,0 +1,57 @@
+var updatePassword = {};
+
+updatePassword.run = function run(params) {
+
+  Vue.component('message', {
+    props: ["target", ],
+    template: '#message',
+  });
+
+  var data = {
+    password: "",
+    password2: "",
+    token: params.token || "",
+    nickname: params.nickname || "",
+    passwordError: "BLANK_PASSWORD",
+    formError: true,
+    state: "",
+  };
+
+  var methods = {};
+  methods.doPost = function doPost() {
+    this.state = "POSTING";
+    newslash.updatePasswordByToken(this.nickname, this.token, this.password).then(
+      (resp) => {
+        // ok
+        this.state = "SUCCEED";
+      },
+      (resp) => {
+        // failed
+        this.passwordError = resp.error || false;
+        this.formError = true;
+        this.state = "";
+      });
+  };
+
+  // form value validations
+  var watch = {};
+  watch.password = function watchPassword(val, oldVal) {
+    if (val.length == 0) { this.passwordError = "BLANK_PASSWORD"; }
+    else if (val != this.password2) { this.passwordError = "PASSWORD_NOT_MATCH"; }
+    else { this.passwordError = ""; }
+    this.formError = this.passwordError;
+  };
+  watch.password2 = function watchPassword2(val, oldVal) {
+    if (val != this.password) { this.passwordError = "PASSWORD_NOT_MATCH"; }
+    else { this.passwordError = ""; }
+    this.formError = this.passwordError;
+  };
+
+  var vm = new Vue({
+    el: params.el,
+    data: data,
+    methods: methods,
+    watch: watch,
+  });
+
+};
index 3228323..2e78617 100644 (file)
@@ -1,26 +1,31 @@
 [% WRAPPER common/layout %]
 
-[%- IF activation_succeed -%]
-<script type="text/x-template" id="password-message">
-  <div class="alert-error" v-else-if="target == 'PASSWORD_NOT_MATCH'">確認用パスワードと一致しません。</div>
+<script type="text/x-template" id="message">
+  <div class="alert-error"      v-if="target == 'PASSWORD_NOT_MATCH'">パスワードが一致しません</div>
+  <div class="alert-error" v-else-if="target == 'INVALID_PASSWORD'">不適切なパスワードです</div>
+  <div class="alert-error" v-else-if="target == 'BLANK_PASSWORD'">パスワードを入力してください</div>
   <div class="alert-error" v-else-if="target == 'SERVER_ERROR'">サーバーエラーが発生しました。</div>
+  <div class="alert-error" v-else-if="target != ''">サーバーエラーが発生しました。</div>
 </script>
 
-<div class="main-contents" id="password-prefs">
+[%- IF activation_succeed -%]
+<div class="main-contents" id="update-password">
   <div class="panel">
     <h3>パスワード設定</h3>
     <form id="password-update-form" action="/my/activation" method="POST">
+      <input type="hidden" name="nickname" value="[% prefs.nickname %]" v-model="nickname">
+      <input type="hidden" name="token" value="[% prefs.token %]" v-model="token">
       <div>
-        ユーザー「[% nickname %]」で使用するパスワードを入力してください。
+        ユーザー「[% prefs.nickname %]」で使用するパスワードを入力してください。
       </div>
       <label>パスワード:
-        [%- IF prefs.id_error %]
+        [%- IF prefs.password_error %]
         <div class="alert-error">
           [%- IF prefs.password_error == "PASSWORD_NOT_MATXH" -%]パスワードが一致しません。
           [%- ELSE %]エラー[% END -%]
         </div>
         [%- END %]
-        <password-message :target="passwordError"></password-message>
+        <message :target="passwordError"></message>
         <input id="password"  type="password" name="password" v-model="password"
                :disabled="state != ''"
                value="[% prefs.password %]"/>
       </label>
 
       <input class="btn btn-primary" :disabled="formError || state != ''" type="submit" @click.prevent.stop:="doPost" value="パスワードを設定する" />
-      <password-message :target="message"></password-message>
     </form>
+    <div class="alert-info" v-if="state == 'SUCCEED'">
+      パスワードを設定しました。<a href="/login">ログインページ</a>からこのパスワードでログインできます。
+    </div>
   </div><!-- .panel -->
 </div>
 
 [% helpers.load_js("activation.js") %]
 <script>
-  newUser.run({ el: '#password-prefs' });
+  updatePassword.run({ el: '#update-password', token: '[% prefs.token %]', nickname: '[% prefs.nickname %]' });
 </script>
 
 [%- ELSE #activation_succeed -%]
-<div class="main-contents" id="password-prefs">
+<div class="main-contents" id="update-password">
   <div class="panel">
     <h3>認証エラー</h3>
     [%- IF error == "TOKEN_EXPIRED" %]