mirror of
https://github.com/docusealco/docuseal
synced 2026-11-04 14:42:32 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ef1c309e0 | ||
|
|
a32dcc0dc5 | ||
|
|
16a2fde4b7 | ||
|
|
7856f7a134 | ||
|
|
c545924fe9 | ||
|
|
b1510bb88c | ||
|
|
31d2024ce5 | ||
|
|
23c49f8706 | ||
|
|
62eb0cda6b | ||
|
|
9f48c6e625 | ||
|
|
83ce401cf2 | ||
|
|
541b025ad0 | ||
|
|
5fd018df46 |
No files matched your search
@@ -21,7 +21,9 @@ gem 'jwt'
|
||||
gem 'lograge'
|
||||
gem 'mysql2', require: false
|
||||
gem 'oj'
|
||||
gem 'omniauth-github'
|
||||
gem 'omniauth-google-oauth2'
|
||||
gem 'omniauth-microsoft-office365'
|
||||
gem 'omniauth-rails_csrf_protection'
|
||||
gem 'pagy'
|
||||
gem 'pdf-reader'
|
||||
|
||||
@@ -328,11 +328,17 @@ GEM
|
||||
hashie (>= 3.4.6)
|
||||
rack (>= 2.2.3)
|
||||
rack-protection
|
||||
omniauth-github (2.0.1)
|
||||
omniauth (~> 2.0)
|
||||
omniauth-oauth2 (~> 1.8)
|
||||
omniauth-google-oauth2 (1.1.1)
|
||||
jwt (>= 2.0)
|
||||
oauth2 (~> 2.0.6)
|
||||
omniauth (~> 2.0)
|
||||
omniauth-oauth2 (~> 1.8.0)
|
||||
omniauth-microsoft-office365 (0.0.8)
|
||||
omniauth
|
||||
omniauth-oauth2
|
||||
omniauth-oauth2 (1.8.0)
|
||||
oauth2 (>= 1.4, < 3)
|
||||
omniauth (~> 2.0)
|
||||
@@ -589,7 +595,9 @@ DEPENDENCIES
|
||||
lograge
|
||||
mysql2
|
||||
oj
|
||||
omniauth-github
|
||||
omniauth-google-oauth2
|
||||
omniauth-microsoft-office365
|
||||
omniauth-rails_csrf_protection
|
||||
pagy
|
||||
pdf-reader
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
class TemplatesCloneController < ApiBaseController
|
||||
load_and_authorize_resource :template
|
||||
|
||||
def create
|
||||
authorize!(:manage, @template)
|
||||
|
||||
template = current_account.templates.new(source: :api)
|
||||
|
||||
template.application_key = params[:application_key]
|
||||
template.name = params[:name] || "#{@template.name} (Clone)"
|
||||
template.account = @template.account
|
||||
template.author = current_user
|
||||
template.assign_attributes(@template.slice(:folder_id, :fields, :schema, :submitters))
|
||||
|
||||
if params[:folder_name].present?
|
||||
template.folder = TemplateFolders.find_or_create_by_name(current_user, params[:folder_name])
|
||||
end
|
||||
|
||||
template.save!
|
||||
|
||||
Templates::CloneAttachments.call(template:, original_template: @template)
|
||||
|
||||
render json: template.as_json(serialize_params)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def serialize_params
|
||||
{
|
||||
include: { author: { only: %i[id email first_name last_name] },
|
||||
documents: { only: %i[id uuid], methods: %i[url filename] } }
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -12,7 +12,7 @@ class ErrorsController < ActionController::Base
|
||||
].freeze
|
||||
|
||||
def show
|
||||
if request.original_fullpath.in?(ENTERPRISE_PATHS)
|
||||
if request.original_fullpath.in?(ENTERPRISE_PATHS) && error_status_code == 404
|
||||
return render json: { status: 404, message: ENTERPRISE_FEATURE_MESSAGE }, status: :not_found
|
||||
end
|
||||
|
||||
|
||||
@@ -38,6 +38,10 @@ class SubmitFormController < ApplicationController
|
||||
def update
|
||||
submitter = Submitter.find_by!(slug: params[:slug])
|
||||
|
||||
if submitter.completed_at?
|
||||
return render json: { error: 'Form has been completed already.' }, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
Submitters::SubmitValues.call(submitter, params, request)
|
||||
|
||||
head :ok
|
||||
|
||||
@@ -14,7 +14,7 @@ class TimestampServerController < ApplicationController
|
||||
else
|
||||
redirect_back fallback_location: settings_notifications_path, alert: 'Unable to save'
|
||||
end
|
||||
rescue HexaPDF::Error, SocketError, Submissions::TimestampHandler::TimestampError
|
||||
rescue HexaPDF::Error, SocketError, Submissions::TimestampHandler::TimestampError, OpenSSL::Timestamp::TimestampError
|
||||
redirect_back fallback_location: settings_notifications_path, alert: 'Invalid Timeserver'
|
||||
end
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ class SubmissionEvent < ApplicationRecord
|
||||
send_email: 'send_email',
|
||||
send_reminder_email: 'send_reminder_email',
|
||||
send_sms: 'send_sms',
|
||||
send_2fa_sms: 'send_2fa_sms',
|
||||
open_email: 'open_email',
|
||||
click_email: 'click_email',
|
||||
click_sms: 'click_sms',
|
||||
|
||||
+5
-2
@@ -55,10 +55,13 @@ class User < ApplicationRecord
|
||||
has_many :template_folders, dependent: :destroy, foreign_key: :author_id, inverse_of: :author
|
||||
has_many :user_configs, dependent: :destroy
|
||||
has_many :encrypted_configs, dependent: :destroy, class_name: 'EncryptedUserConfig'
|
||||
has_many :email_messages, dependent: :destroy
|
||||
has_many :email_messages, dependent: :destroy, foreign_key: :author_id, inverse_of: :author
|
||||
|
||||
devise :two_factor_authenticatable, :recoverable, :rememberable, :validatable, :trackable
|
||||
devise :registerable, :omniauthable, omniauth_providers: [:google_oauth2] if Docuseal.multitenant?
|
||||
|
||||
if Docuseal.multitenant?
|
||||
devise :registerable, :omniauthable, omniauth_providers: %i[google_oauth2 microsoft_office365 github]
|
||||
end
|
||||
|
||||
attribute :role, :string, default: ADMIN_ROLE
|
||||
attribute :uuid, :string, default: -> { SecureRandom.uuid }
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<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' %>
|
||||
<%= f.email_field :email, autofocus: true, autocomplete: 'email', class: 'base-input', placeholder: 'Enter email to continue' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
@@ -16,11 +16,18 @@
|
||||
</div>
|
||||
<% end %>
|
||||
<% if devise_mapping.omniauthable? %>
|
||||
<%= form_for '', url: omniauth_authorize_path(resource_name, :google_oauth2), data: { turbo: false }, method: :post do |f| %>
|
||||
<set-timezone data-input-id="state" data-params="true"></set-timezone>
|
||||
<%= hidden_field_tag :state, { redir: params[:redir].to_s }.compact_blank.to_query %>
|
||||
<%= f.button button_title(title: 'Sign up with Google', icon: svg_icon('brand_google', class: 'w-6 h-6')), class: 'white-button w-full mt-4' %>
|
||||
<% end %>
|
||||
<div class="space-y-4">
|
||||
<%= form_for '', url: omniauth_authorize_path(resource_name, :google_oauth2), data: { turbo: false }, method: :post do |f| %>
|
||||
<set-timezone data-input-id="state" data-params="true"></set-timezone>
|
||||
<%= hidden_field_tag :state, { redir: params[:redir].to_s }.compact_blank.to_query %>
|
||||
<%= f.button button_title(title: 'Sign up with Google', icon: svg_icon('brand_google', class: 'w-6 h-6')), class: 'white-button w-full mt-4' %>
|
||||
<% end %>
|
||||
<%= form_for '', url: omniauth_authorize_path(resource_name, :microsoft_office365), data: { turbo: false }, method: :post do |f| %>
|
||||
<set-timezone data-input-id="state_microsoft" data-params="true"></set-timezone>
|
||||
<%= hidden_field_tag :state, { redir: params[:redir].to_s }.compact_blank.to_query, id: 'state_microsoft' %>
|
||||
<%= f.button button_title(title: 'Sign up with Microsoft', icon: svg_icon('brand_microsoft', class: 'w-6 h-6')), class: 'white-button w-full' %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= render 'devise/shared/links' %>
|
||||
</div>
|
||||
@@ -20,11 +20,18 @@
|
||||
</div>
|
||||
<% end %>
|
||||
<% if devise_mapping.omniauthable? %>
|
||||
<%= form_for '', url: omniauth_authorize_path(resource_name, :google_oauth2), data: { turbo: false }, method: :post do |f| %>
|
||||
<set-timezone data-input-id="state" data-params="true"></set-timezone>
|
||||
<%= hidden_field_tag :state, { redir: params[:redir].to_s }.compact_blank.to_query %>
|
||||
<%= f.button button_title(title: 'Sign in with Google', icon: svg_icon('brand_google', class: 'w-6 h-6')), class: 'white-button w-full mt-4' %>
|
||||
<% end %>
|
||||
<div class="space-y-4">
|
||||
<%= form_for '', url: omniauth_authorize_path(resource_name, :google_oauth2), data: { turbo: false }, method: :post do |f| %>
|
||||
<set-timezone data-input-id="state" data-params="true"></set-timezone>
|
||||
<%= hidden_field_tag :state, { redir: params[:redir].to_s }.compact_blank.to_query %>
|
||||
<%= f.button button_title(title: 'Sign in with Google', icon: svg_icon('brand_google', class: 'w-6 h-6')), class: 'white-button w-full mt-4' %>
|
||||
<% end %>
|
||||
<%= form_for '', url: omniauth_authorize_path(resource_name, :microsoft_office365), data: { turbo: false }, method: :post do |f| %>
|
||||
<set-timezone data-input-id="state_microsoft" data-params="true"></set-timezone>
|
||||
<%= hidden_field_tag :state, { redir: params[:redir].to_s }.compact_blank.to_query, id: 'state_microsoft' %>
|
||||
<%= f.button button_title(title: 'Sign in with Microsoft', icon: svg_icon('brand_microsoft', class: 'w-6 h-6')), class: 'white-button w-full' %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= render 'devise/shared/links' %>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" x="0px" y="0px" width="100" height="100" viewBox="0 0 48 48">
|
||||
<path fill="#ff5722" d="M6 6H22V22H6z" transform="rotate(-180 14 14)"></path><path fill="#4caf50" d="M26 6H42V22H26z" transform="rotate(-180 34 14)"></path><path fill="#ffc107" d="M26 26H42V42H26z" transform="rotate(-180 34 34)"></path><path fill="#03a9f4" d="M6 26H22V42H6z" transform="rotate(-180 14 34)"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 463 B |
@@ -14,6 +14,7 @@ Devise.otp_allowed_drift = 60.seconds
|
||||
#
|
||||
# Use this hook to configure devise mailer, warden hooks and so forth.
|
||||
# Many of these configuration options can be set straight in your model.
|
||||
# rubocop:disable Metrics/BlockLength
|
||||
Devise.setup do |config|
|
||||
config.warden do |manager|
|
||||
manager.default_strategies(scope: :user).unshift(:two_factor_authenticatable)
|
||||
@@ -277,6 +278,12 @@ Devise.setup do |config|
|
||||
# Add a new OmniAuth provider. Check the wiki for more information on setting
|
||||
# up on your models and hooks.
|
||||
config.omniauth :google_oauth2, ENV.fetch('GOOGLE_CLIENT_ID', nil), ENV.fetch('GOOGLE_CLIENT_SECRET', nil), {}
|
||||
config.omniauth :microsoft_office365, ENV.fetch('OFFICE365_CLIENT_ID', nil),
|
||||
ENV.fetch('OFFICE365_CLIENT_SECRET', nil), {}
|
||||
|
||||
if ENV['GITHUB_CLIENT_ID']
|
||||
config.omniauth :github, ENV.fetch('GITHUB_CLIENT_ID', nil), ENV.fetch('GITHUB_CLIENT_SECRET', nil), {}
|
||||
end
|
||||
|
||||
# ==> Warden configuration
|
||||
# If you want to use other strategies, that are not supported by Devise, or
|
||||
@@ -316,3 +323,4 @@ Devise.setup do |config|
|
||||
# changed. Defaults to true, so a user is signed in automatically after changing a password.
|
||||
# config.sign_in_after_change_password = true
|
||||
end
|
||||
# rubocop:enable Metrics/BlockLength
|
||||
@@ -42,6 +42,7 @@ Rails.application.routes.draw do
|
||||
end
|
||||
end
|
||||
resources :templates, only: %i[update show index destroy] do
|
||||
resources :clone, only: %i[create], controller: 'templates_clone'
|
||||
resources :submissions, only: %i[index create]
|
||||
resources :documents, only: %i[create], controller: 'templates_documents'
|
||||
end
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ aws_s3:
|
||||
|
||||
google:
|
||||
service: GCS
|
||||
credentials: <%= JSON.parse(ENV['GCS_CREDENTIALS'] || '{}') %>
|
||||
credentials: <%= ENV['GCS_CREDENTIALS'] || '{}' %>
|
||||
project: <%= ENV['GCS_PROJECT'] %>
|
||||
bucket: <%= ENV['GCS_BUCKET'] %>
|
||||
public: <%= ENV['ACTIVE_STORAGE_PUBLIC'] == 'true' %>
|
||||
|
||||
+8
-1
@@ -75,7 +75,14 @@ module Accounts
|
||||
if Docuseal.multitenant?
|
||||
Docuseal::TIMESERVER_URL
|
||||
else
|
||||
EncryptedConfig.find_by(account:, key: EncryptedConfig::TIMESTAMP_SERVER_URL_KEY)&.value
|
||||
url = EncryptedConfig.find_by(account:, key: EncryptedConfig::TIMESTAMP_SERVER_URL_KEY)&.value
|
||||
|
||||
unless Docuseal.multitenant?
|
||||
url ||=
|
||||
Account.order(:id).first.encrypted_configs.find_by(key: EncryptedConfig::TIMESTAMP_SERVER_URL_KEY)&.value
|
||||
end
|
||||
|
||||
url
|
||||
end.presence
|
||||
end
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ module SubmissionEvents
|
||||
send_email: 'Email sent',
|
||||
send_reminder_email: 'Reminder email sent',
|
||||
send_sms: 'SMS sent',
|
||||
send_2fa_sms: 'Verification SMS sent',
|
||||
open_email: 'Email opened',
|
||||
click_email: 'Email link clicked',
|
||||
click_sms: 'SMS link clicked',
|
||||
|
||||
@@ -19,11 +19,7 @@ module Submissions
|
||||
|
||||
INFO_CREATOR = "#{Docuseal.product_name} (#{Docuseal::PRODUCT_URL})".freeze
|
||||
SIGN_REASON = 'Signed with DocuSeal.co'
|
||||
VERIFIED_TEXT = if Docuseal.multitenant?
|
||||
'Verified by DocuSeal'
|
||||
else
|
||||
'Verified'
|
||||
end
|
||||
VERIFIED_TEXT = 'Verified'
|
||||
UNVERIFIED_TEXT = 'Unverified'
|
||||
|
||||
module_function
|
||||
|
||||
@@ -43,7 +43,9 @@ module Submissions
|
||||
page.rotate(0, flatten: true) if page[:Rotate] != 0
|
||||
|
||||
page[:Annots] ||= []
|
||||
page[:Annots] = page[:Annots].reject { |e| e[:A] && e[:A][:URI].to_s.starts_with?('file:///docuseal_field') }
|
||||
page[:Annots] = page[:Annots].reject do |e|
|
||||
e.present? && e[:A] && e[:A][:URI].to_s.starts_with?('file:///docuseal_field')
|
||||
end
|
||||
|
||||
width = page.box.width
|
||||
height = page.box.height
|
||||
@@ -67,7 +69,7 @@ module Submissions
|
||||
scale = [(area['w'] * width) / image.width,
|
||||
(area['h'] * height) / image.height].min
|
||||
|
||||
io = StringIO.new(image.resize([scale * 4, 1].min).write_to_buffer('.png'))
|
||||
io = StringIO.new(image.resize([scale * 4, 1].select(&:positive?).min).write_to_buffer('.png'))
|
||||
|
||||
canvas.image(
|
||||
io,
|
||||
|
||||
+13
-4
@@ -4,12 +4,21 @@ module Users
|
||||
module_function
|
||||
|
||||
def from_omniauth(oauth)
|
||||
user = User.find_by(email: oauth.info.email)
|
||||
user = User.find_by(email: oauth.info.email.to_s.downcase)
|
||||
|
||||
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)
|
||||
case oauth['provider'].to_s
|
||||
when 'google_oauth2'
|
||||
User.new(email: oauth.info.email,
|
||||
first_name: oauth.extra.id_info.given_name,
|
||||
last_name: oauth.extra.id_info.family_name)
|
||||
when 'microsoft_office365'
|
||||
User.new(email: oauth.info.email,
|
||||
first_name: oauth.info.first_name,
|
||||
last_name: oauth.info.last_name)
|
||||
when 'github'
|
||||
User.new(email: oauth.info.email, first_name: oauth.info.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user