diff --git a/Gemfile b/Gemfile index 45d54dfe0..ae0938676 100644 --- a/Gemfile +++ b/Gemfile @@ -59,6 +59,7 @@ gem 'barnes' ##--- gems for authentication & authorization ---## gem 'devise' +gem 'devise-secure_password', '~> 2.0' gem 'devise_token_auth' # authorization gem 'jwt' diff --git a/Gemfile.lock b/Gemfile.lock index 2923468cd..55d3dbd29 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -123,7 +123,7 @@ GEM barnes (0.0.8) multi_json (~> 1) statsd-ruby (~> 1.1) - bcrypt (3.1.15) + bcrypt (3.1.16) bindex (0.8.1) bootsnap (1.4.8) msgpack (~> 1.0) @@ -158,12 +158,15 @@ GEM declarative-option (0.1.0) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) - devise (4.7.2) + devise (4.8.0) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) responders warden (~> 1.2.3) + devise-secure_password (2.0.1) + devise (>= 4.0.0, < 5.0.0) + railties (>= 5.0.0, < 7.0.0) devise_token_auth (1.1.4) bcrypt (~> 3.0) devise (> 3.5.2, < 5) @@ -259,7 +262,7 @@ GEM multi_json (~> 1.11) os (>= 0.9, < 2.0) signet (~> 0.14) - groupdate (5.1.0) + groupdate (5.2.2) activesupport (>= 5) grpc (1.37.1) google-protobuf (~> 3.15) @@ -348,7 +351,7 @@ GEM connection_pool (~> 2.2) netrc (0.11.0) nio4r (2.5.7) - nokogiri (1.11.4) + nokogiri (1.11.6) mini_portile2 (~> 2.5.0) racc (~> 1.4) oauth (0.5.6) @@ -582,8 +585,8 @@ GEM coercible (~> 1.0) descendants_tracker (~> 0.0, >= 0.0.3) equalizer (~> 0.0, >= 0.0.9) - warden (1.2.8) - rack (>= 2.0.6) + warden (1.2.9) + rack (>= 2.0.9) web-console (4.0.4) actionview (>= 6.0.0) activemodel (>= 6.0.0) @@ -629,6 +632,7 @@ DEPENDENCIES cypress-on-rails (~> 1.0) database_cleaner devise + devise-secure_password (~> 2.0) devise_token_auth dotenv-rails facebook-messenger diff --git a/app/builders/account_builder.rb b/app/builders/account_builder.rb index f7f94fada..0464c8013 100644 --- a/app/builders/account_builder.rb +++ b/app/builders/account_builder.rb @@ -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] def perform if @user.nil? @@ -61,11 +61,9 @@ class AccountBuilder end def create_user - password = user_password || SecureRandom.alphanumeric(12) - @user = User.new(email: @email, - password: password, - password_confirmation: password, + password: user_password, + password_confirmation: user_password, name: @user_full_name) @user.confirm if @confirmed @user.save! diff --git a/app/controllers/api/v1/accounts/agents_controller.rb b/app/controllers/api/v1/accounts/agents_controller.rb index 83f1ad186..46d35d09d 100644 --- a/app/controllers/api/v1/accounts/agents_controller.rb +++ b/app/controllers/api/v1/accounts/agents_controller.rb @@ -58,9 +58,10 @@ class Api::V1::Accounts::AgentsController < Api::V1::Accounts::BaseController end def new_agent_params - time = Time.now.to_i + # intial string ensures the password requirements are met + temp_password = "1!aA#{SecureRandom.alphanumeric(12)}" params.require(:agent).permit(:email, :name, :role) - .merge!(password: time, password_confirmation: time, inviter: current_user) + .merge!(password: temp_password, password_confirmation: temp_password, inviter: current_user) end def agents diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index 8fbb56c19..f67972486 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -18,7 +18,7 @@ class Api::V1::AccountsController < Api::BaseController account_name: account_params[:account_name], user_full_name: account_params[:user_full_name], email: account_params[:email], - confirmed: confirmed?, + user_password: account_params[:password], user: current_user ).perform if @user @@ -46,17 +46,13 @@ class Api::V1::AccountsController < Api::BaseController private - def confirmed? - super_admin? && params[:confirmed] - end - 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 - params.permit(:account_name, :email, :name, :locale, :domain, :support_email, :auto_resolve_duration, :user_full_name) + params.permit(:account_name, :email, :name, :password, :locale, :domain, :support_email, :auto_resolve_duration, :user_full_name) end def check_signup_enabled diff --git a/app/controllers/api/v1/widget/messages_controller.rb b/app/controllers/api/v1/widget/messages_controller.rb index 6def00a3a..fc55b0c1b 100644 --- a/app/controllers/api/v1/widget/messages_controller.rb +++ b/app/controllers/api/v1/widget/messages_controller.rb @@ -20,7 +20,7 @@ class Api::V1::Widget::MessagesController < Api::V1::Widget::BaseController @message.update!(message_update_params[:message]) end rescue StandardError => e - render json: { error: @contact.errors, message: e.message }.to_json, status: 500 + render json: { error: @contact.errors, message: e.message }.to_json, status: :internal_server_error end private diff --git a/app/controllers/concerns/access_token_auth_helper.rb b/app/controllers/concerns/access_token_auth_helper.rb index 91bd461aa..2f4dc4337 100644 --- a/app/controllers/concerns/access_token_auth_helper.rb +++ b/app/controllers/concerns/access_token_auth_helper.rb @@ -17,13 +17,8 @@ module AccessTokenAuthHelper Current.user = @resource if current_user.is_a?(User) end - def super_admin? - @resource.present? && @resource.is_a?(SuperAdmin) - end - def validate_bot_access_token! return if Current.user.is_a?(User) - return if super_admin? return if agent_bot_accessible? render_unauthorized('Access to this endpoint is not authorized for bots') diff --git a/app/controllers/devise_overrides/confirmations_controller.rb b/app/controllers/devise_overrides/confirmations_controller.rb index 0cb71f0d9..02d412cb1 100644 --- a/app/controllers/devise_overrides/confirmations_controller.rb +++ b/app/controllers/devise_overrides/confirmations_controller.rb @@ -1,34 +1,29 @@ class DeviseOverrides::ConfirmationsController < Devise::ConfirmationsController + include AuthHelper skip_before_action :require_no_authentication, raise: false skip_before_action :authenticate_user!, raise: false def create @confirmable = User.find_by(confirmation_token: params[:confirmation_token]) + render_confirmation_success and return if @confirmable&.confirm - if confirm - render_confirmation_success - else - render_confirmation_error - end + render_confirmation_error end - protected - - def confirm - @confirmable&.confirm || (@confirmable&.confirmed_at && @confirmable&.reset_password_token) - end + private def render_confirmation_success - render json: { "message": 'Success', "redirect_url": create_reset_token_link(@confirmable) }, status: :ok + send_auth_headers(@confirmable) + render partial: 'devise/auth.json', locals: { resource: @confirmable } end def render_confirmation_error if @confirmable.blank? - render json: { "message": 'Invalid token', "redirect_url": '/' }, status: 422 + render json: { message: 'Invalid token', redirect_url: '/' }, status: :unprocessable_entity elsif @confirmable.confirmed_at - render json: { "message": 'Already confirmed', "redirect_url": '/' }, status: 422 + render json: { message: 'Already confirmed', redirect_url: '/' }, status: :unprocessable_entity else - render json: { "message": 'Failure', "redirect_url": '/' }, status: 422 + render json: { message: 'Failure', redirect_url: '/' }, status: :unprocessable_entity end end diff --git a/app/controllers/devise_overrides/passwords_controller.rb b/app/controllers/devise_overrides/passwords_controller.rb index ed9d012eb..501b9f90c 100644 --- a/app/controllers/devise_overrides/passwords_controller.rb +++ b/app/controllers/devise_overrides/passwords_controller.rb @@ -13,7 +13,7 @@ class DeviseOverrides::PasswordsController < Devise::PasswordsController send_auth_headers(@recoverable) render partial: 'devise/auth.json', locals: { resource: @recoverable } else - render json: { "message": 'Invalid token', "redirect_url": '/' }, status: 422 + render json: { message: 'Invalid token', redirect_url: '/' }, status: :unprocessable_entity end end @@ -27,7 +27,7 @@ class DeviseOverrides::PasswordsController < Devise::PasswordsController end end - protected + private def reset_password_and_confirmation(recoverable) recoverable.confirm unless recoverable.confirmed? # confirm if user resets password without confirming anytime before @@ -40,7 +40,7 @@ class DeviseOverrides::PasswordsController < Devise::PasswordsController def build_response(message, status) render json: { - "message": message + message: message }, status: status end end diff --git a/app/dashboards/super_admin_dashboard.rb b/app/dashboards/super_admin_dashboard.rb index ab467a255..1d9afd1ba 100644 --- a/app/dashboards/super_admin_dashboard.rb +++ b/app/dashboards/super_admin_dashboard.rb @@ -11,7 +11,6 @@ class SuperAdminDashboard < Administrate::BaseDashboard id: Field::Number, email: Field::String, password: Field::Password, - access_token: Field::HasOne, remember_created_at: Field::DateTime, sign_in_count: Field::Number, current_sign_in_at: Field::DateTime, @@ -30,7 +29,6 @@ class SuperAdminDashboard < Administrate::BaseDashboard COLLECTION_ATTRIBUTES = %i[ id email - access_token ].freeze # SHOW_PAGE_ATTRIBUTES diff --git a/app/javascript/dashboard/api/auth.js b/app/javascript/dashboard/api/auth.js index 4a1ca37f1..558eb4933 100644 --- a/app/javascript/dashboard/api/auth.js +++ b/app/javascript/dashboard/api/auth.js @@ -29,6 +29,7 @@ export default { account_name: creds.accountName.trim(), user_full_name: creds.fullName.trim(), email: creds.email, + password: creds.password, }) .then(response => { setAuthCredentials(response); @@ -95,8 +96,18 @@ export default { }, verifyPasswordToken({ confirmationToken }) { - return axios.post('auth/confirmation', { - confirmation_token: confirmationToken, + return new Promise((resolve, reject) => { + axios + .post('auth/confirmation', { + confirmation_token: confirmationToken, + }) + .then(response => { + setAuthCredentials(response); + resolve(response); + }) + .catch(error => { + reject(error.response); + }); }); }, diff --git a/app/javascript/dashboard/routes/auth/Confirmation.vue b/app/javascript/dashboard/routes/auth/Confirmation.vue index db439af03..1abf16f1e 100644 --- a/app/javascript/dashboard/routes/auth/Confirmation.vue +++ b/app/javascript/dashboard/routes/auth/Confirmation.vue @@ -21,12 +21,10 @@ export default { methods: { async confirmToken() { try { - const { - data: { redirect_url: redirectURL }, - } = await Auth.verifyPasswordToken({ + await Auth.verifyPasswordToken({ confirmationToken: this.confirmationToken, }); - window.location = redirectURL; + window.location = DEFAULT_REDIRECT_URL; } catch (error) { window.location = DEFAULT_REDIRECT_URL; } diff --git a/app/javascript/dashboard/routes/auth/PasswordEdit.vue b/app/javascript/dashboard/routes/auth/PasswordEdit.vue index 4549528a0..751f16e83 100644 --- a/app/javascript/dashboard/routes/auth/PasswordEdit.vue +++ b/app/javascript/dashboard/routes/auth/PasswordEdit.vue @@ -120,8 +120,12 @@ export default { window.location = DEFAULT_REDIRECT_URL; } }) - .catch(() => { - this.showAlert(this.$t('SET_NEW_PASSWORD.API.ERROR_MESSAGE')); + .catch(error => { + let errorMessage = this.$t('SET_NEW_PASSWORD.API.ERROR_MESSAGE'); + if (error?.data?.message) { + errorMessage = error.data.message; + } + this.showAlert(errorMessage); }); }, }, diff --git a/app/javascript/dashboard/routes/auth/Signup.vue b/app/javascript/dashboard/routes/auth/Signup.vue index 5b71e2887..c175e7b9e 100644 --- a/app/javascript/dashboard/routes/auth/Signup.vue +++ b/app/javascript/dashboard/routes/auth/Signup.vue @@ -25,6 +25,17 @@ " @blur="$v.credentials.fullName.$touch" /> + + + Configuration for the Devise Secure Password extension + # Module: password_has_required_content + # + # Configure password content requirements including the number of uppercase, + # lowercase, number, and special characters that are required. To configure the + # minimum and maximum length refer to the Devise config.password_length + # standard configuration parameter. + + # The number of uppercase letters (latin A-Z) required in a password: + config.password_required_uppercase_count = 1 + + # The number of lowercase letters (latin A-Z) required in a password: + config.password_required_lowercase_count = 1 + + # The number of numbers (0-9) required in a password: + config.password_required_number_count = 1 + + # The number of special characters (!@#$%^&*()_+-=[]{}|') required in a password: + config.password_required_special_character_count = 1 + + # we are not using the configurations below + # ==> Configuration for the Devise Secure Password extension + # Module: password_disallows_frequent_reuse + # + # The number of previously used passwords that can not be reused: + # config.password_previously_used_count = 8 + + # ==> Configuration for the Devise Secure Password extension + # Module: password_disallows_frequent_changes + # *Requires* password_disallows_frequent_reuse + # + # The minimum time that must pass between password changes: + # config.password_minimum_age = 1.days + + # ==> Configuration for the Devise Secure Password extension + # Module: password_requires_regular_updates + # *Requires* password_disallows_frequent_reuse + # + # The maximum allowed age of a password: + # config.password_maximum_age = 180.days +end diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index f3ba72aef..f76e4a409 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -1,3 +1,5 @@ +require Rails.root.join('lib/redis/config') + schedule_file = 'config/schedule.yml' Sidekiq.configure_client do |config| diff --git a/config/locales/secure_password.en.yml b/config/locales/secure_password.en.yml new file mode 100644 index 000000000..ad8bbd074 --- /dev/null +++ b/config/locales/secure_password.en.yml @@ -0,0 +1,74 @@ +en: + secure_password: + character: + one: "character" + other: "characters" + + types: + uppercase: "uppercase" + downcase: "downcase" + lowercase: "lowercase" + number: "number" + special: "special" + + password_has_required_content: + errors: + messages: + unknown_characters: "contains %{count} invalid %{subject}" + minimum_characters: "must contain at least %{count} %{type} %{subject}" + maximum_characters: "must contain less than %{count} %{type} %{subject}" + minimum_length: "must contain at least %{count} %{subject}" + maximum_length: "must contain less than %{count} %{subject}" + password_disallows_frequent_reuse: + errors: + messages: + password_is_recent: "Last %{count} passwords may not be reused" + password_disallows_frequent_changes: + errors: + messages: + password_is_recent: "Password cannot be changed more than once per %{timeframe}" + password_requires_regular_updates: + alerts: + messages: + password_updated: "Your password has been updated." + errors: + messages: + password_expired: "Your password has expired. Passwords must be changed every %{timeframe}" + datetime: + # update distance_in_words translations to remove the determiner words: + # about, almost, over, less than, etc. + precise_distance_in_words: + half_a_minute: "half a minute" + less_than_x_seconds: + one: "1 second" # default was: "less than 1 second" + other: "%{count} seconds" # default was: "less than %{count} seconds" + x_seconds: + one: "1 second" + other: "%{count} seconds" + less_than_x_minutes: + one: "a minute" # default was: "less than a minute" + other: "%{count} minutes" # default was: "less than %{count} minutes" + x_minutes: + one: "1 minute" + other: "%{count} minutes" + about_x_hours: + one: "1 hour" # default was: "about 1 hour" + other: "%{count} hours" # default was: "about %{count} hours" + x_days: + one: "1 day" + other: "%{count} days" + about_x_months: + one: "1 month" # default was: "about 1 month" + other: "%{count} months" # default was: "about %{count} months" + x_months: + one: "1 month" + other: "%{count} months" + about_x_years: + one: "1 year" # default was: "about 1 year" + other: "%{count} years" # default was: "about %{count} years" + over_x_years: + one: "1 year" # default was: "over 1 year" + other: "%{count} years" # default was: "over %{count} years" + almost_x_years: + one: "1 year" # default was: "almost 1 year" + other: "%{count} years" # default was: "almost %{count} years" \ No newline at end of file diff --git a/db/migrate/20210527173755_remove_super_admin_access_tokes.rb b/db/migrate/20210527173755_remove_super_admin_access_tokes.rb new file mode 100644 index 000000000..18ad7d4f8 --- /dev/null +++ b/db/migrate/20210527173755_remove_super_admin_access_tokes.rb @@ -0,0 +1,5 @@ +class RemoveSuperAdminAccessTokes < ActiveRecord::Migration[6.0] + def change + AccessToken.where(owner_type: 'SuperAdmin').destroy_all + end +end diff --git a/db/schema.rb b/db/schema.rb index 5a1fd235b..884c208d2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_05_20_200729) do +ActiveRecord::Schema.define(version: 2021_05_27_173755) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" diff --git a/db/seeds.rb b/db/seeds.rb index 115a27108..8d47bded9 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -10,13 +10,13 @@ end ## Seeds for Local Development unless Rails.env.production? - SuperAdmin.create!(email: 'john@acme.inc', password: '123456') + SuperAdmin.create!(email: 'john@acme.inc', password: 'Password1!') account = Account.create!( name: 'Acme Inc' ) - user = User.new(name: 'John', email: 'john@acme.inc', password: '123456') + user = User.new(name: 'John', email: 'john@acme.inc', password: 'Password1!') user.skip_confirmation! user.save! diff --git a/lib/woot_message_seeder.rb b/lib/woot_message_seeder.rb index e28eae3fc..7f7c81e95 100644 --- a/lib/woot_message_seeder.rb +++ b/lib/woot_message_seeder.rb @@ -29,19 +29,19 @@ module WootMessageSeeder def self.sample_card_item { - "media_url": 'https://i.imgur.com/d8Djr4k.jpg', - "title": 'Acme Shoes 2.0', - "description": 'Move with Acme Shoe 2.0', - "actions": [ + media_url: 'https://i.imgur.com/d8Djr4k.jpg', + title: 'Acme Shoes 2.0', + description: 'Move with Acme Shoe 2.0', + actions: [ { - "type": 'link', - "text": 'View More', - "uri": 'http://acme-shoes.inc' + type: 'link', + text: 'View More', + uri: 'http://acme-shoes.inc' }, { - "type": 'postback', - "text": 'Add to cart', - "payload": 'ITEM_SELECTED' + type: 'postback', + text: 'Add to cart', + payload: 'ITEM_SELECTED' } ] } @@ -56,11 +56,11 @@ module WootMessageSeeder content: 'Your favorite food', content_type: 'input_select', content_attributes: { - "items": [ - { "title": '🌯 Burito', "value": 'Burito' }, - { "title": '🍝 Pasta', "value": 'Pasta' }, - { "title": ' 🍱 Sushi', "value": 'Sushi' }, - { "title": ' 🥗 Salad', "value": 'Salad' } + items: [ + { title: '🌯 Burito', value: 'Burito' }, + { title: '🍝 Pasta', value: 'Pasta' }, + { title: ' 🍱 Sushi', value: 'Sushi' }, + { title: ' 🥗 Salad', value: 'Salad' } ] } ) @@ -75,12 +75,12 @@ module WootMessageSeeder content_type: 'form', content: 'form', content_attributes: { - "items": [ - { "name": 'email', "placeholder": 'Please enter your email', "type": 'email', "label": 'Email' }, - { "name": 'text_area', "placeholder": 'Please enter text', "type": 'text_area', "label": 'Large Text' }, - { "name": 'text', "placeholder": 'Please enter text', "type": 'text', "label": 'text', "default": 'defaut value' }, - { "name": 'select', "label": 'Select Option', "type": 'select', "options": [{ "label": '🌯 Burito', "value": 'Burito' }, - { "label": '🍝 Pasta', "value": 'Pasta' }] } + items: [ + { name: 'email', placeholder: 'Please enter your email', type: 'email', label: 'Email' }, + { name: 'text_area', placeholder: 'Please enter text', type: 'text_area', label: 'Large Text' }, + { name: 'text', placeholder: 'Please enter text', type: 'text', label: 'text', default: 'defaut value' }, + { name: 'select', label: 'Select Option', type: 'select', options: [{ label: '🌯 Burito', value: 'Burito' }, + { label: '🍝 Pasta', value: 'Pasta' }] } ] } ) @@ -95,9 +95,9 @@ module WootMessageSeeder content: 'Tech Companies', content_type: 'article', content_attributes: { - "items": [ - { "title": 'Acme Hardware', "description": 'Hardware reimagined', "link": 'http://acme-hardware.inc' }, - { "title": 'Acme Search', "description": 'The best Search Engine', "link": 'http://acme-search.inc' } + items: [ + { title: 'Acme Hardware', description: 'Hardware reimagined', link: 'http://acme-hardware.inc' }, + { title: 'Acme Search', description: 'The best Search Engine', link: 'http://acme-search.inc' } ] } ) diff --git a/spec/controllers/api/v1/accounts_controller_spec.rb b/spec/controllers/api/v1/accounts_controller_spec.rb index 16f36720d..24607f250 100644 --- a/spec/controllers/api/v1/accounts_controller_spec.rb +++ b/spec/controllers/api/v1/accounts_controller_spec.rb @@ -18,13 +18,13 @@ RSpec.describe 'Accounts API', type: :request do it 'calls account builder' do allow(account_builder).to receive(:perform).and_return([user, account]) - params = { account_name: 'test', email: email, user: nil, user_full_name: user_full_name } + params = { account_name: 'test', email: email, user: nil, user_full_name: user_full_name, password: 'Password1!' } post api_v1_accounts_url, params: params, as: :json - expect(AccountBuilder).to have_received(:new).with(params.merge(confirmed: false)) + expect(AccountBuilder).to have_received(:new).with(params.except(:password).merge(user_password: params[:password])) expect(account_builder).to have_received(:perform) expect(response.headers.keys).to include('access-token', 'token-type', 'client', 'expiry', 'uid') end @@ -38,44 +38,11 @@ RSpec.describe 'Accounts API', type: :request do params: params, as: :json - expect(AccountBuilder).to have_received(:new).with(params.merge(confirmed: false)) + expect(AccountBuilder).to have_received(:new).with(params.merge(user_password: params[:password])) expect(account_builder).to have_received(:perform) expect(response).to have_http_status(:forbidden) expect(response.body).to eq({ message: I18n.t('errors.signup.failed') }.to_json) end - - it 'ignores confirmed param when called with out super admin token' do - allow(account_builder).to receive(:perform).and_return(nil) - - params = { account_name: 'test', email: email, confirmed: true, user: nil, user_full_name: user_full_name } - - post api_v1_accounts_url, - params: params, - as: :json - - expect(AccountBuilder).to have_received(:new).with(params.merge(confirmed: false)) - expect(account_builder).to have_received(:perform) - expect(response).to have_http_status(:forbidden) - expect(response.body).to eq({ message: I18n.t('errors.signup.failed') }.to_json) - end - end - - context 'when called with super admin token' do - let(:super_admin) { create(:super_admin) } - - it 'calls account builder with confirmed true when confirmed param is passed' do - params = { account_name: 'test', email: email, confirmed: true, user_full_name: user_full_name } - - post api_v1_accounts_url, - params: params, - headers: { api_access_token: super_admin.access_token.token }, - as: :json - - created_user = User.find_by(email: email) - expect(created_user.confirmed?).to eq(true) - expect(response.headers.keys).to include('access-token', 'token-type', 'client', 'expiry', 'uid') - expect(response.body).to include(created_user.access_token.token) - end end context 'when ENABLE_ACCOUNT_SIGNUP env variable is set to false' do diff --git a/spec/controllers/api/v1/profiles_controller_spec.rb b/spec/controllers/api/v1/profiles_controller_spec.rb index 0a936c6d4..13c2511ad 100644 --- a/spec/controllers/api/v1/profiles_controller_spec.rb +++ b/spec/controllers/api/v1/profiles_controller_spec.rb @@ -44,7 +44,7 @@ RSpec.describe 'Profile API', type: :request do it 'updates the name & email' do new_email = Faker::Internet.email put '/api/v1/profile', - params: { profile: { name: 'test', 'email': new_email } }, + params: { profile: { name: 'test', email: new_email } }, headers: agent.create_new_auth_token, as: :json diff --git a/spec/controllers/devise/confirmations_controller_spec.rb b/spec/controllers/devise/confirmations_controller_spec.rb index 6970b5777..d01ecb196 100644 --- a/spec/controllers/devise/confirmations_controller_spec.rb +++ b/spec/controllers/devise/confirmations_controller_spec.rb @@ -18,12 +18,8 @@ RSpec.describe 'Token Confirmation', type: :request do expect(response.status).to eq 200 end - it 'returns message "Success"' do - expect(response_json[:message]).to eq 'Success' - end - - it 'returns "redirect_url"' do - expect(response_json[:redirect_url]).to include '/app/auth/password/edit?config=default&redirect_url=&reset_password_token' + it 'returns "auth data"' do + expect(response.body).to include('john.doe@gmail.com') end end diff --git a/spec/controllers/devise/session_controller_spec.rb b/spec/controllers/devise/session_controller_spec.rb index ef51f5e4b..957604be3 100644 --- a/spec/controllers/devise/session_controller_spec.rb +++ b/spec/controllers/devise/session_controller_spec.rb @@ -17,10 +17,10 @@ RSpec.describe 'Session', type: :request do end context 'when it is valid credentials' do - let!(:user) { create(:user, password: 'test1234', account: account) } + let!(:user) { create(:user, password: 'Password1!', account: account) } it 'returns successful auth response' do - params = { email: user.email, password: 'test1234' } + params = { email: user.email, password: 'Password1!' } post new_user_session_url, params: params, @@ -32,7 +32,7 @@ RSpec.describe 'Session', type: :request do end context 'when it is invalid sso auth token' do - let!(:user) { create(:user, password: 'test1234', account: account) } + let!(:user) { create(:user, password: 'Password1!', account: account) } it 'returns unauthorized' do params = { email: user.email, sso_auth_token: SecureRandom.hex(32) } @@ -46,7 +46,7 @@ RSpec.describe 'Session', type: :request do end context 'when with valid sso auth token' do - let!(:user) { create(:user, password: 'test1234', account: account) } + let!(:user) { create(:user, password: 'Password1!', account: account) } it 'returns successful auth response' do params = { email: user.email, sso_auth_token: user.generate_sso_auth_token } diff --git a/spec/controllers/platform/api/v1/users_controller_spec.rb b/spec/controllers/platform/api/v1/users_controller_spec.rb index 7f9167b14..e25f3cb42 100644 --- a/spec/controllers/platform/api/v1/users_controller_spec.rb +++ b/spec/controllers/platform/api/v1/users_controller_spec.rb @@ -94,7 +94,7 @@ RSpec.describe 'Platform Users API', type: :request do let(:platform_app) { create(:platform_app) } it 'creates a new user and permissible for the user' do - post '/platform/api/v1/users/', params: { name: 'test', email: 'test@test.com', password: 'password123' }, + post '/platform/api/v1/users/', params: { name: 'test', email: 'test@test.com', password: 'Password1!' }, headers: { api_access_token: platform_app.access_token.token }, as: :json expect(response).to have_http_status(:success) @@ -105,7 +105,7 @@ RSpec.describe 'Platform Users API', type: :request do it 'fetch existing user and creates permissible for the user' do create(:user, name: 'old test', email: 'test@test.com') - post '/platform/api/v1/users/', params: { name: 'test', email: 'test@test.com', password: 'password123' }, + post '/platform/api/v1/users/', params: { name: 'test', email: 'test@test.com', password: 'Password1!' }, headers: { api_access_token: platform_app.access_token.token }, as: :json expect(response).to have_http_status(:success) diff --git a/spec/controllers/super_admin/access_tokens_controller_spec.rb b/spec/controllers/super_admin/access_tokens_controller_spec.rb index bb516bc04..ace011663 100644 --- a/spec/controllers/super_admin/access_tokens_controller_spec.rb +++ b/spec/controllers/super_admin/access_tokens_controller_spec.rb @@ -2,6 +2,7 @@ require 'rails_helper' RSpec.describe 'Super Admin access tokens API', type: :request do let(:super_admin) { create(:super_admin) } + let!(:platform_app) { create(:platform_app) } describe 'GET /super_admin/access_tokens' do context 'when it is an unauthenticated super admin' do @@ -16,7 +17,7 @@ RSpec.describe 'Super Admin access tokens API', type: :request do sign_in super_admin get '/super_admin/access_tokens' expect(response).to have_http_status(:success) - expect(response.body).to include(super_admin.access_token.token) + expect(response.body).to include(platform_app.access_token.token) end end end diff --git a/spec/factories/super_admins.rb b/spec/factories/super_admins.rb index 88e488f68..fc0b485c5 100644 --- a/spec/factories/super_admins.rb +++ b/spec/factories/super_admins.rb @@ -1,6 +1,6 @@ FactoryBot.define do factory :super_admin do email { "admin@#{SecureRandom.uuid}.com" } - password { 'password' } + password { 'Password1!' } end end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index bbe1e6acd..cbebfa838 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -14,7 +14,7 @@ FactoryBot.define do name { Faker::Name.name } display_name { Faker::Name.first_name } email { display_name + "@#{SecureRandom.uuid}.com" } - password { 'password' } + password { 'Password1!' } after(:build) do |user, evaluator| user.skip_confirmation! if evaluator.skip_confirmation diff --git a/spec/lib/chatwoot_hub_spec.rb b/spec/lib/chatwoot_hub_spec.rb index 26d75365f..2cd5c6be1 100644 --- a/spec/lib/chatwoot_hub_spec.rb +++ b/spec/lib/chatwoot_hub_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe ChatwootHub do it 'get latest version from chatwoot hub' do version = '1.1.1' - allow(RestClient).to receive(:get).and_return({ 'version': version }.to_json) + allow(RestClient).to receive(:get).and_return({ version: version }.to_json) expect(described_class.latest_version).to eq version expect(RestClient).to have_received(:get).with(described_class::BASE_URL, { params: described_class.instance_config }) end