Skip to content

Commit

Permalink
fix: Save Extended data for omniauth registrations
Browse files Browse the repository at this point in the history
  • Loading branch information
Quentinchampenois committed Dec 6, 2023
1 parent ab846ed commit 5a1c512
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 3 deletions.
147 changes: 147 additions & 0 deletions app/commands/decidim/create_omniauth_registration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# frozen_string_literal: true

module Decidim
# A command with all the business logic to create a user from omniauth
class CreateOmniauthRegistration < Decidim::Command
# Public: Initializes the command.
#
# form - A form object with the params.
def initialize(form, verified_email = nil)
@form = form
@verified_email = verified_email
end

# Executes the command. Broadcasts these events:
#
# - :ok when everything is valid.
# - :invalid if the form wasn't valid and we couldn't proceed.
#
# Returns nothing.
def call
verify_oauth_signature!

begin
if existing_identity
user = existing_identity.user
verify_user_confirmed(user)

return broadcast(:ok, user)
end
return broadcast(:invalid) if form.invalid?

transaction do
create_or_find_user
@identity = create_identity
end
trigger_omniauth_registration

broadcast(:ok, @user)
rescue ActiveRecord::RecordInvalid => e
broadcast(:error, e.record)
end
end

private

attr_reader :form, :verified_email

def create_or_find_user
generated_password = SecureRandom.hex

@user = User.find_or_initialize_by(
email: verified_email,
organization: organization
)

if @user.persisted?
# If user has left the account unconfirmed and later on decides to sign
# in with omniauth with an already verified account, the account needs
# to be marked confirmed.
@user.skip_confirmation! if !@user.confirmed? && @user.email == verified_email
else
@user.email = (verified_email || form.email)
@user.name = form.name
@user.nickname = form.normalized_nickname
@user.newsletter_notifications_at = nil
@user.password = generated_password
@user.password_confirmation = generated_password
if form.avatar_url.present?
url = URI.parse(form.avatar_url)
filename = File.basename(url.path)
file = url.open
@user.avatar.attach(io: file, filename: filename)
end
@user.extended_data = extended_data
@user.skip_confirmation! if verified_email
end

@user.tos_agreement = "1"
@user.save!
end

def create_identity
@user.identities.create!(
provider: form.provider,
uid: form.uid,
organization: organization
)
end

def organization
@form.current_organization
end

def existing_identity
@existing_identity ||= Identity.find_by(
user: organization.users,
provider: form.provider,
uid: form.uid
)
end

def verify_user_confirmed(user)
return true if user.confirmed?
return false if user.email != verified_email

user.skip_confirmation!
user.save!
end

def verify_oauth_signature!
raise InvalidOauthSignature, "Invalid oauth signature: #{form.oauth_signature}" unless signature_valid?
end

def signature_valid?
signature = OmniauthRegistrationForm.create_signature(form.provider, form.uid)
form.oauth_signature == signature
end

def trigger_omniauth_registration
ActiveSupport::Notifications.publish(
"decidim.user.omniauth_registration",
user_id: @user.id,
identity_id: @identity.id,
provider: form.provider,
uid: form.uid,
email: form.email,
name: form.name,
nickname: form.normalized_nickname,
avatar_url: form.avatar_url,
raw_data: form.raw_data
)
end

def extended_data
{
birth_date: form.birth_date,
address: form.address,
postal_code: form.postal_code,
city: form.city,
certification: form&.certification
}
end
end

class InvalidOauthSignature < StandardError
end
end
6 changes: 5 additions & 1 deletion app/views/decidim/devise/omniauth_registrations/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

<div class="row">
<div class="columns medium-12">
<%= f.date_select :birth_date, { label: t(".birth_date"), start_year: Date.today.year - 116, end_year: Date.today.year - 16 }, { class: "columns medium-3" } %>
<%= f.date_select :birth_date, { label: t(".birth_date"), start_year: Date.today.year - 100, end_year: Date.today.year }, { class: "columns medium-3" } %>
</div>
<div class="columns margin-bottom-1">
<small><em><%= t(".birth_date_help") %></em></small>
Expand All @@ -63,6 +63,10 @@
</div>
</div>
</div>

<div class="field">
<%= f.check_box :certification, label: t(".certification") %>
</div>
</div>

<%= f.hidden_field :email %>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,22 @@ module OmniauthRegistrationFormExtend
extend ActiveSupport::Concern

included do
attribute :certification, ::ActiveModel::Type::Boolean
attribute :birth_date, Date
attribute :address, String
attribute :postal_code, String
attribute :city, String

validates :email, 'valid_email_2/email': { mx: true }
validates :email, "valid_email_2/email": { mx: true }
validates :postal_code,
:birth_date,
:city,
:address,
:certification,
presence: true

validates :postal_code, numericality: { only_integer: true }, length: { is: 5 }
validates :certification, acceptance: true
validate :over_16?

private
Expand All @@ -34,4 +38,4 @@ def over_16?
Decidim::OmniauthRegistrationForm.class_eval do
clear_validators!
include OmniauthRegistrationFormExtend
end
end

0 comments on commit 5a1c512

Please sign in to comment.