From b7a583b2c4b6760ed14716915ccd892697ea449a Mon Sep 17 00:00:00 2001 From: Sojan Jose Date: Tue, 26 May 2020 22:38:48 +0530 Subject: [PATCH] Feature: Ability to switch between multiple accounts (#881) * Feature: Ability to switch between multiple accounts * Fix rubocop * Fix assigned inboxes * fix auth json * Add account switcher in UI * fix ordering on administrate * Add switch accounts to sidebar * add account id * Fix schema.rb timestamp * Revert "add account id" This reverts commit 27570f50ef584cb9a5f69454f43f630b318c8807. * Add a check for account Co-authored-by: Pranav Raj Sreepuram --- app/builders/account_builder.rb | 1 + .../api/v1/accounts/accounts_controller.rb | 19 ++- .../api/v1/accounts/agents_controller.rb | 4 +- .../channels/twilio_channels_controller.rb | 1 + .../v1/accounts/conversations_controller.rb | 1 + .../api/v1/accounts/inboxes_controller.rb | 3 +- .../api/v1/accounts/webhooks_controller.rb | 1 + .../api/v2/accounts/reports_controller.rb | 4 - app/controllers/application_controller.rb | 15 +- .../devise_overrides/passwords_controller.rb | 2 +- .../devise_overrides/sessions_controller.rb | 2 +- app/dashboards/account_user_dashboard.rb | 4 +- .../assets/scss/widgets/_sidemenu.scss | 2 +- .../dashboard/components/layout/Sidebar.vue | 137 ++++++++++++++++-- .../components/layout/SidebarItem.vue | 5 +- .../widgets/conversation/EmptyState.vue | 4 +- .../dashboard/helper/actionCable.js | 4 + .../dashboard/i18n/default-sidebar.js | 12 +- .../dashboard/i18n/locale/en/settings.json | 2 + .../dashboard/i18n/locale/fr/settings.json | 2 + .../dashboard/i18n/locale/nl/settings.json | 2 + app/javascript/dashboard/mixins/isAdmin.js | 9 +- .../dashboard/routes/dashboard/Dashboard.vue | 6 +- .../dashboard/settings/SettingsHeader.vue | 6 +- .../settings/account/account.routes.js | 1 - .../routes/dashboard/settings/inbox/Index.vue | 10 +- .../dashboard/settings/inbox/inbox.routes.js | 2 +- .../dashboard/settings/integrations/Index.vue | 4 +- .../settings/profile/NotificationSettings.vue | 1 - .../settings/profile/profile.routes.js | 2 +- .../dashboard/settings/settings.routes.js | 4 +- .../dashboard/store/modules/auth.js | 20 +++ .../dashboard/store/mutation-types.js | 2 + .../helpers/BaseActionCableConnector.js | 7 +- app/listeners/action_cable_listener.rb | 52 ++++--- app/listeners/base_listener.rb | 6 +- app/listeners/notification_listener.rb | 4 +- app/listeners/reporting_listener.rb | 15 +- app/models/account_user.rb | 17 ++- app/models/user.rb | 38 +++-- app/policies/account_policy.rb | 12 +- app/policies/application_policy.rb | 20 ++- app/policies/contact_policy.rb | 6 +- app/policies/inbox_policy.rb | 21 +-- app/policies/user_policy.rb | 6 +- app/policies/webhook_policy.rb | 8 +- app/views/api/v1/models/user.json.jbuilder | 6 +- .../api/v1/profiles/update.json.jbuilder | 2 - app/views/devise/_auth.json.jbuilder | 22 +++ app/views/devise/auth.json.jbuilder | 14 -- .../mailer/confirmation_instructions.html.erb | 2 +- app/views/devise/token.json.jbuilder | 16 +- config/routes.rb | 3 + ...20125815_add_active_at_to_account_users.rb | 5 + db/schema.rb | 1 + lib/current.rb | 2 + .../v1/accounts/accounts_controller_spec.rb | 30 +++- spec/finders/conversation_finder_spec.rb | 1 + spec/listeners/action_cable_listener_spec.rb | 10 +- .../mailers/confirmation_instructions_spec.rb | 1 + spec/models/user_spec.rb | 1 - spec/policies/contact_policy_spec.rb | 11 +- spec/policies/inbox_policy_spec.rb | 10 +- spec/policies/user_policy_spec.rb | 10 +- 64 files changed, 441 insertions(+), 212 deletions(-) create mode 100644 app/views/devise/_auth.json.jbuilder delete mode 100644 app/views/devise/auth.json.jbuilder create mode 100644 db/migrate/20200520125815_add_active_at_to_account_users.rb diff --git a/app/builders/account_builder.rb b/app/builders/account_builder.rb index 9c724bd43..1c7c1f63d 100644 --- a/app/builders/account_builder.rb +++ b/app/builders/account_builder.rb @@ -38,6 +38,7 @@ class AccountBuilder def create_account @account = Account.create!(name: @account_name) + Current.account = @account end def create_and_link_user diff --git a/app/controllers/api/v1/accounts/accounts_controller.rb b/app/controllers/api/v1/accounts/accounts_controller.rb index 29e26929b..adb8bf11c 100644 --- a/app/controllers/api/v1/accounts/accounts_controller.rb +++ b/app/controllers/api/v1/accounts/accounts_controller.rb @@ -5,8 +5,8 @@ class Api::V1::Accounts::AccountsController < Api::BaseController skip_before_action :authenticate_user!, :set_current_user, :check_subscription, :handle_with_exception, only: [:create], raise: false before_action :check_signup_enabled, only: [:create] - before_action :check_authorization, except: [:create] before_action :fetch_account, except: [:create] + before_action :check_authorization, except: [:create] rescue_from CustomExceptions::Account::InvalidEmail, CustomExceptions::Account::UserExists, @@ -21,7 +21,7 @@ class Api::V1::Accounts::AccountsController < Api::BaseController ).perform if @user send_auth_headers(@user) - render 'devise/auth.json', locals: { resource: @user } + render partial: 'devise/auth.json', locals: { resource: @user } else render_error_response(CustomExceptions::Account::SignupFailed.new({})) end @@ -35,6 +35,12 @@ class Api::V1::Accounts::AccountsController < Api::BaseController @account.update!(account_params.slice(:name, :locale, :domain, :support_email, :domain_emails_enabled)) end + def update_active_at + @current_account_user.active_at = Time.now.utc + @current_account_user.save! + head :ok + end + private def check_authorization @@ -47,6 +53,7 @@ class Api::V1::Accounts::AccountsController < Api::BaseController def fetch_account @account = current_user.accounts.find(params[:id]) + @current_account_user = @account.account_users.find_by(user_id: current_user.id) end def account_params @@ -56,4 +63,12 @@ class Api::V1::Accounts::AccountsController < Api::BaseController def check_signup_enabled raise ActionController::RoutingError, 'Not Found' if ENV.fetch('ENABLE_ACCOUNT_SIGNUP', true) == 'false' end + + def pundit_user + { + user: current_user, + account: @account, + account_user: @current_account_user + } + end end diff --git a/app/controllers/api/v1/accounts/agents_controller.rb b/app/controllers/api/v1/accounts/agents_controller.rb index ca796ceef..7cdd6dbb5 100644 --- a/app/controllers/api/v1/accounts/agents_controller.rb +++ b/app/controllers/api/v1/accounts/agents_controller.rb @@ -10,13 +10,13 @@ class Api::V1::Accounts::AgentsController < Api::BaseController end def destroy - @agent.account_user.destroy + @agent.current_account_user.destroy head :ok end def update @agent.update!(agent_params.except(:role)) - @agent.account_user.update!(role: agent_params[:role]) if agent_params[:role] + @agent.current_account_user.update!(role: agent_params[:role]) if agent_params[:role] render 'api/v1/models/user.json', locals: { resource: @agent } end diff --git a/app/controllers/api/v1/accounts/channels/twilio_channels_controller.rb b/app/controllers/api/v1/accounts/channels/twilio_channels_controller.rb index c0c121900..8011d3891 100644 --- a/app/controllers/api/v1/accounts/channels/twilio_channels_controller.rb +++ b/app/controllers/api/v1/accounts/channels/twilio_channels_controller.rb @@ -1,4 +1,5 @@ class Api::V1::Accounts::Channels::TwilioChannelsController < Api::BaseController + before_action :current_account before_action :authorize_request def create diff --git a/app/controllers/api/v1/accounts/conversations_controller.rb b/app/controllers/api/v1/accounts/conversations_controller.rb index 8008217aa..849c36942 100644 --- a/app/controllers/api/v1/accounts/conversations_controller.rb +++ b/app/controllers/api/v1/accounts/conversations_controller.rb @@ -1,5 +1,6 @@ class Api::V1::Accounts::ConversationsController < Api::BaseController include Events::Types + before_action :current_account before_action :conversation, except: [:index] before_action :contact_inbox, only: [:create] diff --git a/app/controllers/api/v1/accounts/inboxes_controller.rb b/app/controllers/api/v1/accounts/inboxes_controller.rb index 4b3ed836e..8fdde8cc0 100644 --- a/app/controllers/api/v1/accounts/inboxes_controller.rb +++ b/app/controllers/api/v1/accounts/inboxes_controller.rb @@ -1,7 +1,8 @@ class Api::V1::Accounts::InboxesController < Api::BaseController - before_action :check_authorization + before_action :current_account before_action :fetch_inbox, except: [:index, :create] before_action :fetch_agent_bot, only: [:set_agent_bot] + before_action :check_authorization def index @inboxes = policy_scope(current_account.inboxes) diff --git a/app/controllers/api/v1/accounts/webhooks_controller.rb b/app/controllers/api/v1/accounts/webhooks_controller.rb index dbdd953ed..d3afba2af 100644 --- a/app/controllers/api/v1/accounts/webhooks_controller.rb +++ b/app/controllers/api/v1/accounts/webhooks_controller.rb @@ -1,4 +1,5 @@ class Api::V1::Accounts::WebhooksController < Api::BaseController + before_action :current_account before_action :check_authorization before_action :fetch_webhook, only: [:update, :destroy] diff --git a/app/controllers/api/v2/accounts/reports_controller.rb b/app/controllers/api/v2/accounts/reports_controller.rb index fe94db4e1..6aa0355a4 100644 --- a/app/controllers/api/v2/accounts/reports_controller.rb +++ b/app/controllers/api/v2/accounts/reports_controller.rb @@ -11,10 +11,6 @@ class Api::V2::Accounts::ReportsController < Api::BaseController private - def current_account - current_user.account - end - def account_summary_params { type: :account, diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 924a4e451..ae3e5e857 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -14,7 +14,8 @@ class ApplicationController < ActionController::Base private def current_account - @_ ||= find_current_account + @current_account ||= find_current_account + Current.account = @current_account end def find_current_account @@ -37,7 +38,9 @@ class ApplicationController < ActionController::Base end def account_accessible_for_user?(account) - render_unauthorized('You are not authorized to access this account') unless account.account_users.find_by(user_id: current_user.id) + @current_account_user = account.account_users.find_by(user_id: current_user.id) + Current.account_user = @current_account_user + render_unauthorized('You are not authorized to access this account') unless @current_account_user end def account_accessible_for_bot?(account) @@ -102,4 +105,12 @@ class ApplicationController < ActionController::Base render json: { error: 'Account Suspended' }, status: :account_suspended end end + + def pundit_user + { + user: Current.user, + account: Current.account, + account_user: Current.account_user + } + end end diff --git a/app/controllers/devise_overrides/passwords_controller.rb b/app/controllers/devise_overrides/passwords_controller.rb index 4289d5af2..ed9d012eb 100644 --- a/app/controllers/devise_overrides/passwords_controller.rb +++ b/app/controllers/devise_overrides/passwords_controller.rb @@ -11,7 +11,7 @@ class DeviseOverrides::PasswordsController < Devise::PasswordsController @recoverable = User.find_by(reset_password_token: reset_password_token) if @recoverable && reset_password_and_confirmation(@recoverable) send_auth_headers(@recoverable) - render 'devise/auth.json', locals: { resource: @recoverable } + render partial: 'devise/auth.json', locals: { resource: @recoverable } else render json: { "message": 'Invalid token', "redirect_url": '/' }, status: 422 end diff --git a/app/controllers/devise_overrides/sessions_controller.rb b/app/controllers/devise_overrides/sessions_controller.rb index b9cec5447..9ebb3b435 100644 --- a/app/controllers/devise_overrides/sessions_controller.rb +++ b/app/controllers/devise_overrides/sessions_controller.rb @@ -4,6 +4,6 @@ class DeviseOverrides::SessionsController < ::DeviseTokenAuth::SessionsControlle wrap_parameters format: [] def render_create_success - render 'devise/auth.json', locals: { resource: @resource } + render partial: 'devise/auth.json', locals: { resource: @resource } end end diff --git a/app/dashboards/account_user_dashboard.rb b/app/dashboards/account_user_dashboard.rb index d2a2e7f27..d757f4da5 100644 --- a/app/dashboards/account_user_dashboard.rb +++ b/app/dashboards/account_user_dashboard.rb @@ -8,8 +8,8 @@ class AccountUserDashboard < Administrate::BaseDashboard # which determines how the attribute is displayed # on pages throughout the dashboard. ATTRIBUTE_TYPES = { - account: Field::BelongsTo.with_options(searchable: true, searchable_field: 'name'), - user: Field::BelongsTo.with_options(searchable: true, searchable_field: 'name'), + account: Field::BelongsTo.with_options(searchable: true, searchable_field: 'name', order: 'id DESC'), + user: Field::BelongsTo.with_options(searchable: true, searchable_field: 'name', order: 'id DESC'), inviter: Field::BelongsTo.with_options(class_name: 'User', searchable: true, searchable_field: 'name'), id: Field::Number, role: Field::Select.with_options(collection: AccountUser.roles.keys), diff --git a/app/javascript/dashboard/assets/scss/widgets/_sidemenu.scss b/app/javascript/dashboard/assets/scss/widgets/_sidemenu.scss index 83e4ff5ee..3971ec6fd 100644 --- a/app/javascript/dashboard/assets/scss/widgets/_sidemenu.scss +++ b/app/javascript/dashboard/assets/scss/widgets/_sidemenu.scss @@ -72,7 +72,7 @@ @include border-light; display: block; left: 18%; - top: -110%; + top: -110px; visibility: visible; width: 80%; z-index: 999; diff --git a/app/javascript/dashboard/components/layout/Sidebar.vue b/app/javascript/dashboard/components/layout/Sidebar.vue index a38ebe2cf..986232749 100644 --- a/app/javascript/dashboard/components/layout/Sidebar.vue +++ b/app/javascript/dashboard/components/layout/Sidebar.vue @@ -13,7 +13,6 @@ :key="item.toState" :menu-item="item" /> - @@ -42,6 +41,14 @@ class="dropdown-pane top" >