diff --git a/Gemfile b/Gemfile index 5edacf85..0473c2c0 100644 --- a/Gemfile +++ b/Gemfile @@ -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' diff --git a/Gemfile.lock b/Gemfile.lock index a0f7cb73..4988cb69 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -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 diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 60d8acd8..5c568870 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -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 diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 95afc887..4818da9b 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -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) diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb new file mode 100644 index 00000000..de6d1910 --- /dev/null +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -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 diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index f0f0028c..68cc3a12 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -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 diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 00000000..f899f160 --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -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 diff --git a/app/models/submitter.rb b/app/models/submitter.rb index 29d55710..35c1a3e6 100644 --- a/app/models/submitter.rb +++ b/app/models/submitter.rb @@ -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 diff --git a/app/models/template.rb b/app/models/template.rb index e211488e..97db25d3 100644 --- a/app/models/template.rb +++ b/app/models/template.rb @@ -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 diff --git a/app/models/user.rb b/app/models/user.rb index 8f4ce25e..20697d0c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -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' diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index 3d722106..881b82c8 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -1,6 +1,6 @@