diff --git a/README b/README deleted file mode 100644 index b397b14..0000000 --- a/README +++ /dev/null @@ -1 +0,0 @@ -TODO: Documentation diff --git a/README.md b/README.md new file mode 100644 index 0000000..d80a458 --- /dev/null +++ b/README.md @@ -0,0 +1,126 @@ +ReCaptcha for Rails - With AJAX Validation +========================================== + +Purpose +------- + +This plugin implements view helpers to generate ReCaptcha code, +to interface with the HTTP API for captcha verification, a DSL +to generate a `before_filter` and the necessary hacky code to +implement AJAX captcha validation. + +Implementation +-------------- + +For AJAX validation, a request to ReCaptcha HTTP server must be +made in order to verify the user input, but captchas can be +checked only once. + +The plugin thus, in case of a successful verification, uses +`Rails.cache` to cache the result and then the before filter +checks the cache without issuing a second request to the +ReCaptcha HTTP service. + +Installation +------------ + + script/plugin install git://github.com/Panmind/recaptcha.git + +Gems will follow soon, hopefully after the July 22nd Ruby Social Club in Milan. + +Usage +----- + +In your config/environment.rb: + + Panmind::Recaptcha.set( + :private_key => 'your private key', + :public_key => 'your public key + ) + +In your controller, say, the `UsersController` for a signup action: + + require_valid_captcha :only => :create + + private + def invalid_captcha + @user = User.new params[:user] + @user.errors.add_to_base('Captcha failed') + + render :new, :layout => 'login' + end + +The `invalid_captcha` method is called by the plugin when captcha +verification fails, and *must* be overwritten or a `NotImplementedError` +exception will be thrown. + +In your view: + + <%= recaptcha :label => 'Are you human?', :theme => 'clean' %> + +You can pass any `RecaptchaOptions` valid option, as stated by the +service documentation. The only nonstandard option `:label` is used +by the plugin to print a label before the captcha widget. + + +AJAX Validation +--------------- + +To cache the results of a successful captcha verification, a cache +key is needed: this is generated by a `proc` passed to the `:ajax` +option of the `require_valid_captcha` controller method. E.g.: + + require_valid_captcha :only => :create, :ajax => proc { params[:email] } + +This will use the user submitted e-mail as a cache key. When the +form is validated via AJAX, the eventual successful result will +be cached; when the form is submitted, the result will be fetched +from the cache and the signup will continue. + +On Panmind we use our `jquery.ajax-validation` plugin, that you +can download from http://github.com/Panmind/jquery-ajax-nav and +the Javascript code located in the `js/signup-sample.js` file. + +On the backend, an example checker that returns different HTTP +status code follows: + + def signup_checker + if params[:email].blank? + render :nothing => true, :status => :bad_request and return + end + + email = CGI.unescape(params[:email]) + + # more thorough checks on email should go here + + if User.exists?(['email = ?', email]) + render :nothing => true, :status => :not_acceptable and return + end + + unless valid_captcha? + invalid_captcha and return + end + + save_solved_captcha + render :nothing => true, :status => :ok + end + +Moreover, the client Javascript code should be informed via an +HTTP status when validation fails, thus the `invalid_captcha` +must contain a special `render` when the request comes from XHR: + + def invalid_captcha + render :nothing => true, :status => 412 and return true if request.xhr? + # Same invalid_captcha code as above + end + + +Bugs +---- + +The `:ajax` option is clumsy, and should not require the user to pass +a proc with semantics that are closely tied to the method that requires +captcha verification. + +Maybe the `authenticity_token` is a good fit for a validation cache key? +