diff --git a/app/controllers/logos_controller.rb b/app/controllers/logos_controller.rb
new file mode 100644
index 00000000..4a26a1b8
--- /dev/null
+++ b/app/controllers/logos_controller.rb
@@ -0,0 +1,25 @@
+class LogosController < ApplicationController
+ def create
+ authorize! :update, current_account
+
+ current_account.logo.attach(logo_params[:logo])
+
+ redirect_back fallback_location: settings_personalization_path,
+ notice: I18n.t('settings_have_been_saved')
+ end
+
+ def destroy
+ authorize! :update, current_account
+
+ current_account.logo.purge
+
+ redirect_back fallback_location: settings_personalization_path,
+ notice: I18n.t('settings_have_been_saved')
+ end
+
+ private
+
+ def logo_params
+ params.require(:account_logo).permit(:logo)
+ end
+end
diff --git a/app/models/account.rb b/app/models/account.rb
index bc6471bf..f6a07904 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -50,6 +50,7 @@ class Account < ApplicationRecord
has_many :testing_accounts, through: :account_testing_accounts, source: :linked_account
has_many :active_users, -> { active }, dependent: :destroy,
inverse_of: :account, class_name: 'User'
+ has_one_attached :logo
attribute :timezone, :string, default: 'UTC'
attribute :locale, :string, default: 'en-US'
diff --git a/app/views/accounts/_logo.html.erb b/app/views/accounts/_logo.html.erb
new file mode 100644
index 00000000..66189439
--- /dev/null
+++ b/app/views/accounts/_logo.html.erb
@@ -0,0 +1,4 @@
+<%= image_tag url_for(current_account.logo),
+ class: "h-10 object-contain",
+ alt: current_account.name.presence || "Company Logo" %>
+<%= current_account.name %>
diff --git a/app/views/personalization_settings/_logo_dropzone.html.erb b/app/views/personalization_settings/_logo_dropzone.html.erb
new file mode 100644
index 00000000..4993c109
--- /dev/null
+++ b/app/views/personalization_settings/_logo_dropzone.html.erb
@@ -0,0 +1,58 @@
+<%= form_for '', url: account_logo_path, id: form_id = SecureRandom.uuid, method: :post,
+ class: 'mt-8 block', html: { enctype: 'multipart/form-data' } do %>
+
+
+
+
+
+
+
+
+<% end %>
diff --git a/app/views/personalization_settings/_logo_form.html.erb b/app/views/personalization_settings/_logo_form.html.erb
index fc6f3ac7..4041720b 100644
--- a/app/views/personalization_settings/_logo_form.html.erb
+++ b/app/views/personalization_settings/_logo_form.html.erb
@@ -1 +1,5 @@
-<%= render 'logo_placeholder' %>
+<% if !Docuseal.multitenant? || can?(:manage, :personalization_advanced) %>
+ <%= render 'logo_upload_form' %>
+<% else %>
+ <%= render 'logo_placeholder' %>
+<% end %>
\ No newline at end of file
diff --git a/app/views/personalization_settings/_logo_upload_form.html.erb b/app/views/personalization_settings/_logo_upload_form.html.erb
new file mode 100644
index 00000000..ff9a37ef
--- /dev/null
+++ b/app/views/personalization_settings/_logo_upload_form.html.erb
@@ -0,0 +1,27 @@
+
+
+
+ <% if current_account.logo.attached? %>
+ <%= image_tag url_for(current_account.logo),
+ class: "max-h-16 max-w-full object-contain" %>
+ <% else %>
+
+ <%= svg_icon('photo', class: 'w-6 h-6 mb-1') %>
+ No logo
+
+ <% end %>
+
+ <% if current_account.logo.attached? %>
+ <%= button_to account_logo_path,
+ method: :delete,
+ class: "btn btn-outline btn-error btn-sm normal-case",
+ form_class: "inline-block" do %>
+ <%= svg_icon('trash', class: 'w-4 h-4 mr-1') %>
+
<%= t("remove_logo") %>
+ <% end %>
+ <% end %>
+
+
+
+ <%= render 'logo_dropzone' %>
+
diff --git a/app/views/shared/_title.html.erb b/app/views/shared/_title.html.erb
index 9830a7ca..87cc9178 100644
--- a/app/views/shared/_title.html.erb
+++ b/app/views/shared/_title.html.erb
@@ -1,2 +1,6 @@
-<%= render 'shared/logo' %>
-DocuSeal
+<% if current_account&.logo&.attached? %>
+ <%= render 'accounts/logo' %>
+<% else %>
+ <%= render 'shared/logo' %>
+ DocuSeal
+<% end %>
diff --git a/config/locales/i18n.yml b/config/locales/i18n.yml
index da006683..3fab4756 100644
--- a/config/locales/i18n.yml
+++ b/config/locales/i18n.yml
@@ -322,6 +322,7 @@ en: &en
button_title: Button title
button_url: Button URL
upload_logo: Upload Logo
+ remove_logo: Remove Logo
show_confetti_on_successful_completion: Show confetti on successful completion
attach_audit_log_pdf: Attach audit log PDF
attach_documents: Attach documents
diff --git a/config/routes.rb b/config/routes.rb
index f9d3ae38..9dd29e03 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -2,6 +2,7 @@
Rails.application.routes.draw do
mount LetterOpenerWeb::Engine, at: '/letter_opener' if Rails.env.development?
+ mount ActiveStorage::Engine => "/rails/active_storage"
if !Docuseal.multitenant? && defined?(Sidekiq::Web)
authenticated :user, ->(u) { u.sidekiq? } do
@@ -50,6 +51,7 @@ Rails.application.routes.draw do
end
end
+ resource :account_logo, controller: 'logos', only: [:create, :destroy]
resources :verify_pdf_signature, only: %i[create]
resource :mfa_setup, only: %i[show new edit create destroy], controller: 'mfa_setup'
resources :account_configs, only: %i[create destroy]