feat: Unify user and super admin credentials (#3830)
Fixes: #3061, #3489
This commit is contained in:
parent
23965fbaa3
commit
34e8ad9dc5
34 changed files with 303 additions and 233 deletions
|
@ -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") }
|
||||
|
|
|
@ -72,6 +72,15 @@ class Rack::Attack
|
|||
end
|
||||
end
|
||||
|
||||
throttle('super_admin_login/email', limit: 20, period: 5.minutes) do |req|
|
||||
if req.path == '/super_admin/sign_in' && req.post?
|
||||
# NOTE: This line used to throw ArgumentError /rails/action_mailbox/sendgrid/inbound_emails : invalid byte sequence in UTF-8
|
||||
# Hence placed in the if block
|
||||
email = req.params['email'].presence || ActionDispatch::Request.new(req.env).params['email'].presence
|
||||
email.to_s.downcase.gsub(/\s+/, '')
|
||||
end
|
||||
end
|
||||
|
||||
throttle('reset_password/email', limit: 5, period: 1.hour) do |req|
|
||||
if req.path == '/auth/password' && req.post?
|
||||
email = req.params['email'].presence || ActionDispatch::Request.new(req.env).params['email'].presence
|
||||
|
|
|
@ -303,7 +303,6 @@ Rails.application.routes.draw do
|
|||
# order of resources affect the order of sidebar navigation in super admin
|
||||
resources :accounts
|
||||
resources :users, only: [:index, :new, :create, :show, :edit, :update]
|
||||
resources :super_admins
|
||||
resources :access_tokens, only: [:index, :show]
|
||||
resources :installation_configs, only: [:index, :new, :create, :show, :edit, :update]
|
||||
|
||||
|
|
42
db/migrate/20220121055444_add_type_to_users.rb
Normal file
42
db/migrate/20220121055444_add_type_to_users.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
class AddTypeToUsers < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
add_column :users, :type, :string
|
||||
migrate_existing_super_admins
|
||||
|
||||
drop_table :super_admins do |t|
|
||||
t.string :email, null: false, default: ''
|
||||
t.string :encrypted_password, null: false, default: ''
|
||||
t.datetime :remember_created_at
|
||||
t.integer :sign_in_count, default: 0, null: false
|
||||
t.datetime :current_sign_in_at
|
||||
t.datetime :last_sign_in_at
|
||||
t.inet :current_sign_in_ip
|
||||
t.inet :last_sign_in_ip
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def old_super_admins
|
||||
ActiveRecord::Base.connection.execute('SELECT * from super_admins').to_a
|
||||
end
|
||||
|
||||
def create_user_account_for_super_admin(super_admin)
|
||||
u = User.new(email: super_admin['email'], name: "SuperUser #{super_admin['id']}", encrypted_password: super_admin['encrypted_password'],
|
||||
confirmed_at: DateTime.now, type: 'SuperAdmin')
|
||||
u.save(validate: false)
|
||||
end
|
||||
|
||||
def migrate_existing_super_admins
|
||||
old_super_admins.each do |super_admin|
|
||||
user = User.find_by(email: super_admin['email'])
|
||||
if user.present?
|
||||
user.update(type: 'SuperAdmin')
|
||||
else
|
||||
Rails.logger.debug { "User with email #{super_admin['email']} not found" }
|
||||
create_user_account_for_super_admin(super_admin)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2022_01_11_223630) do
|
||||
ActiveRecord::Schema.define(version: 2022_01_21_055444) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_stat_statements"
|
||||
|
@ -745,6 +745,7 @@ ActiveRecord::Schema.define(version: 2022_01_11_223630) do
|
|||
t.integer "availability", default: 0
|
||||
t.jsonb "ui_settings", default: {}
|
||||
t.jsonb "custom_attributes", default: {}
|
||||
t.string "type"
|
||||
t.index ["email"], name: "index_users_on_email"
|
||||
t.index ["pubsub_token"], name: "index_users_on_pubsub_token", unique: true
|
||||
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
|
||||
|
|
|
@ -10,7 +10,6 @@ end
|
|||
|
||||
## Seeds for Local Development
|
||||
unless Rails.env.production?
|
||||
SuperAdmin.create!(email: 'john@acme.inc', password: 'Password1!')
|
||||
|
||||
account = Account.create!(
|
||||
name: 'Acme Inc'
|
||||
|
@ -20,7 +19,7 @@ unless Rails.env.production?
|
|||
name: 'Acme Org'
|
||||
)
|
||||
|
||||
user = User.new(name: 'John', email: 'john@acme.inc', password: 'Password1!')
|
||||
user = User.new(name: 'John', email: 'john@acme.inc', password: 'Password1!', type: 'SuperAdmin')
|
||||
user.skip_confirmation!
|
||||
user.save!
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ RSpec.describe 'Super Admin access tokens API', type: :request do
|
|||
|
||||
context 'when it is an authenticated super admin' do
|
||||
it 'shows the list of access tokens' do
|
||||
sign_in super_admin
|
||||
sign_in(super_admin, scope: :super_admin)
|
||||
get '/super_admin/access_tokens'
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.body).to include(platform_app.access_token.token)
|
||||
|
|
|
@ -13,7 +13,7 @@ RSpec.describe 'Super Admin Account Users API', type: :request do
|
|||
|
||||
context 'when it is an authenticated super admin' do
|
||||
it 'shows the account user create page' do
|
||||
sign_in super_admin
|
||||
sign_in(super_admin, scope: :super_admin)
|
||||
get '/super_admin/account_users/new'
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
|
|
|
@ -15,7 +15,7 @@ RSpec.describe 'Super Admin accounts API', type: :request do
|
|||
let!(:account) { create(:account) }
|
||||
|
||||
it 'shows the list of accounts' do
|
||||
sign_in super_admin
|
||||
sign_in(super_admin, scope: :super_admin)
|
||||
get '/super_admin/accounts'
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.body).to include('New account')
|
||||
|
|
|
@ -15,7 +15,7 @@ RSpec.describe 'Super Admin agent-bots API', type: :request do
|
|||
let!(:agent_bot) { create(:agent_bot) }
|
||||
|
||||
it 'shows the list of users' do
|
||||
sign_in super_admin
|
||||
sign_in(super_admin, scope: :super_admin)
|
||||
get '/super_admin/agent_bots'
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.body).to include(agent_bot.name)
|
||||
|
|
|
@ -15,7 +15,7 @@ RSpec.describe 'Super Admin Application Config API', type: :request do
|
|||
let!(:config) { create(:installation_config, { name: 'FB_APP_ID', value: 'TESTVALUE' }) }
|
||||
|
||||
it 'shows the app_config page' do
|
||||
sign_in super_admin
|
||||
sign_in(super_admin, scope: :super_admin)
|
||||
get '/super_admin/app_config'
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.body).to include(config.name)
|
||||
|
@ -33,7 +33,7 @@ RSpec.describe 'Super Admin Application Config API', type: :request do
|
|||
|
||||
context 'when it is an aunthenticated super admin' do
|
||||
it 'shows the app_config page' do
|
||||
sign_in super_admin
|
||||
sign_in(super_admin, scope: :super_admin)
|
||||
post '/super_admin/app_config', params: { app_config: { TESTKEY: 'TESTVALUE' } }
|
||||
|
||||
expect(response.status).to eq(302)
|
||||
|
|
|
@ -19,20 +19,20 @@ RSpec.describe 'Super Admin Installation Config API', type: :request do
|
|||
end
|
||||
|
||||
it 'shows the installation_configs create page' do
|
||||
sign_in super_admin
|
||||
sign_in(super_admin, scope: :super_admin)
|
||||
get '/super_admin/installation_configs/new'
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
|
||||
it 'shows the installation_configs edit page' do
|
||||
sign_in super_admin
|
||||
sign_in(super_admin, scope: :super_admin)
|
||||
editable_config = InstallationConfig.editable.first
|
||||
get "/super_admin/installation_configs/#{editable_config.id}/edit"
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
|
||||
it 'shows the installation_configs list page' do
|
||||
sign_in super_admin
|
||||
sign_in(super_admin, scope: :super_admin)
|
||||
get '/super_admin/installation_configs'
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.body).to include(config.name)
|
||||
|
|
|
@ -15,7 +15,7 @@ RSpec.describe 'Super Admin platform app API', type: :request do
|
|||
let!(:platform_app) { create(:platform_app) }
|
||||
|
||||
it 'shows the list of users' do
|
||||
sign_in super_admin
|
||||
sign_in(super_admin, scope: :super_admin)
|
||||
get '/super_admin/platform_apps'
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.body).to include(platform_app.name)
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Super Admin super admins API', type: :request do
|
||||
let(:super_admin) { create(:super_admin) }
|
||||
|
||||
describe 'GET /super_admin/users' do
|
||||
context 'when it is an unauthenticated super admin' do
|
||||
it 'returns unauthorized' do
|
||||
get '/super_admin/super_admins'
|
||||
expect(response).to have_http_status(:redirect)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an authenticated super admin' do
|
||||
it 'shows the list of super admins' do
|
||||
sign_in super_admin
|
||||
get '/super_admin/super_admins'
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.body).to include('New super admin')
|
||||
expect(response.body).to include(super_admin.email)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -15,7 +15,7 @@ RSpec.describe 'Super Admin Users API', type: :request do
|
|||
let!(:user) { create(:user) }
|
||||
|
||||
it 'shows the list of users' do
|
||||
sign_in super_admin
|
||||
sign_in(super_admin, scope: :super_admin)
|
||||
get '/super_admin/users'
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.body).to include('New user')
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Super Admin', type: :request do
|
||||
let(:super_admin) { create(:super_admin) }
|
||||
|
||||
describe 'request to /super_admin' do
|
||||
context 'when the super admin is unauthenticated' do
|
||||
it 'redirects to signin page' do
|
||||
get '/super_admin/'
|
||||
expect(response).to have_http_status(:redirect)
|
||||
expect(response.body).to include('sign_in')
|
||||
end
|
||||
|
||||
it 'signs super admin in and out' do
|
||||
sign_in super_admin
|
||||
get '/super_admin'
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.body).to include('Dashboard')
|
||||
|
||||
sign_out super_admin
|
||||
get '/super_admin'
|
||||
expect(response).to have_http_status(:redirect)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'request to /super_admin/sidekiq' do
|
||||
context 'when the super admin is unauthenticated' do
|
||||
it 'redirects to signin page' do
|
||||
get '/monitoring/sidekiq'
|
||||
expect(response).to have_http_status(:not_found)
|
||||
expect(response.body).to include('sign_in')
|
||||
end
|
||||
|
||||
it 'signs super admin in and out' do
|
||||
sign_in super_admin
|
||||
get '/monitoring/sidekiq'
|
||||
expect(response).to have_http_status(:success)
|
||||
|
||||
sign_out super_admin
|
||||
get '/monitoring/sidekiq'
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,9 @@
|
|||
FactoryBot.define do
|
||||
factory :super_admin do
|
||||
name { Faker::Name.name }
|
||||
email { "admin@#{SecureRandom.uuid}.com" }
|
||||
password { 'Password1!' }
|
||||
type { 'SuperAdmin' }
|
||||
confirmed_at { Time.zone.now }
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue