diff --git a/Changelog.md b/Changelog.md index 82389339f..38880d20a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -76,6 +76,7 @@ For more details see https://wiki.diasporafoundation.org/Updating * Add actions on aspects on the contact page [#4570](https://github.com/diaspora/diaspora/pull/4570) * Added a statistics route with general pod information, and if enabled in pod settings, total user, half year/monthly active users and local post counts [#4602](https://github.com/diaspora/diaspora/pull/4602) * Add indication about markdown formatting in the publisher [#4589](https://github.com/diaspora/diaspora/pull/4589) +* Add captcha to signup form [#4659](https://github.com/diaspora/diaspora/pull/4659) ## Gem updates * selenium-webdriver 2.34.0 -> 2.39.0 diff --git a/Gemfile b/Gemfile index 892b7ca8b..9fc5f8e0c 100644 --- a/Gemfile +++ b/Gemfile @@ -15,6 +15,10 @@ gem 'json', '1.8.0' gem 'devise', '3.0.2' +# Captcha + +gem 'galetahub-simple_captcha', '0.1.5', :require => 'simple_captcha' + # Background processing gem 'sidekiq', '2.17.0' diff --git a/Gemfile.lock b/Gemfile.lock index d7e348189..7e269fbed 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -141,6 +141,7 @@ GEM rspec (~> 2.0) rspec-instafail (~> 0.2.0) ruby-progressbar (~> 1.0) + galetahub-simple_captcha (0.1.5) gherkin (2.12.0) multi_json (~> 1.3) gon (4.1.1) @@ -448,6 +449,7 @@ DEPENDENCIES foreigner (= 1.4.2) foreman (= 0.62) fuubar (= 1.1.1) + galetahub-simple_captcha (= 0.1.5) gon (= 4.1.1) guard-cucumber (= 1.4.0) guard-rspec (= 3.0.2) diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 57483d287..b00382438 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -12,7 +12,7 @@ class RegistrationsController < Devise::RegistrationsController @user = User.build(user_params) @user.process_invite_acceptence(invite) if invite.present? - if @user.save + if @user.sign_up flash[:notice] = I18n.t 'registrations.create.success' @user.seed_aspects sign_in_and_redirect(:user, @user) @@ -56,6 +56,6 @@ class RegistrationsController < Devise::RegistrationsController helper_method :invite def user_params - params.require(:user).permit(:username, :email, :getting_started, :password, :password_confirmation, :language, :disable_mail, :invitation_service, :invitation_identifier, :show_community_spotlight_in_stream, :auto_follow_back, :auto_follow_back_aspect_id, :remember_me) + params.require(:user).permit(:username, :email, :getting_started, :password, :password_confirmation, :language, :disable_mail, :invitation_service, :invitation_identifier, :show_community_spotlight_in_stream, :auto_follow_back, :auto_follow_back_aspect_id, :remember_me, :captcha, :captcha_key) end end diff --git a/app/models/user.rb b/app/models/user.rb index af682247e..6ee1b23aa 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -8,6 +8,8 @@ class User < ActiveRecord::Base include Querying include SocialActions + apply_simple_captcha :message => I18n.t('simple_captcha.message.failed'), :add_to_base => true + scope :logged_in_since, lambda { |time| where('last_sign_in_at > ?', time) } scope :monthly_actives, lambda { |time = Time.now| logged_in_since(time - 1.month) } scope :daily_actives, lambda { |time = Time.now| logged_in_since(time - 1.day) } @@ -476,6 +478,14 @@ class User < ActiveRecord::Base self.save(:validate => false) end + def sign_up + if AppConfig.settings.captcha.enable? + save_with_captcha + else + save + end + end + private def clearable_fields self.attributes.keys - ["id", "username", "encrypted_password", diff --git a/app/views/registrations/new.html.erb b/app/views/registrations/new.html.erb index 787d9a61c..650864c5c 100644 --- a/app/views/registrations/new.html.erb +++ b/app/views/registrations/new.html.erb @@ -2,70 +2,77 @@
-
- <%= image_tag('signupimages@2x_mini.jpg', :id => "collage") %> -
+
+ <%= image_tag('signupimages@2x_mini.jpg', :id => "collage") %> +
-
-

- <%= t('.hey_make').html_safe %> -

+
+

+ <%= t('.hey_make').html_safe %> +

-

- <%= t('.diaspora') %> -

+

+ <%= t('.diaspora') %> +

-

- <%= t('.sign_up') %> -

+

+ <%= t('.sign_up') %> +

- <%= form_for(resource, :validate => true, :url => registration_path(resource_name), :html => {:class => "form-horizontal block-form", :autocomplete => "off"}) do |f| %> -
-
- + <%= form_for(resource, :validate => true, :url => registration_path(resource_name), :html => {:class => "form-horizontal block-form", :autocomplete => "off"}) do |f| %> +
+
+ -
- <%= f.email_field :email, :placeholder => "luke@hoth.net", :title => t('registrations.new.enter_email'), :required => true %> -
-
+
+ <%= f.email_field :email, :placeholder => "luke@hoth.net", :title => t('registrations.new.enter_email'), :required => true %> +
+
-
- +
+ -
- <%= f.text_field :username, :placeholder => "jedi_guy", :title => t('registrations.new.enter_username'), :required => true, :pattern => "[A-Za-z0-9_]+" %> -
-
+
+ <%= f.text_field :username, :placeholder => "jedi_guy", :title => t('registrations.new.enter_username'), :required => true, :pattern => "[A-Za-z0-9_]+" %> +
+
-
- +
+ -
- <%= f.password_field :password, :placeholder => "••••••••", :title => t('registrations.new.enter_password'), :required => true, :pattern => "......+" %> -
-
+
+ <%= f.password_field :password, :placeholder => "••••••••", :title => t('registrations.new.enter_password'), :required => true, :pattern => "......+" %> +
+
-
- +
+ -
- <%= f.password_field :password_confirmation, :placeholder => "••••••••", :title => t('registrations.new.enter_password_again'), :required => true, :pattern => "......+" %> -
-
- <%= invite_hidden_tag(invite) %> -
+
+ <%= f.password_field :password_confirmation, :placeholder => "••••••••", :title => t('registrations.new.enter_password_again'), :required => true, :pattern => "......+" %> +
+
- <%= f.submit t('.continue'), :class => "new-btn", :disable_with => t('.submitting') %> - <% end %> -
+ <% if AppConfig.settings.captcha.enable? %> +
+ <%= show_simple_captcha(:object => 'user', :code_type => 'numeric') %> +
+ <% end %> + <%= invite_hidden_tag(invite) %> + + + + <%= f.submit t('.continue'), :class => "new-btn", :disable_with => t('.submitting') %> + <% end %> +
diff --git a/app/views/registrations/new.mobile.haml b/app/views/registrations/new.mobile.haml index f7a897caa..ab4cba4ed 100644 --- a/app/views/registrations/new.mobile.haml +++ b/app/views/registrations/new.mobile.haml @@ -43,6 +43,9 @@ = f.label :password_confirmation, t('password_confirmation').upcase .controls = f.password_field :password_confirmation, :placeholder => "••••••••" + + - if AppConfig.settings.captcha.enable? + = show_simple_captcha(:object => 'user', :code_type => 'numeric') .controls = f.submit t('registrations.new.create_my_account'), :class => 'btn primary', :disable_with => t('registrations.new.submitting') diff --git a/app/views/simple_captcha/_simple_captcha.haml b/app/views/simple_captcha/_simple_captcha.haml new file mode 100644 index 000000000..bc7d70bc4 --- /dev/null +++ b/app/views/simple_captcha/_simple_captcha.haml @@ -0,0 +1,4 @@ +.control-label + = simple_captcha_options[:image] +.controls + = simple_captcha_options[:field] \ No newline at end of file diff --git a/app/views/simple_captcha/_simple_captcha.mobile.haml b/app/views/simple_captcha/_simple_captcha.mobile.haml new file mode 100644 index 000000000..625fa768d --- /dev/null +++ b/app/views/simple_captcha/_simple_captcha.mobile.haml @@ -0,0 +1,4 @@ +.control-group#captcha + = simple_captcha_options[:image] + .controls + = simple_captcha_options[:field] \ No newline at end of file diff --git a/config/defaults.yml b/config/defaults.yml index f29bd246e..264edc8f6 100644 --- a/config/defaults.yml +++ b/config/defaults.yml @@ -82,6 +82,12 @@ defaults: - 'support' - 'contact' - 'example_user1dsioaioedfhgoiesajdigtoearogjaidofgjo' + captcha: + enable: true + image_size: '120x20' + captcha_length: 5 + image_style: 'simply_green' + distortion: 'low' services: facebook: enable: false diff --git a/config/diaspora.yml.example b/config/diaspora.yml.example index 664ce143c..d5e9d2d03 100644 --- a/config/diaspora.yml.example +++ b/config/diaspora.yml.example @@ -34,7 +34,7 @@ configuration: ## Section ## from the internet. This should be the URL you want to use to ## access the pod. So if you plan to reverse proxy it, it should be ## the URL the proxy listens on. - ## DO NOT CHNANGE THIS AFTER INITIAL SETUP + ## DO NOT CHANGE THIS AFTER INITIAL SETUP ## UNLESS YOU KNOW WHAT YOU'RE DOING! ## However changing http to https is okay and has no consequences. ## If you do change it you have to start over as it's hardcoded into @@ -223,7 +223,29 @@ configuration: ## Section ## your server to contact joindiaspora.com, you can change account ## below or set autofollow_on_join to false #autofollow_on_join_user: 'diasporahq@joindiaspora.com' - + + ## Settings about captcha + captcha: ## Section + + ## Set this to false if you don't want to use captcha for signup process + #enable: true + + ## Change this value to use different captcha image size + #image_size: '120x20' + + ## Length of captcha text. Default value is 5 + #captcha_length: 5 + + ## Change this value to use various image style. + ## Available options are: 'simply_blue', 'simply_red' + ## 'simply_green', 'charcoal_grey', 'embosed_silver', 'all_black', + ## 'distorted_black', 'almost_invisible', 'random' + #image_style: 'simply_green' + + ## Set this value to use various level of distortion + ## Available options are: 'low', 'medium', 'high', 'random' + #distortion: 'low' + ## Settings about invitations invitations: ## Section diff --git a/config/initializers/setup_simple_captcha.rb b/config/initializers/setup_simple_captcha.rb new file mode 100644 index 000000000..69ce517c4 --- /dev/null +++ b/config/initializers/setup_simple_captcha.rb @@ -0,0 +1,7 @@ +SimpleCaptcha.setup do |sc| + sc.image_size = AppConfig.settings.captcha.image_size + sc.length = AppConfig.settings.captcha.captcha_length.to_i + sc.image_style = AppConfig.settings.captcha.image_style + sc.distortion = AppConfig.settings.captcha.distortion + p AppConfig.settings.captcha +end \ No newline at end of file diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index 22036d06d..86f50b8a2 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -1270,3 +1270,11 @@ en: xrd_fetch_failed: "there was an error getting the xrd from account %{account}" not_enabled: "webfinger does not seem to be enabled for %{account}'s host" no_person_constructed: "No person could be constructed from this hcard." + + simple_captcha: + placeholder: "Enter the image value" + label: "Enter the code in the box:" + message: + default: "Secret Code did not match with the Image" + user: "The secret Image and code were different" + failed: "Human verification failed" diff --git a/db/migrate/20131213171804_create_simple_captcha_data.rb b/db/migrate/20131213171804_create_simple_captcha_data.rb new file mode 100644 index 000000000..4573b2056 --- /dev/null +++ b/db/migrate/20131213171804_create_simple_captcha_data.rb @@ -0,0 +1,15 @@ +class CreateSimpleCaptchaData < ActiveRecord::Migration + def self.up + create_table :simple_captcha_data do |t| + t.string :key, :limit => 40 + t.string :value, :limit => 6 + t.timestamps + end + + add_index :simple_captcha_data, :key, :name => "idx_key" + end + + def self.down + drop_table :simple_captcha_data + end +end diff --git a/db/schema.rb b/db/schema.rb index f5b374c6b..5326609a5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20130801063213) do +ActiveRecord::Schema.define(:version => 20131213171804) do create_table "account_deletions", :force => true do |t| t.string "diaspora_handle" @@ -401,6 +401,15 @@ ActiveRecord::Schema.define(:version => 20130801063213) do add_index "share_visibilities", ["shareable_id", "shareable_type", "hidden", "contact_id"], :name => "shareable_and_hidden_and_contact_id" add_index "share_visibilities", ["shareable_id"], :name => "index_post_visibilities_on_post_id" + create_table "simple_captcha_data", :force => true do |t| + t.string "key", :limit => 40 + t.string "value", :limit => 6 + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "simple_captcha_data", ["key"], :name => "idx_key" + create_table "tag_followings", :force => true do |t| t.integer "tag_id", :null => false t.integer "user_id", :null => false diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 9974ae843..7f203d1f6 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1018,4 +1018,34 @@ describe User do end end end + + describe "sign up" do + before do + params = {:username => "ohai", + :email => "ohai@example.com", + :password => "password", + :password_confirmation => "password", + :captcha => "12345", + + :person => + {:profile => + {:first_name => "O", + :last_name => "Hai"} + } + } + @user = User.build(params) + end + + it "saves with captcha off" do + AppConfig.settings.captcha.enable = false + @user.should_receive(:save).and_return(true) + @user.sign_up + end + + it "saves with captcha on" do + AppConfig.settings.captcha.enable = true + @user.should_receive(:save_with_captcha).and_return(true) + @user.sign_up + end + end end