├── .gitignore ├── COPYING ├── README.md ├── config └── config.exs ├── lib ├── display.eex └── exrecaptcha.ex ├── mix.exs ├── mix.lock └── test ├── exrecaptcha_test.exs └── test_helper.exs /.gitignore: -------------------------------------------------------------------------------- 1 | /_build 2 | /deps 3 | erl_crash.dump 4 | *.ez 5 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Exrecaptcha 2 | 3 | Simple [ReCaptcha] display/verify code for Elixir applications. 4 | Using Exrecaptcha with a CMS such as [Phoenix] is easy. 5 | 6 | [ReCaptcha]: http://www.google.com/recaptcha 7 | [Phoenix]: https://github.com/phoenixframework/phoenix 8 | 9 | ## Installation 10 | 11 | Set as a dep in your mix.exs and ensure it is running with your app: 12 | 13 | ```elixir 14 | def application do 15 | [ 16 | # ... 17 | applications: [:phoenix, :cowboy, :logger, :exrecaptcha] 18 | # ... 19 | ] 20 | end 21 | 22 | defp deps do 23 | [ 24 | {:phoenix, "0.5.0"}, 25 | {:cowboy, "~> 1.0.0"}, 26 | #... 27 | {:ibrowse, github: "cmullaparthi/ibrowse", tag: "v4.1.0"}, 28 | {:exrecaptcha, "~> 0.0.3"} 29 | ] 30 | end 31 | ``` 32 | 33 | And fetch your project's dependencies: 34 | 35 | ```bash 36 | $ mix deps.get 37 | ``` 38 | 39 | ## Config 40 | 41 | In your application's config.exs : 42 | 43 | ```elixir 44 | config :exrecaptcha, 45 | api_config: %{ verify_url: "http://www.google.com/recaptcha/api/verify", 46 | public_key: "YOUR_PUBLIC_KEY", 47 | private_key: "YOUR_PRIVATE_KEY" } 48 | ``` 49 | 50 | You can use https instead of http for the `verify_url`. 51 | 52 | ## Usage 53 | 54 | ### View 55 | 56 | Put this code somewhere in your html template: 57 | 58 | ```html 59 |
60 | ... 61 | <%= safe Exrecaptcha.display %> 62 | ... 63 |
64 | ``` 65 | 66 | ### Controller 67 | 68 | Provided you've set the routing properly, you just have to call 69 | 70 | ```elixir 71 | # your post method should route you here: 72 | def create(conn, params) do 73 | # do stuff, then check for the validity of the captcha 74 | :ok = verify_captcha(conn, params) 75 | end 76 | 77 | defp verify_captcha(conn, %{"recaptcha_challenge_field" => challenge, 78 | "recaptcha_response_field" => response}) do 79 | remote_ip = conn.remote_ip 80 | Exrecaptcha.verify(remote_ip, challenge, response) 81 | end 82 | ``` 83 | 84 | ##TODO 85 | 86 | - No option for recaptcha display can be set yet 87 | - Error handling is quite inexistent (throws RuntimeError) 88 | - No tests 89 | 90 | ## Changelog 91 | 92 | - 0.0.3: Update HTTPotion dependency, avoiding elixir version warnings 93 | - 0.0.2: Use HTTPS by default 94 | - 0.0.1: Initial release 95 | 96 | ## Licensing 97 | Copyright © 2014 [Adrien Anselme](https://github.com/adanselm) and [contributors](https://github.com/adanselm/exrecaptcha/graphs/contributors) 98 | This work is free. You can redistribute it and/or modify it under the 99 | terms of the Do What The Fuck You Want To Public License, Version 2, 100 | as published by Sam Hocevar. See the COPYING file for more details. 101 | -------------------------------------------------------------------------------- /config/config.exs: -------------------------------------------------------------------------------- 1 | # This file is responsible for configuring your application 2 | # and its dependencies with the aid of the Mix.Config module. 3 | use Mix.Config 4 | 5 | # This configuration is loaded before any dependency and is restricted 6 | # to this project. If another project depends on this project, this 7 | # file won't be loaded nor affect the parent project. For this reason, 8 | # if you want to provide default values for your application for third- 9 | # party users, it should be done in your mix.exs file. 10 | 11 | # Sample configuration: 12 | 13 | config :exrecaptcha, 14 | api_config: %{ verify_url: "http://www.google.com/recaptcha/api/verify", 15 | public_key: "YOUR_PUBLIC_KEY", 16 | private_key: "YOUR_PRIVATE_KEY" } 17 | 18 | # It is also possible to import configuration files, relative to this 19 | # directory. For example, you can emulate configuration per environment 20 | # by uncommenting the line below and defining dev.exs, test.exs and such. 21 | # Configuration from the imported file will override the ones defined 22 | # here (which is why it is important to import them last). 23 | # 24 | # import_config "#{Mix.env}.exs" 25 | -------------------------------------------------------------------------------- /lib/display.eex: -------------------------------------------------------------------------------- 1 | 4 | 13 | -------------------------------------------------------------------------------- /lib/exrecaptcha.ex: -------------------------------------------------------------------------------- 1 | defmodule Exrecaptcha do 2 | require Elixir.EEx 3 | 4 | # Define display function to be read in .eex file 5 | EEx.function_from_file :defp, :display, "lib/display.eex", [:public_key] 6 | 7 | def display do 8 | display conf.public_key 9 | end 10 | 11 | def verify(remote_ip, challenge, response) when is_tuple(remote_ip) do 12 | verify(:inet_parse.ntoa(remote_ip), challenge, response) 13 | end 14 | def verify(remote_ip, challenge, response) do 15 | query = URI.encode_query(%{"privatekey" => conf.private_key, 16 | "remoteip" => to_string(remote_ip), 17 | "challenge" => challenge, 18 | "response" => response}) 19 | IO.inspect query 20 | headers = ["Content-type": "application/x-www-form-urlencoded", 21 | "User-agent": "reCAPTCHA Elixir"] 22 | %{:body => body} = HTTPotion.post conf.verify_url, query, headers 23 | check_result String.split(body) 24 | end 25 | 26 | defp conf do 27 | Application.get_env(:exrecaptcha, :api_config) 28 | end 29 | 30 | defp check_result(["true", _reason]) do 31 | :ok 32 | end 33 | defp check_result(["false", reason]) do 34 | raise RuntimeError, message: reason 35 | end 36 | 37 | end 38 | -------------------------------------------------------------------------------- /mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Exrecaptcha.Mixfile do 2 | use Mix.Project 3 | 4 | def project do 5 | [app: :exrecaptcha, 6 | version: "0.0.3", 7 | elixir: "~> 1.0.0", 8 | description: description, 9 | deps: deps, 10 | package: package] 11 | end 12 | 13 | def application do 14 | [applications: [:logger, :httpotion]] 15 | end 16 | 17 | defp description do 18 | """ 19 | Simple ReCaptcha display/verify code for Elixir applications. 20 | Designed to be used with a CMS such as Phoenix. 21 | """ 22 | end 23 | 24 | defp deps do 25 | [ 26 | {:ibrowse, github: "cmullaparthi/ibrowse", tag: "v4.1.0"}, 27 | {:httpotion, "~> 1.0.0"} 28 | ] 29 | end 30 | 31 | defp package do 32 | [files: ["lib", "mix.exs", "README.md", "COPYING"], 33 | contributors: ["Adrien Anselme"], 34 | licenses: ["Do What the Fuck You Want to Public License, Version 2"], 35 | links: %{ "GitHub" => "https://github.com/adanselm/exrecaptcha" }] 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /mix.lock: -------------------------------------------------------------------------------- 1 | %{"httpotion": {:hex, :httpotion, "1.0.0"}, 2 | "ibrowse": {:git, "git://github.com/cmullaparthi/ibrowse.git", "7871e2ebe8811efb64e1917e2de455fa87e8dfe3", [tag: "v4.1.0"]}} 3 | -------------------------------------------------------------------------------- /test/exrecaptcha_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ExrecaptchaTest do 2 | use ExUnit.Case 3 | 4 | test "the truth" do 5 | assert 1 + 1 == 2 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | --------------------------------------------------------------------------------