Skip to content

Commit

Permalink
feat: Addition of Extra User Fields (#46)
Browse files Browse the repository at this point in the history
* feat: Addition of Extra User Fields

* fix: Fix failing test
  • Loading branch information
AyakorK authored Jul 22, 2024
1 parent de74d19 commit 171ec53
Show file tree
Hide file tree
Showing 6 changed files with 295 additions and 0 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ gem "decidim", "~> #{DECIDIM_VERSION}.0"
# External Decidim gems
gem "decidim-cache_cleaner"
gem "decidim-decidim_awesome", git: "https://github.com/octree-gva/decidim-module-decidim_awesome.git", branch: "feat/awesome_decidim_private_fields"
gem "decidim-extra_user_fields", git: "https://github.com/OpenSourcePolitics/decidim-module-extra_user_fields.git", branch: DECIDIM_BRANCH
gem "decidim-friendly_signup", git: "https://github.com/OpenSourcePolitics/decidim-module-friendly_signup.git"
gem "decidim-spam_detection"
gem "decidim-term_customizer", git: "https://github.com/opensourcepolitics/decidim-module-term_customizer.git", branch: "fix/multi-threading-compliant"
Expand Down
16 changes: 16 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
GIT
remote: https://github.com/OpenSourcePolitics/decidim-module-extra_user_fields.git
revision: 25f5a7843a38a5f9360f9bd42eb7e246d997bc7b
branch: release/0.27-stable
specs:
decidim-extra_user_fields (0.27.2)
country_select (~> 9.0)
decidim-core (>= 0.27.0, < 0.28)
deface (~> 1.5)

GIT
remote: https://github.com/OpenSourcePolitics/decidim-module-friendly_signup.git
revision: 1c91e024ae4467c097b39673e5d78b06afd206d1
Expand Down Expand Up @@ -198,6 +208,10 @@ GEM
commonmarker (0.23.10)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
countries (6.0.1)
unaccent (~> 0.3)
country_select (9.0.0)
countries (> 5.0, < 7.0)
crack (1.0.0)
bigdecimal
rexml
Expand Down Expand Up @@ -882,6 +896,7 @@ GEM
uber (0.1.0)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unaccent (0.4.0)
unicode-display_width (2.5.0)
uri (0.13.0)
valid_email2 (2.3.1)
Expand Down Expand Up @@ -951,6 +966,7 @@ DEPENDENCIES
decidim-cache_cleaner
decidim-decidim_awesome!
decidim-dev (~> 0.27.0)
decidim-extra_user_fields!
decidim-friendly_signup!
decidim-spam_detection
decidim-term_customizer!
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# frozen_string_literal: true

require "active_support/concern"

module Decidim
module ExtraUserFields
# Changes in methods to store extra fields in user profile
module CreateRegistrationsCommandsOverrides
extend ActiveSupport::Concern

def call
return broadcast(:invalid) if same_email_representative?

if form.invalid?

user = User.has_pending_invitations?(form.current_organization.id, form.email)
user.invite!(user.invited_by) if user
return broadcast(:invalid)
end

create_user
send_email_to_statutory_representative

broadcast(:ok, @user)
rescue ActiveRecord::RecordInvalid
broadcast(:invalid)
end

private

def create_user
@user = User.create!(
email: form.email,
name: form.name,
nickname: form.nickname,
password: form.password,
password_confirmation: form.password_confirmation,
password_updated_at: Time.current,
organization: form.current_organization,
tos_agreement: form.tos_agreement,
newsletter_notifications_at: form.newsletter_at,
accepted_tos_version: form.current_organization.tos_version,
locale: form.current_locale,
extended_data: extended_data
)
end

def extended_data
@extended_data ||= (@user&.extended_data || {}).merge(
country: form.country,
postal_code: form.postal_code,
date_of_birth: form.date_of_birth,
gender: form.gender,
phone_number: form.phone_number,
location: form.location,
underage: form.underage,
statutory_representative_email: form.statutory_representative_email
)
end

def send_email_to_statutory_representative
return if form.statutory_representative_email.blank? || !form.underage

Decidim::ExtraUserFields::StatutoryRepresentativeMailer.inform(@user).deliver_now
end

def same_email_representative?
return false if form.statutory_representative_email.blank?

form.statutory_representative_email == form.email
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

# This migration comes from decidim_extra_user_fields (originally 20221024121407)

class AddExtraUserFieldsToDecidimOrganization < ActiveRecord::Migration[6.0]
def up
add_column :decidim_organizations, :extra_user_fields, :jsonb, default: { "enabled" => false }
end

def down
remove_column :decidim_organizations, :extra_user_fields, :jsonb
end
end
1 change: 1 addition & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,7 @@
t.string "machine_translation_display_priority", default: "original", null: false
t.string "external_domain_whitelist", default: [], array: true
t.boolean "enable_participatory_space_filters", default: true
t.jsonb "extra_user_fields", default: {"enabled"=>false}
t.index ["host"], name: "index_decidim_organizations_on_host", unique: true
t.index ["name"], name: "index_decidim_organizations_on_name", unique: true
t.index ["secondary_hosts"], name: "index_decidim_organizations_on_secondary_hosts"
Expand Down
190 changes: 190 additions & 0 deletions spec/commands/decidim/create_registration_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
# frozen_string_literal: true

require "spec_helper"

module Decidim
module Comments
describe CreateRegistration do
describe "call" do
let(:organization) { create(:organization) }

let(:name) { "Username" }
let(:nickname) { "nickname" }
let(:email) { "[email protected]" }
let(:password) { "Y1fERVzL2F" }
let(:password_confirmation) { password }
let(:tos_agreement) { "1" }
let(:current_locale) { "fr" }
let(:country) { "Argentina" }
let(:date_of_birth) { "01/01/2000" }
let(:gender) { "Other" }
let(:location) { "Paris" }
let(:phone_number) { "0123456789" }
let(:postal_code) { "75001" }
let(:newsletter_notifications_at) { nil }
let(:notifications_sending_frequency) { "daily" }
let(:underage) { false }
let(:statutory_representative_email) { nil }
let(:extended_data) do
{
country: country,
date_of_birth: date_of_birth,
gender: gender,
location: location,
phone_number: phone_number,
postal_code: postal_code,
underage: underage,
statutory_representative_email: statutory_representative_email
}
end

let(:form_params) do
{
"user" => {
"name" => name,
"nickname" => nickname,
"email" => email,
"password" => password,
"password_confirmation" => password_confirmation,
"tos_agreement" => tos_agreement,
"country" => country,
"postal_code" => postal_code,
"date_of_birth" => date_of_birth,
"gender" => gender,
"phone_number" => phone_number,
"location" => location,
"underage" => underage,
"statutory_representative_email" => statutory_representative_email
}
}
end
let(:form) do
RegistrationForm.from_params(
form_params,
current_locale: current_locale
).with_context(
current_organization: organization
)
end
let(:command) { described_class.new(form) }

describe "when the form is not valid" do
before do
allow(form).to receive(:invalid?).and_return(true)
end

it "broadcasts invalid" do
expect { command.call }.to broadcast(:invalid)
end

it "doesn't create a user" do
expect do
command.call
end.not_to change(User, :count)
end

context "when the user was already invited" do
let(:user) { build(:user, email: email, organization: organization) }

before do
user.invite!
clear_enqueued_jobs
end

RSpec::Matchers.define_negated_matcher :not_change, :change

it "receives the invitation email again" do
expect { command.call }.not_to change(User, :count)

expect do
command.call
user.reload
end.to not_change(User, :count)
.and broadcast(:invalid)
.and change(user.reload, :invitation_token)

expect(ActionMailer::MailDeliveryJob).to have_been_enqueued.on_queue("mailers").twice
end
end
end

describe "when the form is valid" do
it "broadcasts ok" do
expect { command.call }.to broadcast(:ok)
end

it "creates a new user" do
expect(User).to receive(:create!).with(
name: form.name,
nickname: form.nickname,
email: form.email,
password: form.password,
password_confirmation: form.password_confirmation,
password_updated_at: an_instance_of(ActiveSupport::TimeWithZone),
tos_agreement: form.tos_agreement,
organization: organization,
accepted_tos_version: organization.tos_version,
newsletter_notifications_at: newsletter_notifications_at,
locale: form.current_locale,
extended_data: {
country: country,
date_of_birth: Date.parse(date_of_birth),
gender: gender,
location: location,
phone_number: phone_number,
postal_code: postal_code,
underage: underage,
statutory_representative_email: statutory_representative_email
}
).and_call_original

expect { command.call }.to change(User, :count).by(1)
end

it "sets the password_updated_at to the current time" do
expect { command.call }.to broadcast(:ok)
expect(User.last.password_updated_at).to be_between(2.seconds.ago, Time.current)
end

describe "when user keeps the newsletter unchecked" do
let(:newsletter) { "0" }

it "creates a user with no newsletter notifications" do
expect do
command.call
expect(User.last.newsletter_notifications_at).to be_nil
end.to change(User, :count).by(1)
end
end

describe "when the user is underage and sends a valid email" do
let(:underage) { true }
let(:statutory_representative_email) { "[email protected]" }

it "creates a user with the statutory representative email and sends email" do
expect do
expect(Decidim::ExtraUserFields::StatutoryRepresentativeMailer).to receive(:inform).with(instance_of(Decidim::User)).and_call_original

command.call

user = User.last
expect(user.extended_data["statutory_representative_email"]).to eq(statutory_representative_email)
end.to change(User, :count).by(1)
end
end

describe "when the user is underage and tries to duplicate email" do
let(:underage) { true }
let(:statutory_representative_email) { email }

it "broadcasts invalid" do
expect(Decidim::ExtraUserFields::StatutoryRepresentativeMailer).not_to receive(:inform).with(instance_of(Decidim::User)).and_call_original

expect { command.call }.to broadcast(:invalid)
end
end
end
end
end
end
end

0 comments on commit 171ec53

Please sign in to comment.