OSDN Git Service

implement ReCaptcha support
authorhylom <hylom@users.sourceforge.jp>
Tue, 23 May 2017 12:38:03 +0000 (21:38 +0900)
committerhylom <hylom@users.sourceforge.jp>
Tue, 23 May 2017 12:38:03 +0000 (21:38 +0900)
src/newslash_web/lib/Newslash/Web.pm
src/newslash_web/public/js/article-item2.js
src/newslash_web/templates/common/captcha/recaptcha.html.tt2 [new file with mode: 0644]
src/newslash_web/templates/common/header.html.tt2
src/newslash_web/templates/submission/submission.html.tt2

index 80aafe3..f59dc30 100644 (file)
@@ -163,7 +163,7 @@ sub startup {
     $r->get('/journal/:id/')->to('journal#journal');
 
     # submission page
-    $r->get('/submission/new')->to('submission#create');
+    $r->get('/submission/new')->to('submission#create', use_captcha => 1);
     $r->get('/submission/:id/')->to('submission#submission');
     #$r->post('/submission')->to('submission#create');
 
index 8429b0b..624e948 100644 (file)
@@ -22,6 +22,7 @@ articleItem.init = function init () {
         
       showForm: true,
       showSubmit: false,
+      disablePost: false,
       message: "",
       createdUrl: "",
       currentTopics: [],
@@ -45,8 +46,12 @@ articleItem.init = function init () {
   var props = {
     item: {
       type: Object,
-      default: function () {return new Contents();}
+      default: function () {return new Contents();},
     },
+    showEditor: {
+      type: Boolean,
+      default: false,
+    }
   };
 
   var watch = {
@@ -88,7 +93,7 @@ articleItem.init = function init () {
   }
 
   function editable() {
-    return (vm.user.uid == this.item.uid);
+    return (this.vm.user.uid == this.item.uid);
   }
 
   function url() {
@@ -120,6 +125,12 @@ articleItem.init = function init () {
   }
 
   function showPreview(event) {
+    if (!articleItem.token) {
+      grecaptcha.execute();
+      statusBar.init();
+      statusBar.loading("checking if you are not a bot...");
+    }
+
     var url = this.urls[this.item.content_type];
     var postData = {};
     Object.keys(this.item).forEach(k => {
@@ -145,6 +156,11 @@ articleItem.init = function init () {
   }
 
   function postItem(event) {
+    if (!user.is_login && !articleItem.token) {
+      return;
+    }
+    
+    // load captcha
     this.message = "";
     var url = this.urls[this.item.content_type];
     var postData = {};
@@ -157,6 +173,10 @@ articleItem.init = function init () {
     postData.tags_string = this.tagsString;
     postData.related_urls = this.relatedUrls;
 
+    if (articleItem.token) {
+        postData.recaptcha_token = articleItem.token;
+    }
+
     this.$http.post(url, {item: postData, action: 'post'}).then(
       (response) => { // success
         this.message = "";
@@ -252,27 +272,39 @@ articleItem.init = function init () {
   // end of methods
 
   function created() {
+    if (this.showEditor) {
+      editing = 1;
+    }
+
+    // story edit mode
     if (page.type == 'story' && page.stoid) {
       this.cancelable = 1;
       // load story data
       var url = "/api/v1/story?stoid=" + page.stoid;
       loadItem(this, url);
     }
+
+    // submission to story mode
     if (this.item.submission_id) {
-      vue.item.author = vue.item.author || user.nickname;
+      this.item.author = this.item.author || user.nickname;
       // load submission data
       var url = "/api/v1/submission?subid=" + this.item.submission_id;
       this.$http.get(url).then(
         (resp) => { // succeed
           this.title = resp.body.item.title;
           this.introtext = resp.body.item.drafttext;
-          initItem(this);
+          initEditor(this);
         },
         (resp) => { //failed
           this.message = resp.body.message;
-          initItem();
+          initEditor(this);
         });
     }
+
+    // submission edit mode
+    if (this.item.content_type == 'submission') {
+      initEditor(this);
+    }
   }
 
   function loadItem(vue, url) {
@@ -299,12 +331,17 @@ articleItem.init = function init () {
       }
     }
     vue.createtime = nsUtil.decodeDateTime(vue.item.createtime);
-    var tagnames = vue.item.tags.map(x => {return x.tagname});
-    vue.tagsString = tagnames.join(" ");
+    if (vue.item.tags) {
+      var tagnames = vue.item.tags.map(x => {return x.tagname});
+      vue.tagsString = tagnames.join(" ");
+    } else {
+      vue.tagsString = "";
+    }
+    
     updateTopics.call(vue);
   }
   
-  Vue.component('article-item', {
+   Vue.component('article-item', {
     template: '#article-item-template',
     props: props,
     data: data,
@@ -341,3 +378,9 @@ articleItem.addTrigger = function addTrigger (selector, params) {
 
 articleItem.init();
 
+function recaptchaDone(token) {
+  statusBar.hide();
+  articleItem.token = token;
+  console.log(token);
+}
+  
diff --git a/src/newslash_web/templates/common/captcha/recaptcha.html.tt2 b/src/newslash_web/templates/common/captcha/recaptcha.html.tt2
new file mode 100644 (file)
index 0000000..206bfd3
--- /dev/null
@@ -0,0 +1,8 @@
+[%- IF use_captcha && !user.is_login -%]
+<div class="g-recaptcha"
+     data-sitekey="6LcPlyIUAAAAAN2d4Gw4q2DWLtFCDYmn5tSVqS3w"
+     data-callback="recaptchaDone"
+     data-size="invisible">
+</div>
+[%- END -%]
+
index f431e09..e010631 100644 (file)
@@ -9,7 +9,7 @@
   <link rel="stylesheet" type="text/css" href="[% NS.static_content('css/bootstrap.css'); %]" />
   <link rel="stylesheet" type="text/css" media="screen, projection" href="[% NS.static_content('css/main.css'); %]" />
   <script src="/bootstrap/js/bootstrap.min.js" ></script>
-  
+
   [%- IF production -%]
   <script src="/vue/vue.min.js"></script>
   <script src="/vue/vue-resource.min.js"></script>
@@ -21,4 +21,7 @@
   <script src="/js/escape-html.js" ></script>
   <script src="[% NS.static_content('js/siteconfig.js'); %]" ></script>
 
+  [%- IF use_captcha && !user.is_login -%]
+  <script src="https://www.google.com/recaptcha/api.js"></script>
+  [%- END -%]
 </head>
index a123919..23ecdb9 100644 (file)
@@ -4,7 +4,8 @@
 <div class="main-column">
   <div class="submission main-contents">
     [%- INCLUDE common/article/article story=submission hide_more_link = 1 %]
-  </div><!-- .story -->
+    [%- INCLUDE common/captcha/recaptcha -%]
+ </div><!-- .story -->
 
   [%- INCLUDE common/comment/comments -%]
 </div>