jike_captcha 0.0.2.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +170 -0
- data/Rakefile +6 -0
- data/app/controllers/jike/captcha/get_captcha_controller.rb +10 -0
- data/config/routes.rb +3 -0
- data/example/ScreenShot.png +0 -0
- data/jike_captcha.gemspec +27 -0
- data/lib/jike_captcha.rb +27 -0
- data/lib/jike_captcha/engine.rb +17 -0
- data/lib/jike_captcha/helpers.rb +204 -0
- data/lib/jike_captcha/validation.rb +55 -0
- data/lib/jike_captcha/version.rb +5 -0
- data/spec/helpers_spec.rb +98 -0
- data/spec/jike_captcha_spec.rb +14 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/validation_spec.rb +19 -0
- metadata +152 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9705fad0edd583fc5535d5ad82f53ee6069a1463
|
4
|
+
data.tar.gz: 2d7a401e51fb5910bd9ebb203ea98738bbb7ca89
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 59709b2b11a2d627008cbc8a5e54a8eabac825b06d93d53309f3918207def2c8adba8551129a4d2acae1ee817d23015fe4a170a47522ff21e01053cc5caacfc4
|
7
|
+
data.tar.gz: 33edcccf1f2ecc97d5fe797c4959b29efbb4e9e57693b9f05d915ce8e07f2789e34b8202388827f4d211b89af2ac768539f26bb40f48f8d03629c7d964eb49fa
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Xuhao
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
# JikeCaptcha
|
2
|
+
|
3
|
+
[](https://travis-ci.org/Xuhao/jike_captcha)
|
4
|
+
[](https://codeclimate.com/github/Xuhao/jike_captcha)
|
5
|
+
[](https://coveralls.io/r/Xuhao/jike_captcha?branch=master)
|
6
|
+
[](http://badge.fury.io/rb/jike_captcha)
|
7
|
+
|
8
|
+
Captcha form [Jike API][jike_api_site], It's very simple but it's light weight and very fast. No need generate captcha image locally, so you need not install any software for it, such as ImageMagick. It get captcha form a fast and stable service clusters. It's good choice for Captcha, try it!
|
9
|
+
|
10
|
+

|
11
|
+
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
gem 'jike_captcha'
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
$ gem install jike_captcha
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
#### 1. Get your app_key
|
30
|
+
|
31
|
+
Before use it, you need get you app_key form [Jike API site](http://open.jike.com/).
|
32
|
+
|
33
|
+
Once get your app_key, you need tell JikeCaptcha what kind of app_key you got, there are two ways:
|
34
|
+
|
35
|
+
One: create a file in config/initializers/jike_captcha.rb with below code:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
# config/initializers/jike_captcha.rb
|
39
|
+
Jike::Captcha.app_key = "<your_app_key>"
|
40
|
+
```
|
41
|
+
|
42
|
+
Two: set app_key in config/application.rb:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
config.jike_app_key = '<your_app_key>'
|
46
|
+
```
|
47
|
+
|
48
|
+
#### 2. Put captcha tag in your form
|
49
|
+
|
50
|
+
```erb
|
51
|
+
<%= form_for :post do |f| %>
|
52
|
+
<%= captcha_tag %>
|
53
|
+
<%= f.submit %>
|
54
|
+
<% end %>
|
55
|
+
```
|
56
|
+
|
57
|
+
##### captcha_tag
|
58
|
+
|
59
|
+
The most useful helper is `captcha_tag`, it will render all the necessary tags.
|
60
|
+
|
61
|
+
*args:*
|
62
|
+
|
63
|
+
* `:wrapper_html`: options for wrapper tag
|
64
|
+
* `:tag`: control wrapper tag type
|
65
|
+
* `:input_html`: options for captcha text filed tag
|
66
|
+
* `:image_html`: options for captcha img tag
|
67
|
+
* `:src_type`: control image url type. if set to `:data_url`, will render img src as base64 encode
|
68
|
+
* `:update`: if set to true, captcha can be update be ajax, if set to a hash, value for `:text` key in that has will used for update link content.
|
69
|
+
|
70
|
+
All the options at below are default value, except `args[:image_html][:src_type]`, its default value is nil.
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
captcha_tag wrapper_html: {
|
74
|
+
tag: :div,
|
75
|
+
id: 'jike_captcha_wrapper',
|
76
|
+
class: 'jike_captcha_wrapper'
|
77
|
+
},
|
78
|
+
input_html: {
|
79
|
+
id: 'jike_captcha_input',
|
80
|
+
class: 'jike_captcha_input',
|
81
|
+
name: 'jike_captcha_value'
|
82
|
+
},
|
83
|
+
image_html: {
|
84
|
+
src_type: :data_url,
|
85
|
+
update: { text: 'change a new one' },
|
86
|
+
id: 'jike_captcha_image',
|
87
|
+
class: 'jike_captcha_image'
|
88
|
+
}
|
89
|
+
```
|
90
|
+
|
91
|
+
render:
|
92
|
+
|
93
|
+
```html
|
94
|
+
<div class="jike_captcha_wrapper" id="jike_captcha_wrapper">
|
95
|
+
<input class="jike_captcha_input" id="jike_captcha_input" name="jike_captcha_value" type="text" />
|
96
|
+
<img class="jike_captcha_image" data-src-type="data_url" id="jike_captcha_image" src="data:image/png;base64,iVBO......" style="cursor: pointer;" />
|
97
|
+
<input class="jike_captcha_id" id="jike_captcha_id" name="jike_captcha_id" type="hidden" value="..." />
|
98
|
+
<a href="javascript: void(0);" id="jike_captcha_update_link">change a new one</a>
|
99
|
+
<script type="text/javascript">
|
100
|
+
//<![CDATA[
|
101
|
+
$(function(){
|
102
|
+
$('body').on('click', 'img#jike_captcha_image, a#jike_captcha_update_link', function(event) {
|
103
|
+
var imageType, $captchaInput, $captchaImage, $captchaId;
|
104
|
+
$captchaInput = $('input#jike_captcha_input');
|
105
|
+
$captchaImage = $('img#jike_captcha_image');
|
106
|
+
$captchaId = $('input#jike_captcha_id');
|
107
|
+
imageType = $captchaImage.data('src-type');
|
108
|
+
$.getJSON('/jike_captcha/get_captcha.json', {image_type: imageType}, function(data) {
|
109
|
+
$captchaInput.val('');
|
110
|
+
$captchaImage.attr('src', decodeURIComponent(data.captcha_image));
|
111
|
+
$captchaId.val(data.captcha_id);
|
112
|
+
});
|
113
|
+
});
|
114
|
+
});
|
115
|
+
//]]>
|
116
|
+
</script>
|
117
|
+
</div>
|
118
|
+
```
|
119
|
+
|
120
|
+
#### 3. Validate captcha in controller
|
121
|
+
|
122
|
+
Submit captcha value form your form, then you can validate it in your controller use `captcha_valid?` method. It's very simple to do that.
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
class UsersController < ApplicationController
|
126
|
+
def create
|
127
|
+
if captcha_valid? # Same as Jike::Captcha::Validation.captcha_valid?(params)
|
128
|
+
User.create(params[:user])
|
129
|
+
else
|
130
|
+
redirect_to :new, notice: 'Captcha is not correct!'
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
```
|
135
|
+
|
136
|
+
As default, captcha value should submited by `params[:jike_captcha_value]`, another value is `params[:jike_captcha_id]`, it's generate by `captcha_tag` helper automatically.
|
137
|
+
|
138
|
+
<b>Custom captcha value param in your form</b>
|
139
|
+
|
140
|
+
You can use any param key to submit captcha value, as below:
|
141
|
+
|
142
|
+
```erb
|
143
|
+
<%= captcha_tag input_html: { name: 'my_captcha_value' } %>
|
144
|
+
```
|
145
|
+
|
146
|
+
The captcha value will submited by `params[:my_captcha_value]`. But you can't custom another value `params[:jike_captcha_id]`.
|
147
|
+
|
148
|
+
then validate in your controller like this:
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
class UsersController < ApplicationController
|
152
|
+
def create
|
153
|
+
if captcha_validate(params[:my_captcha_value])
|
154
|
+
User.create(params[:user])
|
155
|
+
else
|
156
|
+
redirect_to :new, notice: 'Captcha is not correct!'
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
```
|
161
|
+
|
162
|
+
## Contributing
|
163
|
+
|
164
|
+
1. Fork it
|
165
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
166
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
167
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
168
|
+
5. Create new Pull Request
|
169
|
+
|
170
|
+
[jike_api_site]: http://open.jike.com/api/detailView?group_id=1
|
data/Rakefile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
module Jike::Captcha
|
2
|
+
class GetCaptchaController < ::ActionController::Metal
|
3
|
+
|
4
|
+
def index
|
5
|
+
Jike::Captcha::Helpers.reset_captcha!
|
6
|
+
image = (params[:image_type] == 'data_url' ? Jike::Captcha::Helpers.captcha_image_data_url : Jike::Captcha::Helpers.captcha_image_url)
|
7
|
+
self.response_body = {captcha_image: image, captcha_id: Jike::Captcha::Helpers.captcha_id}.to_json
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/config/routes.rb
ADDED
Binary file
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'jike_captcha/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "jike_captcha"
|
8
|
+
spec.version = Jike::Captcha::VERSION
|
9
|
+
spec.authors = ["Xuhao"]
|
10
|
+
spec.email = ["xuhao@rubyfans.com"]
|
11
|
+
spec.description = %q{Captcha form Jike API}
|
12
|
+
spec.summary = %q{Captcha form Jike API}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'httparty'
|
22
|
+
spec.add_dependency 'activesupport'
|
23
|
+
spec.add_dependency 'actionpack'
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
end
|
data/lib/jike_captcha.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "jike_captcha/version"
|
2
|
+
require 'jike_captcha/engine' if Module.const_defined?('Rails')
|
3
|
+
|
4
|
+
module Jike
|
5
|
+
module Captcha
|
6
|
+
CAPTCHA_ID_URL = 'http://api.jike.com/captcha/urls'
|
7
|
+
CAPTCHA_IMAGE_URL = 'http://api.jike.com/captcha/images'
|
8
|
+
CAPTCHA_VALIDATE_URL = 'http://api.jike.com/captcha/validation'
|
9
|
+
|
10
|
+
# There two way to set jike app key
|
11
|
+
# TODO: detail for those tow ways
|
12
|
+
def self.app_key
|
13
|
+
@app_key ||= begin
|
14
|
+
if Module.const_defined?('Rails')
|
15
|
+
Rails.application.config.jike_app_key if Rails.application.config.respond_to?(:jike_app_key)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.app_key=(app_key_string)
|
21
|
+
@app_key = app_key_string
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'jike_captcha/helpers'
|
27
|
+
require 'jike_captcha/validation'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rails"
|
2
|
+
|
3
|
+
module Jike
|
4
|
+
module Captcha
|
5
|
+
class Engine < Rails::Engine
|
6
|
+
initializer "Actionpack extensions" do
|
7
|
+
ActiveSupport.on_load :action_view do
|
8
|
+
ActionView::Base.send :include, Jike::Captcha::Helpers
|
9
|
+
end
|
10
|
+
|
11
|
+
ActiveSupport.on_load :action_controller do
|
12
|
+
ActionController::Metal.send :include, Jike::Captcha::Validation
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'active_support/json/decoding'
|
3
|
+
require 'active_support/core_ext/object/to_param'
|
4
|
+
require 'active_support/core_ext/object/to_query'
|
5
|
+
require 'active_support/concern'
|
6
|
+
require 'active_support/core_ext/hash/keys'
|
7
|
+
require 'active_support/core_ext/hash/deep_merge'
|
8
|
+
require 'active_support/core_ext/string/output_safety'
|
9
|
+
require 'active_support/core_ext/object/blank'
|
10
|
+
require 'action_view'
|
11
|
+
|
12
|
+
module Jike
|
13
|
+
module Captcha
|
14
|
+
module Helpers
|
15
|
+
class AppKeyMissingError < StandardError
|
16
|
+
def initialize
|
17
|
+
super 'Please set Jike app_key first! Check out jike_captcha document to see how to do that.'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
# ActionView helpers and helper methods that can be called on Jike::Captcha::Helpers
|
21
|
+
#
|
22
|
+
# Example:
|
23
|
+
# Jike::Captcha::Helpers.captcha_image_url
|
24
|
+
# # => http://api.jike.com/captcha/images?app_key=<app_key>&captcha_id=<captcha_id>
|
25
|
+
#
|
26
|
+
# <%= captcha_image_tag src_type: :data_url, id: :my_captcha_image %>
|
27
|
+
# # => <img url="data_url" src="data:image/png;base64,iVBORw0..." id="my_captcha_image" class="jike_captcha_image">
|
28
|
+
#
|
29
|
+
# <%= captcha_tag wrapper_html: {tag: :span, class: :captcha_field}, input_html: {class: :my_captcha_input}, image_html: {src_type: :data_url, id: :my_captcha_image} %>
|
30
|
+
# # =>
|
31
|
+
# # <span id="jike_captcha_wrapper" class="captcha_field">
|
32
|
+
# # <input id="jike_captcha_input" class="my_captcha_input" type="text" name="jike_captcha_value">
|
33
|
+
# # <img id="my_captcha_image" class="jike_captcha_image" src="data:image/png;base64,iVBORw0KG....">
|
34
|
+
# # <input id="jike_captcha_id" class="jike_captcha_id" type="hidden" value="b7c02131e7..." name="jike_captcha_id">
|
35
|
+
# # </span>
|
36
|
+
include HTTParty, ActionView::Helpers::TagHelper, ActionView::Helpers::TextHelper, ActionView::Context
|
37
|
+
extend self
|
38
|
+
|
39
|
+
DEFAULT_WRAPPER_OPTIONS = { id: 'jike_captcha_wrapper', class: 'jike_captcha_wrapper' }
|
40
|
+
DEFAULT_IMAGE_OPTIONS = { id: 'jike_captcha_image', class: 'jike_captcha_image' }
|
41
|
+
DEFAULT_ID_OPTIONS = { id: 'jike_captcha_id', class: 'jike_captcha_id', name: 'jike_captcha_id' }
|
42
|
+
DEFAULT_INPUT_OPTIONS = { id: 'jike_captcha_input', class: 'jike_captcha_input', name: 'jike_captcha_value' }
|
43
|
+
DEFAULT_AJAX_LINK_OPTIONS = { id: 'jike_captcha_update_link', href: 'javascript: void(0);' }
|
44
|
+
AJAX_LINK_TEXT = 'change another one'
|
45
|
+
|
46
|
+
attr_accessor :captcha_image_url, :captcha_image_data, :captcha_image_data_url, :captcha_id, :captcha_image_base64
|
47
|
+
|
48
|
+
# Return captcha image url that redirect to jike server
|
49
|
+
#
|
50
|
+
# Example:
|
51
|
+
# Jike::Captcha::Helpers.captcha_image_url
|
52
|
+
# # => http://api.jike.com/captcha/images?app_key=<app_key>&captcha_id=<captcha_id>
|
53
|
+
def captcha_image_url
|
54
|
+
@captcha_image_url ||= api_url_for(CAPTCHA_IMAGE_URL, captcha_id: captcha_id)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Return captcha image binary data, useful for some apps except Web application
|
58
|
+
#
|
59
|
+
# Example:
|
60
|
+
# Jike::Captcha::Helpers.captcha_image_data
|
61
|
+
# # => "\x89PNG\r\n\x1A\n\x00\x00\......"
|
62
|
+
def captcha_image_data
|
63
|
+
@captcha_image_data ||= get(captcha_image_url)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Return data url for <code><img><code> tag
|
67
|
+
#
|
68
|
+
# Example:
|
69
|
+
# Jike::Captcha::Helpers.captcha_image_data_url
|
70
|
+
# # => "data:image/png;base64,iVBORw0KGgoAAA......""
|
71
|
+
def captcha_image_data_url
|
72
|
+
@captcha_image_data_url ||= "data:image/png;base64,#{captcha_image_base64}"
|
73
|
+
end
|
74
|
+
|
75
|
+
# Render captcha image and captcha_id hidden field
|
76
|
+
#
|
77
|
+
# Example:
|
78
|
+
# <%= captcha_image_tag src_type: :data_url, id: :my_captcha_image %>
|
79
|
+
# # => <img url="data_url" src="data:image/png;base64,iVBORw0..." id="my_captcha_image" class="jike_captcha_image">
|
80
|
+
def captcha_image_tag(options={})
|
81
|
+
image_options = get_image_options(options)
|
82
|
+
update_options_or_boolean = image_options.delete(:update)
|
83
|
+
set_pointer_cursor(image_options) if update_options_or_boolean.present?
|
84
|
+
output = ActiveSupport::SafeBuffer.new
|
85
|
+
output << tag(:img, image_options)
|
86
|
+
output << tag(:input, { type: :hidden, value: captcha_id }.update(DEFAULT_ID_OPTIONS))
|
87
|
+
if update_options_or_boolean.present?
|
88
|
+
output << ajax_link_tag(update_options_or_boolean)
|
89
|
+
output << js_for_ajax
|
90
|
+
end
|
91
|
+
output
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def captcha_id # :nodoc:
|
96
|
+
@captcha_id ||= get_hash(captcha_id_url)['data']['captcha_id']
|
97
|
+
end
|
98
|
+
|
99
|
+
# Render captcha input text field, captcha image and captcha_id hidden field
|
100
|
+
#
|
101
|
+
# Example:
|
102
|
+
# <%= captcha_tag wrapper_html: {tag: :span, class: :captcha_field}, input_html: {class: :my_captcha_input}, image_html: {src_type: :data_url, id: :my_captcha_image} %>
|
103
|
+
# # =>
|
104
|
+
# # <span id="jike_captcha_wrapper" class="captcha_field">
|
105
|
+
# # <input id="jike_captcha_input" class="my_captcha_input" type="text" name="jike_captcha_value">
|
106
|
+
# # <img id="my_captcha_image" class="jike_captcha_image" src="data:image/png;base64,iVBORw0KG....">
|
107
|
+
# # <input id="jike_captcha_id" class="jike_captcha_id" type="hidden" value="b7c02131e7..." name="jike_captcha_id">
|
108
|
+
# # </span>
|
109
|
+
def captcha_tag(options = {})
|
110
|
+
options.symbolize_keys!
|
111
|
+
input_options = get_input_options(options)
|
112
|
+
wrapper_options = get_wrapper_options(options)
|
113
|
+
|
114
|
+
wrapper_tag = wrapper_options.delete(:tag) || :div
|
115
|
+
content_tag wrapper_tag, wrapper_options do
|
116
|
+
concat tag :input, { type: "text" }.update(input_options)
|
117
|
+
concat captcha_image_tag(options.delete(:image_html) || {})
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def reset_captcha!
|
122
|
+
@captcha_image_url = nil
|
123
|
+
@captcha_image_data = nil
|
124
|
+
@captcha_image_data_url = nil
|
125
|
+
@captcha_id = nil
|
126
|
+
@captcha_image_base64 = nil
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def captcha_image_base64
|
132
|
+
@captcha_image_base64 ||= Base64.encode64(captcha_image_data)
|
133
|
+
end
|
134
|
+
|
135
|
+
def captcha_id_url
|
136
|
+
api_url_for(CAPTCHA_ID_URL)
|
137
|
+
end
|
138
|
+
|
139
|
+
def api_url_for(base_url, params={})
|
140
|
+
params.merge!(app_key: Jike::Captcha.app_key)
|
141
|
+
"#{base_url}?#{params.to_param}"
|
142
|
+
end
|
143
|
+
|
144
|
+
def get(url)
|
145
|
+
raise AppKeyMissingError if Jike::Captcha.app_key.blank?
|
146
|
+
HTTParty.get(url).body
|
147
|
+
end
|
148
|
+
|
149
|
+
def get_hash(url)
|
150
|
+
::ActiveSupport::JSON.decode(get(url))
|
151
|
+
end
|
152
|
+
|
153
|
+
def get_wrapper_options(options)
|
154
|
+
DEFAULT_WRAPPER_OPTIONS.merge(options.delete(:wrapper_html) || {})
|
155
|
+
end
|
156
|
+
|
157
|
+
def get_image_options(options)
|
158
|
+
image_src = options[:src_type].to_s == 'data_url' ? captcha_image_data_url : captcha_image_url
|
159
|
+
DEFAULT_IMAGE_OPTIONS.merge(src: image_src, data: { src_type: options.delete(:src_type) }).deep_merge(options)
|
160
|
+
end
|
161
|
+
|
162
|
+
def get_input_options(options)
|
163
|
+
DEFAULT_INPUT_OPTIONS.merge(options.delete(:input_html) || {})
|
164
|
+
end
|
165
|
+
|
166
|
+
def set_pointer_cursor(options)
|
167
|
+
options[:style] = "cursor: pointer;#{options[:style]}"
|
168
|
+
end
|
169
|
+
|
170
|
+
def ajax_link_tag(options_or_boolean)
|
171
|
+
if Hash === options_or_boolean
|
172
|
+
return '' if options_or_boolean.key?(:text) and options_or_boolean[:text].is_a?(FalseClass)
|
173
|
+
content_tag :a, options_or_boolean.delete(:text), options_or_boolean.merge( DEFAULT_AJAX_LINK_OPTIONS )
|
174
|
+
else
|
175
|
+
content_tag :a, AJAX_LINK_TEXT, DEFAULT_AJAX_LINK_OPTIONS
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def js_for_ajax
|
180
|
+
js = <<-JAVASCRIPT
|
181
|
+
<script type="text/javascript">
|
182
|
+
//<![CDATA[
|
183
|
+
$(function(){
|
184
|
+
$('body').on('click', 'img#jike_captcha_image, a#jike_captcha_update_link', function(event) {
|
185
|
+
var imageType, $captchaInput, $captchaImage, $captchaId;
|
186
|
+
$captchaInput = $('input#jike_captcha_input');
|
187
|
+
$captchaImage = $('img#jike_captcha_image');
|
188
|
+
$captchaId = $('input#jike_captcha_id');
|
189
|
+
imageType = $captchaImage.data('src-type');
|
190
|
+
$.getJSON('/jike_captcha/get_captcha.json', {image_type: imageType}, function(data) {
|
191
|
+
$captchaInput.val('');
|
192
|
+
$captchaImage.attr('src', decodeURIComponent(data.captcha_image));
|
193
|
+
$captchaId.val(data.captcha_id);
|
194
|
+
});
|
195
|
+
});
|
196
|
+
});
|
197
|
+
//]]>
|
198
|
+
</script>
|
199
|
+
JAVASCRIPT
|
200
|
+
js.html_safe
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'active_support/core_ext/object/blank'
|
2
|
+
require 'active_support/concern'
|
3
|
+
|
4
|
+
module Jike
|
5
|
+
module Captcha
|
6
|
+
module Validation
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
extend self
|
9
|
+
|
10
|
+
# Validate the request params
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
# class UsersController < ApplicationController
|
14
|
+
# def create
|
15
|
+
# if captcha_valid? # Same as Jike::Captcha::Validation.captcha_valid?(params)
|
16
|
+
# User.create(params[:user])
|
17
|
+
# else
|
18
|
+
# redirect_to :new, notice: 'Captcha is not correct!'
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
def captcha_valid?(_params={})
|
23
|
+
request_params = self.respond_to?(:params) ? (_params.presence || params) : _params
|
24
|
+
captcha_validate(request_params[:jike_captcha_value], request_params[:jike_captcha_id])
|
25
|
+
end
|
26
|
+
|
27
|
+
# Validate the input value by a captcha_id
|
28
|
+
# It's usefull to custom the captcha_tag to pass the captcha value with different param
|
29
|
+
#
|
30
|
+
# Example:
|
31
|
+
# class UsersController < ApplicationController
|
32
|
+
# def create
|
33
|
+
# if captcha_validate(params[:captcha_value])
|
34
|
+
# User.create(params[:user])
|
35
|
+
# else
|
36
|
+
# redirect_to :new, notice: 'Captcha is not correct!'
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
def captcha_validate(input_value, captcha_id=nil)
|
41
|
+
captcha_id ||= self.respond_to?(:params) && params[:jike_captcha_id]
|
42
|
+
return false if input_value.blank? or captcha_id.blank?
|
43
|
+
response = Jike::Captcha::Helpers.send(:get_hash, validate_url(input_value, captcha_id))
|
44
|
+
!!response['data']
|
45
|
+
rescue
|
46
|
+
false
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def validate_url(input_value, captcha_id)
|
51
|
+
Jike::Captcha::Helpers.send(:api_url_for, CAPTCHA_VALIDATE_URL, captcha_id: captcha_id, input: input_value)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Jike::Captcha::Helpers do
|
4
|
+
before(:each) { Jike::Captcha.app_key = 'ba02964ba79438ec' }
|
5
|
+
it 'should return captcha image url that redirect to jike server when call captcha_url method' do
|
6
|
+
image_url = Jike::Captcha::Helpers.captcha_image_url
|
7
|
+
image_url.should be_a(String)
|
8
|
+
image_url.include?(Jike::Captcha::CAPTCHA_IMAGE_URL).should be_true
|
9
|
+
image_url.include?("captcha_id=").should be_true
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should return a captcha id when call captcha_id method' do
|
13
|
+
captcha_id = Jike::Captcha::Helpers.captcha_id
|
14
|
+
captcha_id.should be_a(String)
|
15
|
+
captcha_id.size.should eq(32)
|
16
|
+
captcha_id.include?("captcha_id=").should be_false
|
17
|
+
Jike::Captcha.app_key = nil
|
18
|
+
Jike::Captcha::Helpers.reset_captcha!
|
19
|
+
expect { Jike::Captcha::Helpers.captcha_id }.to raise_error(Jike::Captcha::Helpers::AppKeyMissingError, "Please set Jike app_key first! Check out jike_captcha document to see how to do that.")
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should return binary data for captcha image when all captcha_image_data' do
|
23
|
+
image_data = Jike::Captcha::Helpers.captcha_image_data
|
24
|
+
image_data.encoding.name.should eq('ASCII-8BIT')
|
25
|
+
Jike::Captcha.app_key = nil
|
26
|
+
Jike::Captcha::Helpers.reset_captcha!
|
27
|
+
expect { Jike::Captcha::Helpers.captcha_image_data }.to raise_error(Jike::Captcha::Helpers::AppKeyMissingError, "Please set Jike app_key first! Check out jike_captcha document to see how to do that.")
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should return data url for captcha image when call captcha_image_data_url' do
|
31
|
+
Jike::Captcha::Helpers.captcha_image_data_url.should =~ /\Adata:image\/png;base64,+/
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should render captcha image and hidden input to value current captcha id when call captcha_image_tag' do
|
35
|
+
image_tag = Jike::Captcha::Helpers.captcha_image_tag(name: 'my_captcha_image')
|
36
|
+
image_tag.should =~ /\A<img+/
|
37
|
+
image_tag.should =~ /<input+/
|
38
|
+
image_tag.include?('class="jike_captcha_image"').should be_true
|
39
|
+
image_tag.include?('id="jike_captcha_image"').should be_true
|
40
|
+
image_tag.include?('class="jike_captcha_id"').should be_true
|
41
|
+
image_tag.include?('id="jike_captcha_id"').should be_true
|
42
|
+
image_tag.include?('name="my_captcha_image"').should be_true
|
43
|
+
Jike::Captcha::Helpers.captcha_image_tag(id: 'my_captcha_image').include?('id="my_captcha_image"').should be_true
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should render captcha input and captcha image when call captcha_tag method' do
|
47
|
+
captcha_tag = Jike::Captcha::Helpers.captcha_tag(wrapper_html: {tag: :div})
|
48
|
+
captcha_tag1 = Jike::Captcha::Helpers.captcha_tag(
|
49
|
+
wrapper_html: {tag: :span, class: 'my_captcha_wrapper'},
|
50
|
+
input_html: {id: 'my_captcha_input'},
|
51
|
+
image_html: {name: 'my_captcha_image', class: 'test_class'}
|
52
|
+
)
|
53
|
+
captcha_tag2 = Jike::Captcha::Helpers.captcha_tag(image_html: {update: { text: 'UPDATE IT', id: 'my_update_link_id'}})
|
54
|
+
captcha_tag3 = Jike::Captcha::Helpers.captcha_tag(image_html: {update: true})
|
55
|
+
captcha_tag.include?('class="jike_captcha_wrapper"').should be_true
|
56
|
+
captcha_tag.include?('id="jike_captcha_wrapper"').should be_true
|
57
|
+
captcha_tag.should =~ /\A<div+/
|
58
|
+
captcha_tag.should =~ /<img+/
|
59
|
+
captcha_tag.should =~ /<input+/
|
60
|
+
captcha_tag.include?('class="jike_captcha_image"').should be_true
|
61
|
+
captcha_tag.include?('id="jike_captcha_image"').should be_true
|
62
|
+
captcha_tag.include?('class="jike_captcha_id"').should be_true
|
63
|
+
captcha_tag.include?('id="jike_captcha_id"').should be_true
|
64
|
+
captcha_tag.include?('<script type="text/javascript">').should be_false
|
65
|
+
|
66
|
+
captcha_tag1.should =~ /\A<span+/
|
67
|
+
captcha_tag1.include?('class="test_class"').should be_true
|
68
|
+
captcha_tag1.include?('name="my_captcha_image"').should be_true
|
69
|
+
captcha_tag1.include?('class="my_captcha_wrapper"').should be_true
|
70
|
+
captcha_tag1.include?('id="my_captcha_input"').should be_true
|
71
|
+
captcha_tag1.include?('<script type="text/javascript">').should be_false
|
72
|
+
|
73
|
+
captcha_tag2.include?('style="cursor: pointer;"').should be_true
|
74
|
+
captcha_tag2.include?('<a href="javascript: void(0);" id="jike_captcha_update_link">UPDATE IT</a>').should be_true
|
75
|
+
captcha_tag2.include?('<script type="text/javascript">').should be_true
|
76
|
+
captcha_tag2.include?('id="jike_captcha_update_link">').should be_true
|
77
|
+
|
78
|
+
captcha_tag3.include?('style="cursor: pointer;"').should be_true
|
79
|
+
captcha_tag3.include?('<a href="javascript: void(0);" id="jike_captcha_update_link">change another one</a>').should be_true
|
80
|
+
captcha_tag3.include?('<script type="text/javascript">').should be_true
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should clean all cacha and reset all instance variables when call reset_captcha! method' do
|
84
|
+
helper = Jike::Captcha::Helpers
|
85
|
+
helper.captcha_id = 'captcha_id.sample'
|
86
|
+
helper.captcha_image_url = 'captcha_image_url.sample'
|
87
|
+
helper.captcha_image_data = 'captcha_image_data.sample'
|
88
|
+
helper.captcha_image_data_url = 'captcha_image_data_url.sample'
|
89
|
+
helper.captcha_image_base64 = 'captcha_image_base64.sample'
|
90
|
+
|
91
|
+
helper.reset_captcha!
|
92
|
+
helper.captcha_id.should_not eq('captcha_id.sample')
|
93
|
+
helper.captcha_image_url.should_not eq('captcha_image_url.sample')
|
94
|
+
helper.captcha_image_data.should_not eq('captcha_image_data.sample')
|
95
|
+
helper.captcha_image_data_url.should_not eq('captcha_image_data_url.sample')
|
96
|
+
helper.send(:captcha_image_base64).should_not eq('captcha_image_base64.sample')
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Jike::Captcha do
|
4
|
+
it 'should have a version number' do
|
5
|
+
Jike::Captcha::VERSION.should_not be_nil
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should return app_key which defined in rails application configuration file.' do
|
9
|
+
Jike::Captcha.app_key = nil
|
10
|
+
stub_const('Rails', Module.new)
|
11
|
+
Rails.stub_chain('application.config.jike_app_key') { 'jike_app_key_test_sample' }
|
12
|
+
Jike::Captcha.app_key.should eq('jike_app_key_test_sample')
|
13
|
+
end
|
14
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Jike::Captcha::Validation do
|
4
|
+
let(:params1) { { jike_captcha_value: 'captcha_value', jike_captcha_id: 'captcha_id' }}
|
5
|
+
let(:params2) { { jike_captcha_value: '', jike_captcha_id: nil }}
|
6
|
+
let(:params3) { { captcha_id: 'captcha_id' }}
|
7
|
+
|
8
|
+
it 'should validate captcha value in params when call captcha_valid?' do
|
9
|
+
Jike::Captcha::Validation.captcha_valid?(params1).should be_false
|
10
|
+
Jike::Captcha::Validation.captcha_valid?(params2).should be_false
|
11
|
+
Jike::Captcha::Validation.captcha_valid?(params3).should be_false
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should check the given captcha value and id and return boolean' do
|
15
|
+
Jike::Captcha::Validation.captcha_validate(params1[:jike_captcha_value], params1[:jike_captcha_id]).class.should satisfy{|k| [TrueClass, FalseClass].include?(k)}
|
16
|
+
Jike::Captcha::Helpers.stub(:send).and_raise
|
17
|
+
Jike::Captcha::Validation.captcha_validate(params1[:jike_captcha_value], params1[:jike_captcha_id]).should be_false
|
18
|
+
end
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jike_captcha
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2.beta
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Xuhao
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-08-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httparty
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: actionpack
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.3'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.3'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Captcha form Jike API
|
98
|
+
email:
|
99
|
+
- xuhao@rubyfans.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- .gitignore
|
105
|
+
- .rspec
|
106
|
+
- .travis.yml
|
107
|
+
- Gemfile
|
108
|
+
- LICENSE.txt
|
109
|
+
- README.md
|
110
|
+
- Rakefile
|
111
|
+
- app/controllers/jike/captcha/get_captcha_controller.rb
|
112
|
+
- config/routes.rb
|
113
|
+
- example/ScreenShot.png
|
114
|
+
- jike_captcha.gemspec
|
115
|
+
- lib/jike_captcha.rb
|
116
|
+
- lib/jike_captcha/engine.rb
|
117
|
+
- lib/jike_captcha/helpers.rb
|
118
|
+
- lib/jike_captcha/validation.rb
|
119
|
+
- lib/jike_captcha/version.rb
|
120
|
+
- spec/helpers_spec.rb
|
121
|
+
- spec/jike_captcha_spec.rb
|
122
|
+
- spec/spec_helper.rb
|
123
|
+
- spec/validation_spec.rb
|
124
|
+
homepage: ''
|
125
|
+
licenses:
|
126
|
+
- MIT
|
127
|
+
metadata: {}
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - '>'
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: 1.3.1
|
142
|
+
requirements: []
|
143
|
+
rubyforge_project:
|
144
|
+
rubygems_version: 2.0.5
|
145
|
+
signing_key:
|
146
|
+
specification_version: 4
|
147
|
+
summary: Captcha form Jike API
|
148
|
+
test_files:
|
149
|
+
- spec/helpers_spec.rb
|
150
|
+
- spec/jike_captcha_spec.rb
|
151
|
+
- spec/spec_helper.rb
|
152
|
+
- spec/validation_spec.rb
|