improve registration and add oauth

pull/105/head
Alex Turchyn 2 years ago
parent f7ef99a624
commit 6f3fe1dd7b

@ -16,6 +16,8 @@ gem 'image_processing'
gem 'lograge'
gem 'mysql2', require: false
gem 'oj'
gem 'omniauth-google-oauth2'
gem 'omniauth-rails_csrf_protection'
gem 'pagy'
gem 'pg', require: false
gem 'premailer-rails'

@ -232,6 +232,7 @@ GEM
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
hashdiff (1.0.1)
hashie (5.0.0)
hexapdf (0.32.2)
cmdparse (~> 3.0, >= 3.0.3)
geom2d (~> 0.3)
@ -282,6 +283,7 @@ GEM
minitest (5.18.1)
msgpack (1.7.1)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.3.0)
mysql2 (0.5.5)
net-http-persistent (4.0.2)
@ -298,7 +300,29 @@ GEM
nio4r (2.5.9)
nokogiri (1.15.2-arm64-darwin)
racc (~> 1.4)
oauth2 (2.0.9)
faraday (>= 0.17.3, < 3.0)
jwt (>= 1.0, < 3.0)
multi_xml (~> 0.5)
rack (>= 1.2, < 4)
snaky_hash (~> 2.0)
version_gem (~> 1.1)
oj (3.15.0)
omniauth (2.1.1)
hashie (>= 3.4.6)
rack (>= 2.2.3)
rack-protection
omniauth-google-oauth2 (1.1.1)
jwt (>= 2.0)
oauth2 (~> 2.0.6)
omniauth (~> 2.0)
omniauth-oauth2 (~> 1.8.0)
omniauth-oauth2 (1.8.0)
oauth2 (>= 1.4, < 3)
omniauth (~> 2.0)
omniauth-rails_csrf_protection (1.0.1)
actionpack (>= 4.2)
omniauth (~> 2.0)
openssl (3.1.0)
orm_adapter (0.5.0)
os (1.1.4)
@ -326,6 +350,8 @@ GEM
nio4r (~> 2.0)
racc (1.7.1)
rack (2.2.7)
rack-protection (3.0.6)
rack
rack-proxy (0.7.6)
rack
rack-test (2.1.0)
@ -444,6 +470,9 @@ GEM
simplecov-html (0.12.3)
simplecov_json_formatter (0.1.4)
smart_properties (1.17.0)
snaky_hash (2.0.1)
hashie
version_gem (~> 1.1, >= 1.1.1)
sqlite3 (1.5.4)
mini_portile2 (~> 2.8.0)
strip_attributes (1.13.0)
@ -462,6 +491,7 @@ GEM
uber (0.1.0)
unicode-display_width (2.4.2)
uniform_notifier (1.16.0)
version_gem (1.1.3)
warden (1.2.9)
rack (>= 2.0.9)
web-console (4.2.0)
@ -507,6 +537,8 @@ DEPENDENCIES
lograge
mysql2
oj
omniauth-google-oauth2
omniauth-rails_csrf_protection
pagy
pg
premailer-rails

@ -40,6 +40,8 @@ class AccountsController < ApplicationController
end
def app_url_params
return {} if params[:encrypted_config].blank?
params.require(:encrypted_config).permit(:value)
end
end

@ -4,6 +4,7 @@ class DashboardController < ApplicationController
skip_before_action :authenticate_user!, only: %i[index]
def index
return redirect_to Docuseal::PRODUCT_URL, allow_other_host: true if Docuseal.multitenant? && !signed_in?
return render 'pages/landing' unless signed_in?
templates = current_account.templates.active.preload(:author).order(id: :desc)

@ -0,0 +1,16 @@
# frozen_string_literal: true
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
@user = Users.from_omniauth(request.env['omniauth.auth'])
if @user.persisted?
flash[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: 'Google')
sign_in_and_redirect @user, event: :authentication
else
redirect_to new_registration_path(oauth_callback: true, user: @user.slice(:email, :first_name, :last_name)),
notice: 'Please complete registration with Google auth'
end
end
end

@ -1,6 +1,16 @@
# frozen_string_literal: true
class RegistrationsController < Devise::RegistrationsController
prepend_before_action :require_no_authentication, only: [:show]
def show; end
def create
super
Accounts.create_default_template(resource.account) if resource.account.persisted?
end
private
def build_resource(_hash = {})
@ -8,17 +18,21 @@ class RegistrationsController < Devise::RegistrationsController
account.timezone = Accounts.normalize_timezone(account.timezone)
self.resource = account.users.new(user_params)
account.name ||= "#{resource.full_name}'s Company" if params[:action] == 'create'
end
def user_params
return {} if params[:user].blank?
params.require(:user).permit(:first_name, :last_name, :email, :password)
params.require(:user).permit(:first_name, :last_name, :email, :password).compact_blank.tap do |attrs|
attrs[:password] ||= SecureRandom.hex if params[:action] == 'create'
end
end
def account_params
return {} if params[:account].blank?
params.require(:account).permit(:name, :timezone)
params.require(:account).permit(:name, :timezone).compact_blank
end
end

@ -0,0 +1,12 @@
# frozen_string_literal: true
class SessionsController < Devise::SessionsController
def create
if Docuseal.multitenant? && !User.exists?(email: sign_in_params[:email])
return redirect_to new_registration_path(sign_up: true, user: sign_in_params.slice(:email)),
notice: 'Create a new account'
end
super
end
end

@ -32,7 +32,7 @@ class Submitter < ApplicationRecord
belongs_to :submission
attribute :values, :string, default: -> { {} }
attribute :slug, :string, default: -> { SecureRandom.base58(10) }
attribute :slug, :string, default: -> { SecureRandom.base58(14) }
serialize :values, JSON

@ -36,7 +36,7 @@ class Template < ApplicationRecord
attribute :fields, :string, default: -> { [] }
attribute :schema, :string, default: -> { [] }
attribute :submitters, :string, default: -> { [{ name: DEFAULT_SUBMITTER_NAME, uuid: SecureRandom.uuid }] }
attribute :slug, :string, default: -> { SecureRandom.base58(10) }
attribute :slug, :string, default: -> { SecureRandom.base58(14) }
serialize :fields, JSON
serialize :schema, JSON

@ -46,7 +46,7 @@ class User < ApplicationRecord
belongs_to :account
devise :database_authenticatable, :recoverable, :rememberable, :validatable, :trackable
devise :registerable if Docuseal.multitenant?
devise :registerable, :omniauthable, omniauth_providers: [:google_oauth2] if Docuseal.multitenant?
attribute :role, :string, default: 'admin'

@ -1,6 +1,6 @@
<div class="max-w-xl mx-auto px-2">
<h1 class="text-4xl font-bold text-center my-8">Sign up</h1>
<%= form_for('', as: resource_name, html: { class: 'space-y-6' }, url: registration_path) do |f| %>
<%= form_for('', as: resource_name, html: { class: 'space-y-6' }, url: new_registration_path) do |f| %>
<div class="space-y-2">
<%= render 'devise/shared/error_messages', resource: %>
<%= f.fields_for resource do |ff| %>
@ -16,7 +16,7 @@
</div>
<% end %>
<%= f.fields_for resource do |ff| %>
<div class="form-control">
<div class="form-control <%= 'hidden' if (params[:oauth_callback] || params[:sign_up]) && resource.email? %>">
<%= ff.label :email, class: 'label' %>
<%= ff.email_field :email, required: true, class: 'base-input' %>
</div>
@ -25,14 +25,14 @@
<set-timezone data-input-id="_account_timezone"></set-timezone>
<%= ff.hidden_field :timezone %>
<div class="form-control">
<%= ff.label :name, 'Company name', class: 'label' %>
<%= ff.text_field :name, required: true, class: 'base-input' %>
<%= ff.label :name, 'Company name (optional)', class: 'label' %>
<%= ff.text_field :name, class: 'base-input' %>
</div>
<% end %>
<%= f.fields_for resource do |ff| %>
<div class="form-control">
<div class="form-control <%= 'hidden' if params[:oauth_callback] %>">
<%= ff.label :password, class: 'label' %>
<%= ff.password_field :password, required: true, class: 'base-input' %>
<%= ff.password_field :password, required: !params[:oauth_callback], class: 'base-input' %>
</div>
<% end %>
</div>

@ -0,0 +1,18 @@
<div class="max-w-xl mx-auto px-2">
<h1 class="text-4xl font-bold text-center my-8">Sign up</h1>
<%= form_for(User.new, html: { class: 'space-y-6' }, url: new_registration_path, method: :get) do |f| %>
<div class="space-y-2">
<div class="form-control">
<%= f.label :email, class: 'label' %>
<%= f.email_field :email, autofocus: true, autocomplete: 'email', class: 'base-input' %>
</div>
</div>
<div class="form-control">
<%= f.button button_title(title: 'Sign up', disabled_with: 'Sign up'), name: 'sign_up', value: true, class: 'base-button' %>
</div>
<% end %>
<% if devise_mapping.omniauthable? %>
<%= button_to button_title(title: 'Sign up with Google', icon: svg_icon('brand_google', class: 'w-6 h-6')), omniauth_authorize_path(resource_name, :google_oauth2), class: 'white-button w-full mt-4', data: { turbo: false }, method: :post %>
<% end %>
<%= render 'devise/shared/links' %>
</div>

@ -23,5 +23,8 @@
<%= f.button button_title(title: 'Log In', disabled_with: 'Logging In'), class: 'base-button' %>
</div>
<% end %>
<% if devise_mapping.omniauthable? %>
<%= button_to button_title(title: 'Log in with Google', icon: svg_icon('brand_google', class: 'w-6 h-6')), omniauth_authorize_path(resource_name, :google_oauth2), class: 'white-button w-full mt-4', data: { turbo: false }, method: :post %>
<% end %>
<%= render 'devise/shared/links' %>
</div>

@ -3,7 +3,7 @@
<%= link_to 'Log in', new_session_path(resource_name), class: 'link link-hover' %>
<% end %>
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to 'Sign up', new_registration_path, class: 'link link-hover' %>
<%= link_to 'Sign up', registration_path, class: 'link link-hover' %>
<% end %>
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
<%= link_to 'Forgot your password?', new_password_path(resource_name), class: 'link link-hover' %>
@ -14,9 +14,4 @@
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
<%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name), class: 'link link-hover' %>
<% end %>
<%- if devise_mapping.omniauthable? %>
<%- resource_class.omniauth_providers.each do |provider| %>
<%= button_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), class: 'link link-hover', data: { turbo: false } %>
<% end %>
<% end %>
</div>

@ -0,0 +1,16 @@
<svg width="800" height="800" viewBox="-0.5 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>">
<g id="Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Color-" transform="translate(-401.000000, -860.000000)">
<g id="Google" transform="translate(401.000000, 860.000000)">
<path d="M9.82727273,24 C9.82727273,22.4757333 10.0804318,21.0144 10.5322727,19.6437333 L2.62345455,13.6042667 C1.08206818,16.7338667 0.213636364,20.2602667 0.213636364,24 C0.213636364,27.7365333 1.081,31.2608 2.62025,34.3882667 L10.5247955,28.3370667 C10.0772273,26.9728 9.82727273,25.5168 9.82727273,24" id="Fill-1" fill="#FBBC05">
</path>
<path d="M23.7136364,10.1333333 C27.025,10.1333333 30.0159091,11.3066667 32.3659091,13.2266667 L39.2022727,6.4 C35.0363636,2.77333333 29.6954545,0.533333333 23.7136364,0.533333333 C14.4268636,0.533333333 6.44540909,5.84426667 2.62345455,13.6042667 L10.5322727,19.6437333 C12.3545909,14.112 17.5491591,10.1333333 23.7136364,10.1333333" id="Fill-2" fill="#EB4335">
</path>
<path d="M23.7136364,37.8666667 C17.5491591,37.8666667 12.3545909,33.888 10.5322727,28.3562667 L2.62345455,34.3946667 C6.44540909,42.1557333 14.4268636,47.4666667 23.7136364,47.4666667 C29.4455,47.4666667 34.9177955,45.4314667 39.0249545,41.6181333 L31.5177727,35.8144 C29.3995682,37.1488 26.7323182,37.8666667 23.7136364,37.8666667" id="Fill-3" fill="#34A853">
</path>
<path d="M46.1454545,24 C46.1454545,22.6133333 45.9318182,21.12 45.6113636,19.7333333 L23.7136364,19.7333333 L23.7136364,28.8 L36.3181818,28.8 C35.6879545,31.8912 33.9724545,34.2677333 31.5177727,35.8144 L39.0249545,41.6181333 C43.3393409,37.6138667 46.1454545,31.6490667 46.1454545,24" id="Fill-4" fill="#4285F4">
</path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -29,8 +29,8 @@
<% end %>
</li>
<li>
<%= link_to destroy_user_session_path, data: { turbo_method: :delete } do %>
<%= svg_icon('logout', class: 'w-5 h-5 stroke-2') %>
<%= button_to destroy_user_session_path, method: :delete, data: { turbo: false } do %>
<%= svg_icon('logout', class: 'w-5 h-5 stroke-2 inline') %>
<span class="mr-1">Sign out</span>
<% end %>
</li>

@ -266,7 +266,7 @@ Devise.setup do |config|
# ==> OmniAuth
# Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks.
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
config.omniauth :google_oauth2, ENV.fetch('GOOGLE_CLIENT_ID', nil), ENV.fetch('GOOGLE_CLIENT_SECRET', nil), {}
# ==> Warden configuration
# If you want to use other strategies, that are not supported by Devise, or

@ -5,11 +5,18 @@ Rails.application.routes.draw do
root 'dashboard#index'
devise_for :users, path: '/', only: %i[sessions passwords]
devise_for :users,
path: '/', only: %i[sessions passwords omniauth_callbacks],
controllers: begin
options = { sessions: 'sessions' }
options[:omniauth_callbacks] = 'omniauth_callbacks' if Docuseal.multitenant?
options
end
devise_scope :user do
if Docuseal.multitenant?
resource :registration, only: %i[create], path: 'sign_up' do
resource :registration, only: %i[show], path: 'sign_up'
resource :registration, only: %i[create], path: 'new' do
get '' => :new, as: :new
end
end

@ -16,7 +16,7 @@ module Accounts
new_template = template.dup
new_template.account = new_account
new_template.slug = SecureRandom.base58(10)
new_template.slug = SecureRandom.base58(14)
new_template.save!
@ -28,6 +28,20 @@ module Accounts
new_account
end
def create_default_template(account)
template = Template.find(1)
new_template = Template.find(1).dup
new_template.account_id = account.id
new_template.slug = SecureRandom.base58(14)
new_template.save!
Templates::CloneAttachments.call(template: new_template, original_template: template)
new_template
end
def load_signing_certs(account)
certs =
if Docuseal.multitenant?

@ -0,0 +1,15 @@
# frozen_string_literal: true
module Users
module_function
def from_omniauth(oauth)
user = User.find_by(email: oauth.info.email)
return user if user
User.new(email: oauth.info.email,
first_name: oauth.extra.id_info.given_name,
last_name: oauth.extra.id_info.family_name)
end
end
Loading…
Cancel
Save