decidim-friendly_signup 0.3 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -1
- data/app/controllers/concerns/decidim/friendly_signup/registrations_redirect.rb +37 -0
- data/app/controllers/decidim/friendly_signup/confirmation_codes_controller.rb +50 -0
- data/app/forms/decidim/friendly_signup/confirmation_code_form.rb +33 -0
- data/app/mailers/decidim/friendly_signup/confirmation_codes_mailer.rb +22 -0
- data/app/models/concerns/decidim/friendly_signup/needs_registration_codes.rb +24 -0
- data/app/packs/entrypoints/decidim_friendly_signup.js +1 -0
- data/app/packs/entrypoints/decidim_friendly_signup.scss +1 -0
- data/app/packs/src/decidim/friendly_signup/lib/instant_validator.js +3 -0
- data/app/packs/src/decidim/friendly_signup/setup_confirmations.js +57 -0
- data/app/packs/stylesheets/decidim/friendly_signup/_confirmation-codes.scss +23 -0
- data/app/views/decidim/friendly_signup/confirmation_codes/index.html.erb +38 -0
- data/app/views/decidim/friendly_signup/confirmation_codes_mailer/confirmation_instructions.html.erb +13 -0
- data/config/locales/en.yml +79 -0
- data/lib/decidim/friendly_signup/engine.rb +16 -1
- data/lib/decidim/friendly_signup/version.rb +1 -1
- data/lib/decidim/friendly_signup.rb +12 -0
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df7a2d3137cd72541b5d7e63878f022eebb44e0b115044425e727c4f0fe68d59
|
4
|
+
data.tar.gz: dd63fddf8a154b335369dcf87cae2aaff1c9b28c9bd58ad1910a97088283b75f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a03470e2cb20fec61fe7106cd59d96293d9c9e490cd132570aa514a841c43587cbcf675ba25bfd272c5dec497db6c3f6a1922c170effb21f1ddeadeec252f331
|
7
|
+
data.tar.gz: 36919447d408e1a91f22b8d650b12db69ac00c08282fd5b07862bc074a344e9d99075d53fe53436af12ba80dc209b25e9085d3ca2bc0a219a1f47061d91566be
|
data/README.md
CHANGED
@@ -20,7 +20,7 @@ This module simply substitutes some pages to ease up the registration process in
|
|
20
20
|
|
21
21
|
- [x] Remove the nickname field from the registration process and automatically create one on registering. ![Hide nickname](examples/nickname.png)
|
22
22
|
- [x] Instant validate parameters when registering without having to send it for backend validation. ![Instant validation](examples/instant_validation.png)
|
23
|
-
- [
|
23
|
+
- [x] Use numeric, confirmation codes to validate the email instead of a link. ![Confirmation codes](examples/confirmation_codes.png)
|
24
24
|
|
25
25
|
## Installation
|
26
26
|
|
@@ -42,6 +42,18 @@ And then execute:
|
|
42
42
|
bundle
|
43
43
|
```
|
44
44
|
|
45
|
+
For security reasons, it is also recomended to set a expiration time on confirmation tokens, to do that, make sure your Devise initializer has the variable `confirm_within` to certain amount of time.
|
46
|
+
|
47
|
+
For instance, you can do that by creating an initializer such as:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
# config/initializers/devise.rb
|
51
|
+
|
52
|
+
Devise.setup do |config|
|
53
|
+
config.confirm_within = 12.hours
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
45
57
|
**Note:**
|
46
58
|
|
47
59
|
The correct version of FriendlySignup should resolved automatically by the Bundler.
|
@@ -51,6 +63,7 @@ Depending on your Decidim version, choose the corresponding FriendlySignup versi
|
|
51
63
|
|
52
64
|
| FriendlySignup version | Compatible Decidim versions |
|
53
65
|
|---|---|
|
66
|
+
| 0.4.x | 0.26.x |
|
54
67
|
| 0.3.x | 0.26.x |
|
55
68
|
| 0.2.x | 0.26.x |
|
56
69
|
| 0.1.x | 0.26.x |
|
@@ -71,6 +84,9 @@ Decidim::FriendlySignup.configure do |config|
|
|
71
84
|
|
72
85
|
# Hide nickname field and create one automatically from user's name or email (default is true)
|
73
86
|
config.hide_nickname = false
|
87
|
+
|
88
|
+
# Send the users a 4-digit number that needs to be entered in a confirmation page instead of a confirmation link (default is true)
|
89
|
+
config.use_confirmation_codes = false
|
74
90
|
end
|
75
91
|
```
|
76
92
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module FriendlySignup
|
7
|
+
module RegistrationsRedirect
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
def after_sign_up_path_for(user)
|
12
|
+
codes_confirmation_path(user) || super(user)
|
13
|
+
end
|
14
|
+
|
15
|
+
def after_inactive_sign_up_path_for(user)
|
16
|
+
codes_confirmation_path(user) || super(user)
|
17
|
+
end
|
18
|
+
|
19
|
+
def after_resending_confirmation_instructions_path_for(resource_name)
|
20
|
+
user = Decidim::User.find_by email: params.dig(:user, :email)
|
21
|
+
codes_confirmation_path(user) || super(resource_name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def codes_confirmation_path(user)
|
28
|
+
return if Decidim::FriendlySignup.use_confirmation_codes.blank?
|
29
|
+
return if user.blank?
|
30
|
+
return unless user.inactive_message.to_s == "unconfirmed"
|
31
|
+
|
32
|
+
set_flash_message! :notice, :signed_up_but_code_required
|
33
|
+
decidim_friendly_signup.confirmation_codes_path(confirmation_token: user.confirmation_token)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module FriendlySignup
|
5
|
+
class ConfirmationCodesController < Decidim::Devise::ConfirmationsController
|
6
|
+
include Decidim::FormFactory
|
7
|
+
include NeedsHeaderSnippets
|
8
|
+
|
9
|
+
before_action :require_unconfirmed_user
|
10
|
+
helper_method :user, :confirmation_form
|
11
|
+
|
12
|
+
def index; end
|
13
|
+
|
14
|
+
def create
|
15
|
+
if confirmation_form.valid?
|
16
|
+
user.confirm
|
17
|
+
flash[:success] = I18n.t("confirmation_codes.create.user_confirmed", name: user.name, scope: "decidim.friendly_signup")
|
18
|
+
return sign_in_and_redirect user, event: :authentication
|
19
|
+
end
|
20
|
+
|
21
|
+
flash.now[:alert] = confirmation_form.errors.messages.values.flatten.join(" ")
|
22
|
+
render :index
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def confirmation_form
|
28
|
+
@confirmation_form ||= form(ConfirmationCodeForm).from_params(params)
|
29
|
+
end
|
30
|
+
|
31
|
+
def user
|
32
|
+
@user ||= User.find_by(confirmation_token: params[:confirmation_token], organization: current_organization)
|
33
|
+
end
|
34
|
+
|
35
|
+
def require_unconfirmed_user
|
36
|
+
return redirect_to decidim.user_confirmation_path unless FriendlySignup.use_confirmation_codes
|
37
|
+
|
38
|
+
unless user.present? && !user.confirmed?
|
39
|
+
flash[:alert] = I18n.t("confirmation_code_form.invalid_token", scope: "decidim.friendly_signup")
|
40
|
+
return redirect_to decidim.new_user_session_path
|
41
|
+
end
|
42
|
+
|
43
|
+
if user.send(:confirmation_period_expired?)
|
44
|
+
flash[:alert] = I18n.t("confirmation_code_form.expired", scope: "decidim.friendly_signup")
|
45
|
+
redirect_to decidim.user_confirmation_path
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module FriendlySignup
|
5
|
+
class ConfirmationCodeForm < Decidim::Form
|
6
|
+
attribute :confirmation_token, String
|
7
|
+
attribute :code, Integer
|
8
|
+
attribute :confirmation_numbers, Array[Integer]
|
9
|
+
|
10
|
+
validates :confirmation_token, presence: true
|
11
|
+
validate :code_matches_confirmation_token
|
12
|
+
validate :user_exists
|
13
|
+
|
14
|
+
def user_code
|
15
|
+
code || confirmation_numbers.map(&:to_s).join("").to_i
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def code_matches_confirmation_token
|
21
|
+
return if FriendlySignup.confirmation_code(confirmation_token) == user_code
|
22
|
+
|
23
|
+
errors.add(:code, I18n.t("confirmation_code_form.invalid", scope: "decidim.friendly_signup"))
|
24
|
+
end
|
25
|
+
|
26
|
+
def user_exists
|
27
|
+
return if User.exists?(confirmation_token: confirmation_token, organization: current_organization)
|
28
|
+
|
29
|
+
errors.add(:code, I18n.t("confirmation_code_form.invalid_token", scope: "decidim.friendly_signup"))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module FriendlySignup
|
5
|
+
class ConfirmationCodesMailer < ApplicationMailer
|
6
|
+
include Decidim::LocalisedMailer
|
7
|
+
|
8
|
+
def confirmation_instructions(user, opts)
|
9
|
+
@user = user
|
10
|
+
@email = opts[:to] || user.email
|
11
|
+
@token = opts[:token]
|
12
|
+
@organization = user.organization
|
13
|
+
@code = FriendlySignup.confirmation_code(@token)
|
14
|
+
@expires_at = @user.confirmation_sent_at + @user.class.confirm_within if @user.class.confirm_within
|
15
|
+
|
16
|
+
with_user(user) do
|
17
|
+
mail(to: "#{user.name} <#{@email}>", subject: I18n.t("decidim.friendly_signup.confirmation_codes.mailer.subject", organization: @organization.name))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module FriendlySignup
|
7
|
+
module NeedsRegistrationCodes
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
def send_confirmation_instructions
|
12
|
+
return super if Decidim::FriendlySignup.use_confirmation_codes.blank?
|
13
|
+
return super unless inactive_message.to_s == "unconfirmed"
|
14
|
+
|
15
|
+
generate_confirmation_token! unless @raw_confirmation_token
|
16
|
+
|
17
|
+
opts = pending_reconfirmation? ? { to: unconfirmed_email } : {}
|
18
|
+
opts[:token] = @raw_confirmation_token
|
19
|
+
ConfirmationCodesMailer.confirmation_instructions(self, opts).deliver_now
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -15,6 +15,9 @@ export default class InstantValidator {
|
|
15
15
|
}
|
16
16
|
|
17
17
|
init() {
|
18
|
+
if (!this.url || !this.$form.length) {
|
19
|
+
return;
|
20
|
+
}
|
18
21
|
this.$form.foundation("disableValidation");
|
19
22
|
// this final validation prevents abide from resetting the field when user loses focus
|
20
23
|
this.$inputs.on("blur", (evt) => {
|
@@ -0,0 +1,57 @@
|
|
1
|
+
$(() => {
|
2
|
+
const $inputs = $('.confirmation-code-inputs input[type="number"]');
|
3
|
+
const $form = $inputs.closest("form");
|
4
|
+
const intRegex = /^\d+$/;
|
5
|
+
let disableManual = false;
|
6
|
+
|
7
|
+
// Parses the individual digits into the individual boxes.
|
8
|
+
const pasteValues = (element, $first) => {
|
9
|
+
const values = element.split("");
|
10
|
+
let $inputBox = $first;
|
11
|
+
|
12
|
+
$(values).each((index) => {
|
13
|
+
$inputBox.val(values[index]);
|
14
|
+
$inputBox = $inputBox.next('input[type="number"]');
|
15
|
+
if ($inputBox.length === 0) {
|
16
|
+
$form.submit();
|
17
|
+
}
|
18
|
+
});
|
19
|
+
};
|
20
|
+
|
21
|
+
$inputs.on("focus", (e) => {
|
22
|
+
$(e.target).select();
|
23
|
+
});
|
24
|
+
|
25
|
+
// Prevents user from manually entering non-digits.
|
26
|
+
$inputs.on("input.fromManual", (e) => {
|
27
|
+
if (disableManual) {
|
28
|
+
return;
|
29
|
+
}
|
30
|
+
const $this = $(e.target);
|
31
|
+
if (intRegex.test($this.val())) {
|
32
|
+
pasteValues($this.val(), $this);
|
33
|
+
$this.next('input[type="number"]').focus();
|
34
|
+
} else {
|
35
|
+
$this.val("");
|
36
|
+
}
|
37
|
+
});
|
38
|
+
|
39
|
+
$inputs.on("paste", (evt) => {
|
40
|
+
const $this = $(evt.target);
|
41
|
+
const originalValue = $this.val();
|
42
|
+
$this.val("");
|
43
|
+
disableManual = true;
|
44
|
+
$this.one("input.fromPaste", (e) => {
|
45
|
+
const $currentInputBox = $(e.target);
|
46
|
+
|
47
|
+
const pastedValue = $currentInputBox.val();
|
48
|
+
if (intRegex.test(pastedValue)) {
|
49
|
+
pasteValues(pastedValue, $inputs.eq(0));
|
50
|
+
}
|
51
|
+
else {
|
52
|
+
$this.val(originalValue);
|
53
|
+
}
|
54
|
+
disableManual = false;
|
55
|
+
});
|
56
|
+
});
|
57
|
+
});
|
@@ -0,0 +1,23 @@
|
|
1
|
+
.confirmation-code-inputs {
|
2
|
+
display: flex;
|
3
|
+
justify-content: center;
|
4
|
+
margin: 2rem;
|
5
|
+
|
6
|
+
input[type="number"] {
|
7
|
+
width: 15%;
|
8
|
+
font-size: 5em;
|
9
|
+
height: 1.2em;
|
10
|
+
line-height: 1;
|
11
|
+
padding: 0;
|
12
|
+
margin: 0 2%;
|
13
|
+
text-align: center;
|
14
|
+
box-shadow: 1px 3px 3px #bbb;
|
15
|
+
-moz-appearance: textfield;
|
16
|
+
|
17
|
+
&::-webkit-inner-spin-button,
|
18
|
+
&::-webkit-outer-spin-button {
|
19
|
+
-webkit-appearance: none;
|
20
|
+
margin: 0;
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
<% add_decidim_page_title(t(".enter_code")) %>
|
2
|
+
|
3
|
+
<div class="wrapper">
|
4
|
+
<div class="row collapse">
|
5
|
+
<div class="row collapse">
|
6
|
+
<div class="columns large-8 large-centered text-center page-title">
|
7
|
+
<h1><%= t(".title") %></h1>
|
8
|
+
<h6><%= t(".subtitle") %></h6>
|
9
|
+
</div>
|
10
|
+
</div>
|
11
|
+
|
12
|
+
<div class="row">
|
13
|
+
<div class="columns medium-10 large-8 medium-centered">
|
14
|
+
<div class="card">
|
15
|
+
<div class="card__content">
|
16
|
+
<p class="text-center"><%= t(".description", email: "<strong>#{user.email}</strong>").html_safe %></p>
|
17
|
+
<%= decidim_form_for(confirmation_form, url: decidim_friendly_signup.confirmation_codes_path(confirmation_token: confirmation_form.confirmation_token)) do |f| %>
|
18
|
+
<div class="field confirmation-code-inputs">
|
19
|
+
<%= number_field_tag "confirmation_numbers[0]", "", autofocus: true, autocomplete: :off %>
|
20
|
+
<%= number_field_tag "confirmation_numbers[1]", "", autocomplete: :off %>
|
21
|
+
<%= number_field_tag "confirmation_numbers[2]", "", autocomplete: :off %>
|
22
|
+
<%= number_field_tag "confirmation_numbers[3]", "", autocomplete: :off %>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<div class="actions text-center">
|
26
|
+
<%= f.submit t(".verify"), class: "button text-uppercase" %>
|
27
|
+
</div>
|
28
|
+
<% end %>
|
29
|
+
|
30
|
+
<p class="text-center">
|
31
|
+
<%= link_to t(".code_not_received"), decidim.user_confirmation_path(confirmation_token: confirmation_form.confirmation_token, "user[email]": user.email), method: :post, data: { confirm: t(".confirm_send_code", email: user.email) } %>
|
32
|
+
</p>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
</div>
|
data/app/views/decidim/friendly_signup/confirmation_codes_mailer/confirmation_instructions.html.erb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
<h1 class="text-center"><%= t(".title") %></h1>
|
2
|
+
|
3
|
+
<p class="email-instructions text-center"><%= t(".subtitle", organization: link_to(@organization.name, decidim_friendly_signup.confirmation_codes_path(confirmation_token: @token))).html_safe %></p>
|
4
|
+
|
5
|
+
<h3 class="email-instruction text-center" style="margin:1em 0 0.2em 0;"><%= t(".copy") %></h3>
|
6
|
+
|
7
|
+
<% if @expires_at %>
|
8
|
+
<p class="email-small text-center"><%= t(".expires_in", time: distance_of_time_in_words(Time.now, @expires_at, scope: "decidim.friendly_signup.datetime.distance_in_words")) %></p>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<p class="stat text-center" style="margin:1em 0;"><b style="font-size: 2em"><%= @code %></b></p>
|
12
|
+
|
13
|
+
<p class="email-small email-closing text-center"><%= t(".ignore").html_safe %></p>
|
data/config/locales/en.yml
CHANGED
@@ -1,10 +1,89 @@
|
|
1
1
|
---
|
2
2
|
en:
|
3
|
+
activemodel:
|
4
|
+
attributes:
|
5
|
+
confirmation_code:
|
6
|
+
code: Confirmation code
|
3
7
|
decidim:
|
4
8
|
friendly_signup:
|
9
|
+
confirmation_code_form:
|
10
|
+
expired: Sorry, this code has expired, please generate a new one.
|
11
|
+
invalid: Code is invalid, please make sure to copy the code emailed to you.
|
12
|
+
invalid_token: Invalid token.
|
13
|
+
confirmation_codes:
|
14
|
+
create:
|
15
|
+
user_confirmed: Welcome %{name}! Your account has been succesfully confirmed!
|
16
|
+
index:
|
17
|
+
code_not_received: Didn't receive the code?
|
18
|
+
confirm_send_code: Do you want to resend the confirmation code to %{email}?<br>Be
|
19
|
+
sure to check the spam folder just in case!
|
20
|
+
description: You should receive a 4 digit code at %{email}.<br>If you can't
|
21
|
+
find it, please check your spam folder or wait up to 10 minutes.
|
22
|
+
enter_code: Enter code
|
23
|
+
subtitle: You need to confirm your email address to be able to submit proposals,
|
24
|
+
comment and vote.
|
25
|
+
title: One last step...
|
26
|
+
verify: Verify
|
27
|
+
mailer:
|
28
|
+
subject: Confirm your account at %{organization}
|
29
|
+
resend_code:
|
30
|
+
sent: The confirmation code has been sent to %{email}.
|
31
|
+
confirmation_codes_mailer:
|
32
|
+
confirmation_instructions:
|
33
|
+
copy: 'Copy this code:'
|
34
|
+
expires_in: It will expire in %{time}.
|
35
|
+
ignore: |-
|
36
|
+
If you didn't request this comunication, please ignore this email.<br />
|
37
|
+
Your account won't be active until your account is fully confirmed.
|
38
|
+
subtitle: To finalize the registration you just need to copy the 4 digit
|
39
|
+
code below, go back to the %{organization} signup page and paste it!
|
40
|
+
title: You're almost there!
|
41
|
+
datetime:
|
42
|
+
distance_in_words:
|
43
|
+
about_x_hours:
|
44
|
+
one: about 1 hour
|
45
|
+
other: about %{count} hours
|
46
|
+
about_x_months:
|
47
|
+
one: about 1 month
|
48
|
+
other: about %{count} months
|
49
|
+
about_x_years:
|
50
|
+
one: about 1 year
|
51
|
+
other: about %{count} years
|
52
|
+
almost_x_years:
|
53
|
+
one: almost 1 year
|
54
|
+
other: almost %{count} years
|
55
|
+
half_a_minute: half a minute
|
56
|
+
less_than_x_minutes:
|
57
|
+
one: less than a minute
|
58
|
+
other: less than %{count} minutes
|
59
|
+
less_than_x_seconds:
|
60
|
+
one: less than 1 second
|
61
|
+
other: less than %{count} seconds
|
62
|
+
over_x_years:
|
63
|
+
one: over 1 year
|
64
|
+
other: over %{count} years
|
65
|
+
x_days:
|
66
|
+
one: 1 day
|
67
|
+
other: "%{count} days"
|
68
|
+
x_minutes:
|
69
|
+
one: 1 minute
|
70
|
+
other: "%{count} minutes"
|
71
|
+
x_months:
|
72
|
+
one: 1 month
|
73
|
+
other: "%{count} months"
|
74
|
+
x_seconds:
|
75
|
+
one: 1 second
|
76
|
+
other: "%{count} seconds"
|
5
77
|
shared:
|
6
78
|
password_fields:
|
7
79
|
hidden_password: Your password is hidden
|
8
80
|
hide_password: Hide password
|
9
81
|
show_password: Show password
|
10
82
|
shown_password: Your password is shown
|
83
|
+
devise:
|
84
|
+
confirmations:
|
85
|
+
signed_up_but_code_required: A message with a code has been sent to your email
|
86
|
+
address. Please copy and paste the received code in this page.
|
87
|
+
registrations:
|
88
|
+
signed_up_but_code_required: A message with a code has been sent to your email
|
89
|
+
address. Please copy and paste the received code in this page.
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "rails"
|
4
4
|
require "decidim/core"
|
5
|
+
require "rack/attack"
|
5
6
|
|
6
7
|
module Decidim
|
7
8
|
module FriendlySignup
|
@@ -10,6 +11,9 @@ module Decidim
|
|
10
11
|
isolate_namespace Decidim::FriendlySignup
|
11
12
|
|
12
13
|
routes do
|
14
|
+
devise_scope :user do
|
15
|
+
resources :confirmation_codes, only: [:index, :create]
|
16
|
+
end
|
13
17
|
post :validate, to: "validator#validate"
|
14
18
|
end
|
15
19
|
|
@@ -18,13 +22,24 @@ module Decidim
|
|
18
22
|
# overrides
|
19
23
|
config.after_initialize do
|
20
24
|
Decidim::Devise::RegistrationsController.include(Decidim::FriendlySignup::NeedsHeaderSnippets)
|
25
|
+
Decidim::Devise::RegistrationsController.include(Decidim::FriendlySignup::RegistrationsRedirect)
|
26
|
+
Decidim::Devise::ConfirmationsController.include(Decidim::FriendlySignup::RegistrationsRedirect)
|
21
27
|
Decidim::Devise::InvitationsController.include(Decidim::FriendlySignup::NeedsHeaderSnippets)
|
22
28
|
Decidim::Devise::PasswordsController.include(Decidim::FriendlySignup::NeedsHeaderSnippets)
|
23
29
|
Decidim::AccountController.include(Decidim::FriendlySignup::NeedsHeaderSnippets)
|
24
30
|
Decidim::RegistrationForm.include(Decidim::FriendlySignup::AutoNickname)
|
31
|
+
Decidim::User.include(Decidim::FriendlySignup::NeedsRegistrationCodes)
|
25
32
|
end
|
26
33
|
|
27
|
-
initializer "
|
34
|
+
initializer "friendly_signup.confirmation_throttling" do
|
35
|
+
# Throttle confirmation attempts for a given code parameter to 6 reqs/minute
|
36
|
+
# Return the confirmation_token as a discriminator on POST /users/sign_in requests
|
37
|
+
Rack::Attack.throttle("limit confirmations attempts per code", limit: 5, period: 60.seconds) do |request|
|
38
|
+
request.params["confirmation_token"] if request.path == "/friendly_signup/confirmation_codes" && request.post?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
initializer "friendly_signup.webpacker.assets_path" do
|
28
43
|
Decidim.register_assets_path File.expand_path("app/packs", root)
|
29
44
|
end
|
30
45
|
end
|
@@ -23,6 +23,18 @@ module Decidim
|
|
23
23
|
config_accessor :hide_nickname do
|
24
24
|
true
|
25
25
|
end
|
26
|
+
|
27
|
+
# Use confirmation codes instead of confirmation links
|
28
|
+
config_accessor :use_confirmation_codes do
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
# Generates a secure code from a string
|
33
|
+
def self.confirmation_code(hash)
|
34
|
+
num = Decidim::Tokenizer.new(salt: Rails.application.secret_key_base).int_digest(hash).to_s[0..3]
|
35
|
+
num += "0" while num.size < 4
|
36
|
+
num.to_i
|
37
|
+
end
|
26
38
|
end
|
27
39
|
end
|
28
40
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: decidim-friendly_signup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.4'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Vergés
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-07-
|
11
|
+
date: 2022-07-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: decidim-core
|
@@ -49,21 +49,30 @@ files:
|
|
49
49
|
- README.md
|
50
50
|
- Rakefile
|
51
51
|
- app/controllers/concerns/decidim/friendly_signup/needs_header_snippets.rb
|
52
|
+
- app/controllers/concerns/decidim/friendly_signup/registrations_redirect.rb
|
52
53
|
- app/controllers/decidim/friendly_signup/application_controller.rb
|
54
|
+
- app/controllers/decidim/friendly_signup/confirmation_codes_controller.rb
|
53
55
|
- app/controllers/decidim/friendly_signup/validator_controller.rb
|
54
56
|
- app/forms/concerns/decidim/friendly_signup/auto_nickname.rb
|
57
|
+
- app/forms/decidim/friendly_signup/confirmation_code_form.rb
|
58
|
+
- app/mailers/decidim/friendly_signup/confirmation_codes_mailer.rb
|
59
|
+
- app/models/concerns/decidim/friendly_signup/needs_registration_codes.rb
|
55
60
|
- app/packs/entrypoints/decidim_friendly_signup.js
|
56
61
|
- app/packs/entrypoints/decidim_friendly_signup.scss
|
57
62
|
- app/packs/images/decidim/friendly_signup/icon.svg
|
58
63
|
- app/packs/src/decidim/friendly_signup/lib/instant_validator.js
|
59
64
|
- app/packs/src/decidim/friendly_signup/lib/password_toggler.js
|
65
|
+
- app/packs/src/decidim/friendly_signup/setup_confirmations.js
|
60
66
|
- app/packs/src/decidim/friendly_signup/setup_password.js
|
61
67
|
- app/packs/src/decidim/friendly_signup/setup_validations.js
|
68
|
+
- app/packs/stylesheets/decidim/friendly_signup/_confirmation-codes.scss
|
62
69
|
- app/packs/stylesheets/decidim/friendly_signup/_input-groups.scss
|
63
70
|
- app/views/decidim/account/_password_fields.html.erb
|
64
71
|
- app/views/decidim/devise/invitations/edit.html.erb
|
65
72
|
- app/views/decidim/devise/passwords/edit.html.erb
|
66
73
|
- app/views/decidim/devise/registrations/new.html.erb
|
74
|
+
- app/views/decidim/friendly_signup/confirmation_codes/index.html.erb
|
75
|
+
- app/views/decidim/friendly_signup/confirmation_codes_mailer/confirmation_instructions.html.erb
|
67
76
|
- app/views/decidim/friendly_signup/shared/_password_fields.html.erb
|
68
77
|
- config/assets.rb
|
69
78
|
- config/i18n-tasks.yml
|