feat: Unify user and super admin credentials (#3830)
Fixes: #3061, #3489
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
class AccountBuilder
|
||||
include CustomExceptions::Account
|
||||
pattr_initialize [:account_name!, :email!, :confirmed, :user, :user_full_name, :user_password]
|
||||
pattr_initialize [:account_name!, :email!, :confirmed, :user, :user_full_name, :user_password, :super_admin]
|
||||
|
||||
def perform
|
||||
if @user.nil?
|
||||
@@ -65,6 +65,7 @@ class AccountBuilder
|
||||
password: user_password,
|
||||
password_confirmation: user_password,
|
||||
name: @user_full_name)
|
||||
@user.type = 'SuperAdmin' if @super_admin
|
||||
@user.confirm if @confirmed
|
||||
@user.save!
|
||||
end
|
||||
|
||||
@@ -10,6 +10,7 @@ class Installation::OnboardingController < ApplicationController
|
||||
user_full_name: onboarding_params.dig(:user, :name),
|
||||
email: onboarding_params.dig(:user, :email),
|
||||
user_password: params.dig(:user, :password),
|
||||
super_admin: true,
|
||||
confirmed: true
|
||||
).perform
|
||||
rescue StandardError => e
|
||||
|
||||
@@ -8,7 +8,7 @@ class SuperAdmin::Devise::SessionsController < Devise::SessionsController
|
||||
def create
|
||||
redirect_to(super_admin_session_path, flash: { error: @error_message }) && return unless valid_credentials?
|
||||
|
||||
sign_in(@super_admin, scope: :super_admin)
|
||||
sign_in(:super_admin, @super_admin)
|
||||
flash.discard
|
||||
redirect_to super_admin_users_path
|
||||
end
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
class SuperAdmin::SuperAdminsController < SuperAdmin::ApplicationController
|
||||
# Overwrite any of the RESTful controller actions to implement custom behavior
|
||||
# For example, you may want to send an email after a foo is updated.
|
||||
#
|
||||
# def update
|
||||
# super
|
||||
# send_foo_updated_email(requested_resource)
|
||||
# end
|
||||
|
||||
# Override this method to specify custom lookup behavior.
|
||||
# This will be used to set the resource for the `show`, `edit`, and `update`
|
||||
# actions.
|
||||
#
|
||||
# def find_resource(param)
|
||||
# Foo.find_by!(slug: param)
|
||||
# end
|
||||
|
||||
# The result of this lookup will be available as `requested_resource`
|
||||
|
||||
# Override this if you have certain roles that require a subset
|
||||
# this will be used to set the records shown on the `index` action.
|
||||
#
|
||||
# def scoped_resource
|
||||
# if current_user.super_admin?
|
||||
# resource_class
|
||||
# else
|
||||
# resource_class.with_less_stuff
|
||||
# end
|
||||
# end
|
||||
|
||||
# Override `resource_params` if you want to transform the submitted
|
||||
# data before it's persisted. For example, the following would turn all
|
||||
# empty values into nil values. It uses other APIs such as `resource_class`
|
||||
# and `dashboard`:
|
||||
#
|
||||
# def resource_params
|
||||
# params.require(resource_class.model_name.param_key).
|
||||
# permit(dashboard.permitted_attributes).
|
||||
# transform_values { |value| value == "" ? nil : value }
|
||||
# end
|
||||
|
||||
# See https://administrate-prototype.herokuapp.com/customizing_controller_actions
|
||||
# for more information
|
||||
end
|
||||
@@ -33,12 +33,15 @@ class SuperAdmin::UsersController < SuperAdmin::ApplicationController
|
||||
# empty values into nil values. It uses other APIs such as `resource_class`
|
||||
# and `dashboard`:
|
||||
#
|
||||
# def resource_params
|
||||
# params.require(resource_class.model_name.param_key).
|
||||
# permit(dashboard.permitted_attributes).
|
||||
# transform_values { |value| value == "" ? nil : value }
|
||||
# end
|
||||
def resource_params
|
||||
permitted_params = super
|
||||
permitted_params.delete(:password) if permitted_params[:password].blank?
|
||||
permitted_params
|
||||
end
|
||||
|
||||
# See https://administrate-prototype.herokuapp.com/customizing_controller_actions
|
||||
# for more information
|
||||
def find_resource(param)
|
||||
super.becomes(User)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
require 'administrate/base_dashboard'
|
||||
|
||||
class SuperAdminDashboard < Administrate::BaseDashboard
|
||||
# ATTRIBUTE_TYPES
|
||||
# a hash that describes the type of each of the model's fields.
|
||||
#
|
||||
# Each different type represents an Administrate::Field object,
|
||||
# which determines how the attribute is displayed
|
||||
# on pages throughout the dashboard.
|
||||
ATTRIBUTE_TYPES = {
|
||||
id: Field::Number,
|
||||
email: Field::String,
|
||||
password: Field::Password,
|
||||
remember_created_at: Field::DateTime,
|
||||
sign_in_count: Field::Number,
|
||||
current_sign_in_at: Field::DateTime,
|
||||
last_sign_in_at: Field::DateTime,
|
||||
current_sign_in_ip: Field::String.with_options(searchable: false),
|
||||
last_sign_in_ip: Field::String.with_options(searchable: false),
|
||||
created_at: Field::DateTime,
|
||||
updated_at: Field::DateTime
|
||||
}.freeze
|
||||
|
||||
# COLLECTION_ATTRIBUTES
|
||||
# an array of attributes that will be displayed on the model's index page.
|
||||
#
|
||||
# By default, it's limited to four items to reduce clutter on index pages.
|
||||
# Feel free to add, remove, or rearrange items.
|
||||
COLLECTION_ATTRIBUTES = %i[
|
||||
id
|
||||
email
|
||||
].freeze
|
||||
|
||||
# SHOW_PAGE_ATTRIBUTES
|
||||
# an array of attributes that will be displayed on the model's show page.
|
||||
SHOW_PAGE_ATTRIBUTES = %i[
|
||||
id
|
||||
email
|
||||
remember_created_at
|
||||
sign_in_count
|
||||
current_sign_in_at
|
||||
last_sign_in_at
|
||||
current_sign_in_ip
|
||||
last_sign_in_ip
|
||||
created_at
|
||||
updated_at
|
||||
].freeze
|
||||
|
||||
# FORM_ATTRIBUTES
|
||||
# an array of attributes that will be displayed
|
||||
# on the model's form (`new` and `edit`) pages.
|
||||
FORM_ATTRIBUTES = %i[
|
||||
email
|
||||
password
|
||||
].freeze
|
||||
|
||||
# COLLECTION_FILTERS
|
||||
# a hash that defines filters that can be used while searching via the search
|
||||
# field of the dashboard.
|
||||
#
|
||||
# For example to add an option to search for open resources by typing "open:"
|
||||
# in the search field:
|
||||
#
|
||||
# COLLECTION_FILTERS = {
|
||||
# open: ->(resources) { resources.where(open: true) }
|
||||
# }.freeze
|
||||
COLLECTION_FILTERS = {}.freeze
|
||||
|
||||
# Overwrite this method to customize how super admins are displayed
|
||||
# across all pages of the admin dashboard.
|
||||
#
|
||||
# def display_resource(super_admin)
|
||||
# "SuperAdmin ##{super_admin.id}"
|
||||
# end
|
||||
end
|
||||
@@ -30,6 +30,7 @@ class UserDashboard < Administrate::BaseDashboard
|
||||
created_at: Field::DateTime,
|
||||
updated_at: Field::DateTime,
|
||||
pubsub_token: Field::String,
|
||||
type: Field::Select.with_options(collection: [nil, 'SuperAdmin']),
|
||||
accounts: CountField
|
||||
}.freeze
|
||||
|
||||
@@ -44,6 +45,7 @@ class UserDashboard < Administrate::BaseDashboard
|
||||
name
|
||||
email
|
||||
accounts
|
||||
type
|
||||
].freeze
|
||||
|
||||
# SHOW_PAGE_ATTRIBUTES
|
||||
@@ -53,10 +55,12 @@ class UserDashboard < Administrate::BaseDashboard
|
||||
avatar_url
|
||||
unconfirmed_email
|
||||
name
|
||||
type
|
||||
display_name
|
||||
email
|
||||
created_at
|
||||
updated_at
|
||||
confirmed_at
|
||||
account_users
|
||||
].freeze
|
||||
|
||||
@@ -68,6 +72,8 @@ class UserDashboard < Administrate::BaseDashboard
|
||||
display_name
|
||||
email
|
||||
password
|
||||
confirmed_at
|
||||
type
|
||||
].freeze
|
||||
|
||||
# COLLECTION_FILTERS
|
||||
|
||||
@@ -12,7 +12,7 @@ module Avatarable
|
||||
def avatar_url
|
||||
return url_for(avatar.representation(resize: '250x250')) if avatar.attached? && avatar.representable?
|
||||
|
||||
if [User, Contact].include?(self.class) && email.present?
|
||||
if [SuperAdmin, User, Contact].include?(self.class) && email.present?
|
||||
hash = Digest::MD5.hexdigest(email)
|
||||
return "https://www.gravatar.com/avatar/#{hash}?d=404"
|
||||
end
|
||||
|
||||
@@ -1,25 +1,41 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: super_admins
|
||||
# Table name: users
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# current_sign_in_at :datetime
|
||||
# current_sign_in_ip :inet
|
||||
# email :string default(""), not null
|
||||
# encrypted_password :string default(""), not null
|
||||
# last_sign_in_at :datetime
|
||||
# last_sign_in_ip :inet
|
||||
# remember_created_at :datetime
|
||||
# sign_in_count :integer default(0), not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# id :integer not null, primary key
|
||||
# availability :integer default("online")
|
||||
# confirmation_sent_at :datetime
|
||||
# confirmation_token :string
|
||||
# confirmed_at :datetime
|
||||
# current_sign_in_at :datetime
|
||||
# current_sign_in_ip :string
|
||||
# custom_attributes :jsonb
|
||||
# display_name :string
|
||||
# email :string
|
||||
# encrypted_password :string default(""), not null
|
||||
# last_sign_in_at :datetime
|
||||
# last_sign_in_ip :string
|
||||
# name :string not null
|
||||
# provider :string default("email"), not null
|
||||
# pubsub_token :string
|
||||
# remember_created_at :datetime
|
||||
# reset_password_sent_at :datetime
|
||||
# reset_password_token :string
|
||||
# sign_in_count :integer default(0), not null
|
||||
# tokens :json
|
||||
# type :string
|
||||
# ui_settings :jsonb
|
||||
# uid :string default(""), not null
|
||||
# unconfirmed_email :string
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_super_admins_on_email (email) UNIQUE
|
||||
# index_users_on_email (email)
|
||||
# index_users_on_pubsub_token (pubsub_token) UNIQUE
|
||||
# index_users_on_reset_password_token (reset_password_token) UNIQUE
|
||||
# index_users_on_uid_and_provider (uid,provider) UNIQUE
|
||||
#
|
||||
class SuperAdmin < ApplicationRecord
|
||||
# Include default devise modules. Others available are:
|
||||
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
|
||||
devise :database_authenticatable, :trackable, :rememberable, :validatable, :password_has_required_content
|
||||
class SuperAdmin < User
|
||||
end
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
# reset_password_token :string
|
||||
# sign_in_count :integer default(0), not null
|
||||
# tokens :json
|
||||
# type :string
|
||||
# ui_settings :jsonb
|
||||
# uid :string default(""), not null
|
||||
# unconfirmed_email :string
|
||||
|
||||
26
app/views/fields/belongs_to/_form.html.erb
Normal file
26
app/views/fields/belongs_to/_form.html.erb
Normal file
@@ -0,0 +1,26 @@
|
||||
<%#
|
||||
# BelongsTo Form Partial
|
||||
|
||||
This partial renders an input element for belongs_to relationships.
|
||||
By default, the input is a collection select box
|
||||
that displays all possible records to associate with.
|
||||
|
||||
## Local variables:
|
||||
|
||||
- `f`:
|
||||
A Rails form generator, used to help create the appropriate input fields.
|
||||
- `field`:
|
||||
An instance of [Administrate::Field::BelongsTo][1].
|
||||
Contains helper methods for displaying a collection select box.
|
||||
|
||||
[1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/BelongsTo
|
||||
%>
|
||||
|
||||
<div class="field-unit__label">
|
||||
<%= f.label field.permitted_attribute %>
|
||||
</div>
|
||||
<div class="field-unit__field">
|
||||
<%= f.select(field.permitted_attribute,
|
||||
options_for_select(field.associated_resource_options, field.selected_option),
|
||||
include_blank: field.include_blank_option) %>
|
||||
</div>
|
||||
32
app/views/fields/belongs_to/_index.html.erb
Normal file
32
app/views/fields/belongs_to/_index.html.erb
Normal file
@@ -0,0 +1,32 @@
|
||||
<%#
|
||||
# BelongsTo Index Partial
|
||||
|
||||
This partial renders a belongs_to relationship,
|
||||
to be displayed on a resource's index page.
|
||||
|
||||
By default, the relationship is rendered as a link to the associated object.
|
||||
|
||||
## Local variables:
|
||||
|
||||
- `field`:
|
||||
An instance of [Administrate::Field::BelongsTo][1].
|
||||
A wrapper around the belongs_to relationship pulled from the database.
|
||||
|
||||
[1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/BelongsTo
|
||||
%>
|
||||
|
||||
<% if field.data %>
|
||||
<% if field.data.is_a? User %>
|
||||
<%= link_to(
|
||||
field.display_associated_resource,
|
||||
super_admin_user_path(field.data),
|
||||
) %>
|
||||
<% elsif valid_action?(:show, field.associated_class) %>
|
||||
<%= link_to(
|
||||
field.display_associated_resource,
|
||||
[namespace, field.data],
|
||||
) %>
|
||||
<% else %>
|
||||
<%= field.display_associated_resource %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
27
app/views/fields/belongs_to/_show.html.erb
Normal file
27
app/views/fields/belongs_to/_show.html.erb
Normal file
@@ -0,0 +1,27 @@
|
||||
<%#
|
||||
# BelongsTo Show Partial
|
||||
|
||||
This partial renders a belongs_to relationship,
|
||||
to be displayed on a resource's show page.
|
||||
|
||||
By default, the relationship is rendered as a link to the associated object.
|
||||
|
||||
## Local variables:
|
||||
|
||||
- `field`:
|
||||
An instance of [Administrate::Field::BelongsTo][1].
|
||||
A wrapper around the belongs_to relationship pulled from the database.
|
||||
|
||||
[1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/BelongsTo
|
||||
%>
|
||||
|
||||
<% if field.data %>
|
||||
<% if valid_action?(:show, field.associated_class) %>
|
||||
<%= link_to(
|
||||
field.display_associated_resource,
|
||||
[namespace, field.data],
|
||||
) %>
|
||||
<% else %>
|
||||
<%= field.display_associated_resource %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
29
app/views/fields/polymorphic/_form.html.erb
Normal file
29
app/views/fields/polymorphic/_form.html.erb
Normal file
@@ -0,0 +1,29 @@
|
||||
<%#
|
||||
# Polymorphic Form Partial
|
||||
|
||||
This partial renders an input element for polymorphic relationships.
|
||||
|
||||
## Local variables:
|
||||
|
||||
- `f`:
|
||||
A Rails form generator, used to help create the appropriate input fields.
|
||||
- `field`:
|
||||
An instance of [Administrate::Field::Polymorphic][1].
|
||||
A wrapper around the polymorphic belongs_to relationship
|
||||
pulled from the database.
|
||||
|
||||
[1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/Polymorphic
|
||||
%>
|
||||
|
||||
<%= f.fields_for field.attribute do |pf| %>
|
||||
<div class="field-unit__label">
|
||||
<%= pf.label :value, field.name.humanize %>
|
||||
</div>
|
||||
|
||||
<div class="field-unit__field">
|
||||
<%= pf.hidden_field(:type, value: field.class.name) %>
|
||||
<%= pf.select(:value) do %>
|
||||
<%= grouped_options_for_select(field.associated_resource_grouped_options, field.selected_global_id, prompt: true) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
31
app/views/fields/polymorphic/_index.html.erb
Normal file
31
app/views/fields/polymorphic/_index.html.erb
Normal file
@@ -0,0 +1,31 @@
|
||||
<%#
|
||||
# Polymorphic Index Partial
|
||||
|
||||
This partial renders a polymorphic relationship,
|
||||
to be displayed on a resource's index page.
|
||||
|
||||
By default, the relationship is rendered as a link to the associated object.
|
||||
|
||||
## Local variables:
|
||||
|
||||
- `field`:
|
||||
An instance of [Administrate::Field::Polymorphic][1].
|
||||
A wrapper around the polymorphic belongs_to relationship
|
||||
pulled from the database.
|
||||
|
||||
[1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/Polymorphic
|
||||
%>
|
||||
|
||||
<% if field.data %>
|
||||
<% if field.data.is_a? User %>
|
||||
<%= link_to(
|
||||
"User ##{field.data.id}",
|
||||
super_admin_user_path(field.data)
|
||||
) %>
|
||||
<% else %>
|
||||
<%= link_to(
|
||||
field.display_associated_resource,
|
||||
[namespace, field.data]
|
||||
) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
28
app/views/fields/polymorphic/_show.html.erb
Normal file
28
app/views/fields/polymorphic/_show.html.erb
Normal file
@@ -0,0 +1,28 @@
|
||||
<%#
|
||||
# Polymorphic Show Partial
|
||||
|
||||
This partial renders a polymorphic relationship,
|
||||
to be displayed on a resource's show page.
|
||||
|
||||
By default, the relationship is rendered as a link to the associated object.
|
||||
|
||||
## Local variables:
|
||||
|
||||
- `field`:
|
||||
An instance of [Administrate::Field::Polymorphic][1].
|
||||
A wrapper around the polymorphic belongs_to relationship
|
||||
pulled from the database.
|
||||
|
||||
[1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/Polymorphic
|
||||
%>
|
||||
|
||||
<% if field.data %>
|
||||
<% if valid_action?(:show, field.data.class) %>
|
||||
<%= link_to(
|
||||
field.display_associated_resource,
|
||||
[namespace, field.data],
|
||||
) %>
|
||||
<% else %>
|
||||
<%= field.display_associated_resource %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
@@ -56,9 +56,14 @@ as defined by the routes in the `admin/` namespace
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="logout">
|
||||
|
||||
<li class="navigation__link">
|
||||
<i class="ion ion-log-out"></i>
|
||||
<%= link_to "Logout", super_admin_logout_url %>
|
||||
</li>
|
||||
<li class="navigation__link">
|
||||
<i class="ion ion-android-contacts"></i>
|
||||
<%= link_to "Agent Dashboard", '/' %>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -57,13 +57,13 @@ to display a collection of resources in an HTML table.
|
||||
<tr class="js-table-row"
|
||||
tabindex="0"
|
||||
<% if valid_action? :show, collection_presenter.resource_name %>
|
||||
<%= %(role=link data-url=#{polymorphic_path([namespace, resource])}) %>
|
||||
<%= %(role=link data-url=#{polymorphic_path([namespace, resource.becomes(User)])}) %>
|
||||
<% end %>
|
||||
>
|
||||
<% collection_presenter.attributes_for(resource).each do |attribute| %>
|
||||
<td class="cell-data cell-data--<%= attribute.html_class %>">
|
||||
<% if show_action? :show, resource -%>
|
||||
<a href="<%= polymorphic_path([namespace, resource]) -%>"
|
||||
<a href="<%= polymorphic_path([namespace, resource.becomes(User)]) -%>"
|
||||
class="action-show"
|
||||
>
|
||||
<%= render_field attribute %>
|
||||
@@ -75,7 +75,7 @@ to display a collection of resources in an HTML table.
|
||||
<% if valid_action? :edit, collection_presenter.resource_name %>
|
||||
<td><%= link_to(
|
||||
t("administrate.actions.edit"),
|
||||
[:edit, namespace, resource],
|
||||
[:edit, namespace, resource.becomes(User)],
|
||||
class: "action-edit",
|
||||
) if show_action? :edit, resource%></td>
|
||||
<% end %>
|
||||
@@ -83,7 +83,7 @@ to display a collection of resources in an HTML table.
|
||||
<% if valid_action? :destroy, collection_presenter.resource_name %>
|
||||
<td><%= link_to(
|
||||
t("administrate.actions.destroy"),
|
||||
[namespace, resource],
|
||||
[namespace, resource.becomes(User)],
|
||||
class: "text-color-red",
|
||||
method: :delete,
|
||||
data: { confirm: t("administrate.actions.confirm") }
|
||||
|
||||
Reference in New Issue
Block a user