From 55ca68bb3a6fd03a394ff628b6162af377d50a2b Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Sun, 13 Jan 2019 21:13:20 +0300 Subject: [PATCH 01/16] Add invite users from admin panel --- app/controllers/admin/users_controller.rb | 135 ++++++++++-------- app/mailers/.keep | 0 app/operations/ops/admin/user/invite.rb | 46 ++++++ app/views/admin/users/_filter.html.slim | 2 +- app/views/admin/users/_prolongation.html.slim | 2 +- app/views/admin/users/_submenu.html.slim | 6 +- app/views/admin/users/_table.html.slim | 24 ++-- app/views/admin/users/edit.html.slim | 18 +-- app/views/admin/users/index.html.slim | 12 +- app/views/admin/users/new.html.slim | 10 ++ app/views/admin/users/payers.html.slim | 10 +- app/views/admin/users/show.html.slim | 2 +- .../admin/users/this_month_payers.html.slim | 10 +- config/environments/development.rb | 4 +- config/locales/admin/en.yml | 27 ++++ config/locales/admin/ru.yml | 31 +++- config/locales/en.yml | 3 + config/locales/ru.yml | 3 + config/routes.rb | 58 ++++---- 19 files changed, 278 insertions(+), 125 deletions(-) delete mode 100644 app/mailers/.keep create mode 100644 app/operations/ops/admin/user/invite.rb create mode 100644 app/views/admin/users/new.html.slim diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 3b4f96af..37dbd5ae 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -1,81 +1,95 @@ -class Admin::UsersController < Admin::BaseController - before_action :find_user, only: [:show, :edit, :update, :withdraw, - :prolongate, :payment, :enable_test_period, - :disable_test_period, :force_disconnect - ] - decorates_assigned :user - - def index - @users = users.page params[:page] - end +# frozen_string_literal: true - def payers - @users = users.payers.page params[:page] - end +class Admin + class UsersController < Admin::BaseController + before_action :find_user, only: %i[show edit update withdraw + prolongate payment enable_test_period + disable_test_period force_disconnect] + decorates_assigned :user - def this_month_payers - @users = users.this_month_payers.page params[:page] - end + def index + @users = users.page params[:page] + end - def show - end + def payers + @users = users.payers.page params[:page] + end - def edit - end + def this_month_payers + @users = users.this_month_payers.page params[:page] + end + + def show; end - def update - if @user.update(resource_params) - redirect_to admin_users_path, notice: "Пользователь успешно обновлен" - else - render :edit + def new + @user = User.new end - end - def withdraw - Withdrawer.single_withdraw(@user) - redirect_to admin_users_path, notice: "Списано" - end + def create + result = ::Ops::Admin::User::Invite.new(params: resource_params).call + if result[:success] + redirect_to admin_users_path, notice: t('admin.users.notices.created') + else + @user = result[:user] + render :new + end + end - def prolongate - @user.withdrawals.last.withdrawal_prolongations.create!(days_number: params[:withdrawal_prolongation][:days_number]) - redirect_to admin_user_path(@user), notice: 'Подписка пользователя успешно продлена' - end + def edit; end - def payment - payment = @user.payments.create!(payment_params) - payment.accept! - redirect_to admin_user_path(@user), notice: t('admin.users.notices.payment_created') - end + def update + if @user.update(resource_params) + redirect_to admin_users_path, notice: t('admin.users.notices.updated') + else + render :edit + end + end - def emails_export - users = User.search(search_params).result - render text: Admin::UsersSerializer.new(users, :csv).emails - end + def withdraw + Withdrawer.single_withdraw(@user) + redirect_to admin_users_path, notice: t('admin.users.notices.write_off') + end - def enable_test_period - @user.test_period.enable! - UserMailer.test_period_enabled(@user).deliver_now - redirect_to admin_user_path(@user), notice: t('admin.users.notices.test_period_enabled') - end + def prolongate + @user.withdrawals.last.withdrawal_prolongations.create!(days_number: days_number_prolongate) + redirect_to admin_user_path(@user), notice: t('admin.users.notices.prolongated') + end - def disable_test_period - @user.test_period.disable! - redirect_to admin_user_path(@user), notice: t('admin.users.notices.test_period_disabled') - end + def payment + payment = @user.payments.create!(payment_params) + payment.accept! + redirect_to admin_user_path(@user), notice: t('admin.users.notices.payment_created') + end - def force_disconnect - ForcedDisconnect.new(@user).invoke - redirect_to admin_user_path(@user), notice: t('admin.users.notices.disconnected') - end + def emails_export + users = User.search(search_params).result + render text: Admin::UsersSerializer.new(users, :csv).emails + end - private + def enable_test_period + @user.test_period.enable! + UserMailer.test_period_enabled(@user).deliver_now + redirect_to admin_user_path(@user), notice: t('admin.users.notices.test_period_enabled') + end + + def disable_test_period + @user.test_period.disable! + redirect_to admin_user_path(@user), notice: t('admin.users.notices.test_period_disabled') + end + + def force_disconnect + ForcedDisconnect.new(@user).invoke + redirect_to admin_user_path(@user), notice: t('admin.users.notices.disconnected') + end + + private def find_user @user = User.find(params[:id]) end def users - search.result.order("id DESC") + search.result.order('id DESC') end def search @@ -99,4 +113,9 @@ def payment_params def resource_params params.require(:user).permit(:email, :plan_id, :state, :balance, :period_length) end + + def days_number_prolongate + params[:withdrawal_prolongation][:days_number] + end + end end diff --git a/app/mailers/.keep b/app/mailers/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/app/operations/ops/admin/user/invite.rb b/app/operations/ops/admin/user/invite.rb new file mode 100644 index 00000000..e6a9f1a9 --- /dev/null +++ b/app/operations/ops/admin/user/invite.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +module Ops + module Admin + module User + class Invite + attr_reader :params + + def initialize(params:) + @params = params + end + + def call + user.skip_confirmation_notification! + return error_create_user unless user.save + + build_invited_user! + success_result + end + + private + + def build_invited_user! + user.confirm + user.send_reset_password_instructions + end + + def user + @user ||= ::User.new(params.merge(password: generate_password)) + end + + def generate_password + SecureRandom.alphanumeric + end + + def error_create_user + { success: false, user: user } + end + + def success_result + { success: true, user: user } + end + end + end + end +end diff --git a/app/views/admin/users/_filter.html.slim b/app/views/admin/users/_filter.html.slim index 9f77e144..aff03256 100644 --- a/app/views/admin/users/_filter.html.slim +++ b/app/views/admin/users/_filter.html.slim @@ -1,5 +1,5 @@ .col-md-12.d-flex.justify-content-end - = search_form_for [:admin, search], class: 'form-inline my-3' do |f| + = search_form_for [:admin, search], class: 'form-inline mb-5' do |f| .form-group.mr-3 = f.label :email_cont, class: 'mr-3' = f.text_field :email_cont, class: 'form-control' diff --git a/app/views/admin/users/_prolongation.html.slim b/app/views/admin/users/_prolongation.html.slim index e3922064..306f6910 100644 --- a/app/views/admin/users/_prolongation.html.slim +++ b/app/views/admin/users/_prolongation.html.slim @@ -1,5 +1,5 @@ - if can_be_prolongated? @user - legend Продление подписки + legend= t('admin.users.prolongation') = simple_form_for [:admin, WithdrawalProlongation.new], url: prolongate_admin_user_path(@user), method: :put do |f| = f.input :days_number = f.submit t('global.apply'), class: 'btn btn-primary' diff --git a/app/views/admin/users/_submenu.html.slim b/app/views/admin/users/_submenu.html.slim index e8dded99..9c64c5b1 100644 --- a/app/views/admin/users/_submenu.html.slim +++ b/app/views/admin/users/_submenu.html.slim @@ -1,4 +1,4 @@ ul.list-unstyled - li= link_to 'Все пользователи', admin_users_path - li= link_to 'Оплатившие', payers_admin_users_path - li= link_to 'Оплатившие в текущем месяце', this_month_payers_admin_users_path + li= link_to t('admin.users.all_users'), admin_users_path + li= link_to t('admin.users.payers'), payers_admin_users_path + li= link_to t('admin.users.this_month_payers'), this_month_payers_admin_users_path diff --git a/app/views/admin/users/_table.html.slim b/app/views/admin/users/_table.html.slim index fff19162..b198f63d 100644 --- a/app/views/admin/users/_table.html.slim +++ b/app/views/admin/users/_table.html.slim @@ -1,17 +1,17 @@ table.table thead tr - th ID - th Email - th Тариф - th Дата регистрации - th Баланс - th Количество подключений - th Входил в биллинг - th Оборот - th Неудачных списаний - th Статус - th Действия + th= 'ID' + th= 'Email' + th= t('admin.tables.plan') + th= t('admin.tables.registration_date') + th= t('admin.tables.balance') + th= t('admin.tables.number_connections') + th= t('admin.tables.logged_in_billing') + th= t('admin.tables.turnover') + th= t('admin.tables.unsuccessful_charges') + th= t('admin.tables.status') + th= t('admin.tables.actions') - @users.each do |user| tr class="#{background_highlight(user)}" @@ -30,7 +30,7 @@ table.table li.pb-1 = link_to t('admin.links.edit'), edit_admin_user_path(user), class: 'btn btn-sm btn-info' li - = link_to 'Списать', withdraw_admin_user_path(user), method: :put, class: 'btn btn-sm btn-warning' + = link_to t('admin.links.write_off'), withdraw_admin_user_path(user), method: :put, class: 'btn btn-sm btn-warning' = render partial: 'admin/shared/paginate', locals: {collection: @users} diff --git a/app/views/admin/users/edit.html.slim b/app/views/admin/users/edit.html.slim index 849d22bc..04b5c10b 100644 --- a/app/views/admin/users/edit.html.slim +++ b/app/views/admin/users/edit.html.slim @@ -1,9 +1,11 @@ -= page_title('Редактирование пользователя', 'user') += page_title(t('admin.users.title'), 'user', "#{t('admin.users.edit')} #{@user.email}") -= simple_form_for [:admin, @user], html: { class: 'form-horizontal' },wrapper: :horizontal_form do |f| - = f.input :email - = f.input :balance - = f.input :plan_id, as: :select, collection: Plan.all.map { |p| [p.name, p.id] }, include_blank: false - = f.input :state, as: :select, collection: User.state_machine.states.map { |s| [s.name, s.name] } - = f.input :period_length, input_html: { value: f.object.period_length || User::DEFAULT_TEST_PERIOD } - = f.submit 'Сохранить', class: 'btn btn-primary' +.row.mt-5 + .col + = simple_form_for [:admin, @user], html: { class: 'form-horizontal' },wrapper: :horizontal_form do |f| + = f.input :email + = f.input :balance + = f.input :plan_id, as: :select, collection: Plan.all.map { |p| [p.name, p.id] }, include_blank: false + = f.input :state, as: :select, collection: User.state_machine.states.map { |s| [s.name, s.name] } + = f.input :period_length, input_html: { value: f.object.period_length || User::DEFAULT_TEST_PERIOD } + = f.submit t('admin.buttons.apply'), class: 'btn btn-primary' diff --git a/app/views/admin/users/index.html.slim b/app/views/admin/users/index.html.slim index 14e0c9d9..f1a15b3f 100644 --- a/app/views/admin/users/index.html.slim +++ b/app/views/admin/users/index.html.slim @@ -1,9 +1,13 @@ -= page_title('Все пользователи', 'user') += page_title(t('admin.users.title'), 'user', t('admin.users.all')) -.row - .col +.row.mt-3 + .col.col-md-6 = link_to t('admin.links.email_list'), emails_export_admin_users_path(q: params[:q]), target: '_blank', class: 'btn btn-primary' = render partial: 'filter' -= render partial: 'submenu' +.row.mb-3 + .col-md-6 + = render partial: 'submenu' + .col-md-6.text-right + = link_to t('admin.links.create'), new_admin_user_path, class: 'btn btn-info' = render partial: 'table' diff --git a/app/views/admin/users/new.html.slim b/app/views/admin/users/new.html.slim new file mode 100644 index 00000000..9bb2d122 --- /dev/null +++ b/app/views/admin/users/new.html.slim @@ -0,0 +1,10 @@ += page_title(t('admin.users.title'), 'user', t('admin.users.new')) + +.row.mt-5 + .col + = simple_form_for [:admin, @user], html: { class: 'form-horizontal' },wrapper: :horizontal_form do |f| + = f.input :email + = f.input :balance + = f.input :plan_id, as: :select, collection: Plan.all.map { |p| [p.name, p.id] }, include_blank: false + = f.input :period_length, input_html: { value: f.object.period_length || User::DEFAULT_TEST_PERIOD } + = f.submit t('admin.buttons.apply'), class: 'btn btn-primary' diff --git a/app/views/admin/users/payers.html.slim b/app/views/admin/users/payers.html.slim index 0d444ef5..61c25334 100644 --- a/app/views/admin/users/payers.html.slim +++ b/app/views/admin/users/payers.html.slim @@ -1,7 +1,11 @@ -= page_title('Оплатившие подписку пользователи', 'file-invoice-dollar') += page_title(t('admin.users.title'), 'user', t('admin.users.payers')) -.row +.row.mt-3 = render partial: 'filter' -= render partial: 'submenu' +.row.mb-3 + .col-md-6 + = render partial: 'submenu' + .col-md-6.text-right + = link_to t('admin.links.create'), new_admin_user_path, class: 'btn btn-info' = render partial: 'table' diff --git a/app/views/admin/users/show.html.slim b/app/views/admin/users/show.html.slim index 8b8fb554..a43f1bed 100644 --- a/app/views/admin/users/show.html.slim +++ b/app/views/admin/users/show.html.slim @@ -1,4 +1,4 @@ -= page_title('Просмотр пользователя', 'user') += page_title(t('admin.users.title'), 'user', t('admin.users.show')) = show_for user do |u| diff --git a/app/views/admin/users/this_month_payers.html.slim b/app/views/admin/users/this_month_payers.html.slim index 410a0840..1fd426c3 100644 --- a/app/views/admin/users/this_month_payers.html.slim +++ b/app/views/admin/users/this_month_payers.html.slim @@ -1,7 +1,11 @@ -= page_title('Оплатившие в текущем месяце', 'file-invoice-dollar') += page_title(t('admin.users.title'), 'user', t('admin.users.this_month_payers')) -.row +.row.mt-3 = render partial: 'filter' -= render partial: 'submenu' +.row.mb-3 + .col-md-6 + = render partial: 'submenu' + .col-md-6.text-right + = link_to t('admin.links.create'), new_admin_user_path, class: 'btn btn-info' = render partial: 'table' diff --git a/config/environments/development.rb b/config/environments/development.rb index 25d177c8..6c535503 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Smartvpn::Application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -26,5 +28,5 @@ config.assets.debug = true config.action_mailer.delivery_method = :letter_opener - config.action_mailer.default_url_options = { :host => "smartvpn.dev" } + config.action_mailer.default_url_options = { host: 'localhost:3000' } end diff --git a/config/locales/admin/en.yml b/config/locales/admin/en.yml index 20925375..6d86a2dc 100644 --- a/config/locales/admin/en.yml +++ b/config/locales/admin/en.yml @@ -7,26 +7,53 @@ en: sign_in: 'Sign in' staff_entrance: 'Administration' admin: + tables: + plan: 'Plan' + registration_date: 'Registration date' + balance: 'Balance' + number_connections: 'Number of connections' + logged_in_billing: 'Logged in billing' + turnover: 'Turnover' + unsuccessful_charges: 'Unsuccessful charges' + status: 'Status' + actions: 'Actions' links: edit: 'Edit' email_list: 'Email list' + create: 'Create' + write_off: 'Write off' buttons: filter: 'Filter' + apply: 'Apply' users: + title: 'Users' + all: 'All' + all_users: 'All users' + show: 'Show' + new: 'Create new' + edit: 'Edit' + payers: 'Paid subscription' + this_month_payers: 'Paid in the current month' current_connection: 'Current connection' not_connected: 'No connection' connected_to_server_at: 'Connected to server %{server} at %{date}' not_paid: 'Unpaid' prolongation_not_possible: 'Impossible to prolong. User has no active payment' + prolongation: 'Subscription renewal' new_payment: 'Top up balance' test_period: 'Trial account' test_period_until: 'Active from %{start} to %{finish}' filter: never_paid_users: 'Never paying users' notices: + created: 'User created successfully' + updated: 'User updated successfully' + write_off: 'Write off' + prolongated: 'User subscription successfully renewed' payment_created: "User's account balance top-up successfully" test_period_enabled: 'Trial period activated' test_period_disabled: 'Trial period deactivated' + disconnected: 'User successfully disconnected' pay_systems: states: enabled: 'Activated' diff --git a/config/locales/admin/ru.yml b/config/locales/admin/ru.yml index b88a1a7e..2898edf6 100644 --- a/config/locales/admin/ru.yml +++ b/config/locales/admin/ru.yml @@ -7,26 +7,53 @@ ru: sign_in: 'Войти' staff_entrance: 'Служебный вход' admin: + tables: + plan: 'Тариф' + registration_date: 'Дата регистрации' + balance: 'Баланс' + number_connections: 'Количество подключений' + logged_in_billing: 'Входил в биллинг' + turnover: 'Оборот' + unsuccessful_charges: 'Неудачных списаний' + status: 'Статус' + actions: 'Действия' links: edit: 'Редактировать' email_list: 'Список email' + create: 'Создать' + write_off: 'Списать' buttons: filter: 'Фильтер' + apply: 'Применить' users: + title: 'Пользователи' + all: 'Все' + all_users: 'Все пользователи' + show: 'Просмотр' + new: 'Создать нового' + edit: 'Редактировать' + payers: 'Оплатившие подписку' + this_month_payers: 'Оплатившие в текущем месяце' current_connection: 'Текущее подключение' not_connected: 'Нет подключения' - connected_to_server_at: "Подключен к серверу %{server} в %{date}" + connected_to_server_at: 'Подключен к серверу %{server} в %{date}' not_paid: 'Не оплачен' - prolongation_not_possible: "Пролонгация невозможна, у пользователя нет активного платежа" + prolongation_not_possible: 'Пролонгация невозможна, у пользователя нет активного платежа' + prolongation: 'Продление подписки' new_payment: 'Пополнение баланса' test_period: 'Тестовый доступ' test_period_until: 'Активен c %{start} до %{finish}' filter: never_paid_users: 'С нулевым оборотом' notices: + created: 'Пользователь успешно создан' + updated: 'Пользователь успешно обновлен' + write_off: 'Списано' + prolongated: 'Подписка пользователя успешно продлена' payment_created: 'Баланс пользователя успешно пополнен' test_period_enabled: 'Тестовый период активирован' test_period_disabled: 'Тестовый период деактивирован' + disconnected: 'Пользователь успешно отключен' pay_systems: states: enabled: 'Включена' diff --git a/config/locales/en.yml b/config/locales/en.yml index 133bd02a..faff92ff 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,4 +1,7 @@ en: + mailers: + invite_user_mailer: + subject: 'An account has been created for you' date: formats: default: '%d.%m.%Y' diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 5cd6c91a..39f7b642 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -1,4 +1,7 @@ ru: + mailers: + invite_user_mailer: + subject: 'Вам был создан аккаунт' date: formats: default: "%d.%m.%Y" diff --git a/config/routes.rb b/config/routes.rb index 8e61b3f6..597f58f7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + Smartvpn::Application.routes.draw do require 'sidekiq/web' devise_for :users, controllers: { - registrations: "users/registrations", - sessions: "users/sessions", + registrations: 'users/registrations', + sessions: 'users/sessions', passwords: 'users/passwords' } devise_for :admins, controllers: { @@ -11,15 +13,15 @@ } namespace :billing do - root to: "home#index" + root to: 'home#index' - resources :payments, only: [:index, :new, :create] do + resources :payments, only: %i[index new create] do member do get :merchant end end resources :promotions, only: [:create] - resources :options, only: [:index, :create, :update, :destroy] do + resources :options, only: %i[index create update destroy] do put :toggle, on: :member end resources :referrers, only: [:index] @@ -27,33 +29,33 @@ get :download_config, on: :member end - scope "/webmoney" do - get "fail", to: "webmoney#fail", as: :webmoney_fail - get "success", to: "webmoney#success", as: :webmoney_success - match "result", to: "webmoney#result", as: :webmoney_result, via: [:get, :post] + scope '/webmoney' do + get 'fail', to: 'webmoney#fail', as: :webmoney_fail + get 'success', to: 'webmoney#success', as: :webmoney_success + match 'result', to: 'webmoney#result', as: :webmoney_result, via: %i[get post] end - scope "/robokassa" do - get "fail", to: "robokassa#fail", as: :robokassa_fail - get "success", to: "robokassa#success", as: :robokassa_success - post "result", to: "robokassa#result", as: :robokassa_result + scope '/robokassa' do + get 'fail', to: 'robokassa#fail', as: :robokassa_fail + get 'success', to: 'robokassa#success', as: :robokassa_success + post 'result', to: 'robokassa#result', as: :robokassa_result end - scope "/paypal" do - get "fail", to: "paypal#fail", as: :paypal_fail - get "success", to: "paypal#success", as: :paypal_success - match "result", to: "paypal#result", as: :paypal_result, via: [:get, :post] + scope '/paypal' do + get 'fail', to: 'paypal#fail', as: :paypal_fail + get 'success', to: 'paypal#success', as: :paypal_success + match 'result', to: 'paypal#result', as: :paypal_result, via: %i[get post] end end namespace :admin do - root to: "home#index" + root to: 'home#index' resources :servers do get :generate_config, on: :member end resources :plans - resources :pay_systems, except: [:destroy] - resources :users, only: [:index, :show, :edit, :update] do + resources :pay_systems, except: :destroy + resources :users, except: :destroy do collection do get :payers get :this_month_payers @@ -68,7 +70,7 @@ put :force_disconnect end end - resources :connections, only: [:index, :show] do + resources :connections, only: %i[index show] do get :active, on: :collection end resources :traffic_reports, only: [:index] do @@ -84,16 +86,16 @@ get :withdrawals end end - resources :promos, only: [:index, :new, :create, :edit, :update] - resources :options, only: [:index, :new, :create, :edit, :update] + resources :promos, only: %i[index new create edit update] + resources :options, only: %i[index new create edit update] resources :referrers, only: [:index] end namespace :api do - match "/activate", to: "servers#activate", via: [:post] - match "/auth", to: "authentication#auth", via: [:post] - match "/disconnect", to: "connection#disconnect", via: [:post] - match "/connect", to: "connection#connect", via: [:post] + match '/activate', to: 'servers#activate', via: [:post] + match '/auth', to: 'authentication#auth', via: [:post] + match '/disconnect', to: 'connection#disconnect', via: [:post] + match '/connect', to: 'connection#connect', via: [:post] end match '/referrer', to: 'referrers#set_referrer', via: [:get] @@ -101,6 +103,6 @@ authenticate :admin do mount Sidekiq::Web, at: '/sidekiq' - mount PgHero::Engine, at: "pghero" + mount PgHero::Engine, at: 'pghero' end end From 49a27b6d79fcb1b71610c5e6713ca0db0aab6791 Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Sun, 13 Jan 2019 22:24:10 +0300 Subject: [PATCH 02/16] Add attachment to letter --- app/mailers/invite_user_mailer.rb | 19 +++++++++++++++++++ app/operations/ops/admin/user/invite.rb | 1 + app/services/server_config_builder.rb | 19 ++++++++++++------- .../invite_user_mailer/notify.html.slim | 3 +++ .../user_mailer/_signature.html.slim | 0 .../user_mailer/balance_withdrawal.html.slim | 0 .../could_not_withdraw_funds.html.slim | 0 .../user_mailer/funds_recieved.html.slim | 0 .../user_mailer/test_period_enabled.html.slim | 0 .../unpaid_user_notification.html.slim | 0 app/workers/invite_user_mail_worker.rb | 11 +++++++++++ config/application.rb | 18 ++++++++++-------- 12 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 app/mailers/invite_user_mailer.rb create mode 100644 app/views/mailers/invite_user_mailer/notify.html.slim rename app/views/{ => mailers}/user_mailer/_signature.html.slim (100%) rename app/views/{ => mailers}/user_mailer/balance_withdrawal.html.slim (100%) rename app/views/{ => mailers}/user_mailer/could_not_withdraw_funds.html.slim (100%) rename app/views/{ => mailers}/user_mailer/funds_recieved.html.slim (100%) rename app/views/{ => mailers}/user_mailer/test_period_enabled.html.slim (100%) rename app/views/{ => mailers}/user_mailer/unpaid_user_notification.html.slim (100%) create mode 100644 app/workers/invite_user_mail_worker.rb diff --git a/app/mailers/invite_user_mailer.rb b/app/mailers/invite_user_mailer.rb new file mode 100644 index 00000000..b00722e5 --- /dev/null +++ b/app/mailers/invite_user_mailer.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class InviteUserMailer < ActionMailer::Base + default from: 'admin@smartvpn.biz' + + def notify(user) + @user = user + server = user.plan.servers.last + attachments["#{server.hostname}.ovpn"] = File.read(generate_config(server).path) + mail(to: @user.email, subject: t('mailers.invite_user_mailer.subject')) + end + + private + + def generate_config(server) + binding.pry + ServerConfigBuilder.new(server).generate_config + end +end diff --git a/app/operations/ops/admin/user/invite.rb b/app/operations/ops/admin/user/invite.rb index e6a9f1a9..0654e8ed 100644 --- a/app/operations/ops/admin/user/invite.rb +++ b/app/operations/ops/admin/user/invite.rb @@ -23,6 +23,7 @@ def call def build_invited_user! user.confirm user.send_reset_password_instructions + InviteUserMailWorker.perform_async(user.id) end def user diff --git a/app/services/server_config_builder.rb b/app/services/server_config_builder.rb index 7dbca2c7..af97b2a1 100644 --- a/app/services/server_config_builder.rb +++ b/app/services/server_config_builder.rb @@ -1,5 +1,5 @@ class ServerConfigBuilder - attr_accessor :config + attr_accessor :server def initialize(server) @server = server @@ -10,7 +10,8 @@ def generate_config new_line = rewrite_line(line) config.append_line(new_line) end - config + File.write(tempfile.path, config) + tempfile end def to_text @@ -44,20 +45,24 @@ def sample_config_path def rewrite_mappings { - "proto" => protocol, - "remote" => "#{host} #{port}" + 'proto' => protocol, + 'remote' => "#{host} #{port}" } end def protocol - @server.protocol + @protocol ||= server.protocol end def host - @server.hostname + @host ||= server.hostname end def port - @server.port + @port ||= server.port + end + + def tempfile + @tempfile ||= Tempfile.new(%w[server-config- .ovpn]) end end diff --git a/app/views/mailers/invite_user_mailer/notify.html.slim b/app/views/mailers/invite_user_mailer/notify.html.slim new file mode 100644 index 00000000..adf6d2d9 --- /dev/null +++ b/app/views/mailers/invite_user_mailer/notify.html.slim @@ -0,0 +1,3 @@ +p= "Hello #{@user.email}!" +p= 'Attached is a configuration file' + diff --git a/app/views/user_mailer/_signature.html.slim b/app/views/mailers/user_mailer/_signature.html.slim similarity index 100% rename from app/views/user_mailer/_signature.html.slim rename to app/views/mailers/user_mailer/_signature.html.slim diff --git a/app/views/user_mailer/balance_withdrawal.html.slim b/app/views/mailers/user_mailer/balance_withdrawal.html.slim similarity index 100% rename from app/views/user_mailer/balance_withdrawal.html.slim rename to app/views/mailers/user_mailer/balance_withdrawal.html.slim diff --git a/app/views/user_mailer/could_not_withdraw_funds.html.slim b/app/views/mailers/user_mailer/could_not_withdraw_funds.html.slim similarity index 100% rename from app/views/user_mailer/could_not_withdraw_funds.html.slim rename to app/views/mailers/user_mailer/could_not_withdraw_funds.html.slim diff --git a/app/views/user_mailer/funds_recieved.html.slim b/app/views/mailers/user_mailer/funds_recieved.html.slim similarity index 100% rename from app/views/user_mailer/funds_recieved.html.slim rename to app/views/mailers/user_mailer/funds_recieved.html.slim diff --git a/app/views/user_mailer/test_period_enabled.html.slim b/app/views/mailers/user_mailer/test_period_enabled.html.slim similarity index 100% rename from app/views/user_mailer/test_period_enabled.html.slim rename to app/views/mailers/user_mailer/test_period_enabled.html.slim diff --git a/app/views/user_mailer/unpaid_user_notification.html.slim b/app/views/mailers/user_mailer/unpaid_user_notification.html.slim similarity index 100% rename from app/views/user_mailer/unpaid_user_notification.html.slim rename to app/views/mailers/user_mailer/unpaid_user_notification.html.slim diff --git a/app/workers/invite_user_mail_worker.rb b/app/workers/invite_user_mail_worker.rb new file mode 100644 index 00000000..8ce1211e --- /dev/null +++ b/app/workers/invite_user_mail_worker.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class InviteUserMailWorker + include Sidekiq::Worker + sidekiq_options queue: :mailers + + def perform(user_id) + user = User.find(user_id) + InviteUserMailer.notify(user).deliver_now + end +end diff --git a/config/application.rb b/config/application.rb index 71e44cad..07a11c74 100644 --- a/config/application.rb +++ b/config/application.rb @@ -3,7 +3,7 @@ require 'rails/all' # Assets should be precompiled for production (so we don't need the gems loaded then) -Bundler.require(*Rails.groups(assets: %w(development test))) +Bundler.require(*Rails.groups(assets: %w[development test])) module Smartvpn class Application < Rails::Application @@ -14,19 +14,21 @@ class Application < Rails::Application # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. # config.time_zone = 'Central Time (US & Canada)' - config.autoload_paths += %W(#{config.root}/app/models/connections) - config.autoload_paths += %W(#{config.root}/app/models/traffic_reports) - config.autoload_paths += %W(#{config.root}/app/models/dto) - config.autoload_paths += %W(#{config.root}/app/models/promoters) - config.autoload_paths += %W(#{config.root}/lib) - config.autoload_paths += %W(#{config.root}/lib/exceptions) + config.autoload_paths += %W[#{config.root}/app/models/connections] + config.autoload_paths += %W[#{config.root}/app/models/traffic_reports] + config.autoload_paths += %W[#{config.root}/app/models/dto] + config.autoload_paths += %W[#{config.root}/app/models/promoters] + config.autoload_paths += %W[#{config.root}/lib] + config.autoload_paths += %W[#{config.root}/lib/exceptions] + + config.paths['app/views'].unshift(Rails.root.join('app/views/mailers')) # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')] config.i18n.default_locale = :en I18n.enforce_available_locales = true - config.assets.precompile += ['admin.js', 'admin.css'] + config.assets.precompile += %w[admin.js admin.scss] config.active_record.raise_in_transactional_callbacks = true end end From 55a6fe2fc6cfaa58d81ff0ee6d2da0c754dafc7b Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Sun, 13 Jan 2019 23:14:14 +0300 Subject: [PATCH 03/16] refactoring server config builder and emails --- .env.sample | 2 ++ Gemfile | 7 ++-- app/controllers/admin/servers_controller.rb | 4 +-- app/mailers/invite_user_mailer.rb | 3 +- app/services/server_config_builder.rb | 40 +++++++++------------ config/environments/production.rb | 11 +++--- 6 files changed, 31 insertions(+), 36 deletions(-) diff --git a/.env.sample b/.env.sample index 0b4045b8..bbec1e0e 100644 --- a/.env.sample +++ b/.env.sample @@ -1 +1,3 @@ SECRET_TOKEN= +EMAIL_USER= +EMAIL_PASS= diff --git a/Gemfile b/Gemfile index 558887f9..d2af2f86 100644 --- a/Gemfile +++ b/Gemfile @@ -40,6 +40,10 @@ gem 'russian_central_bank' gem 'show_for', github: 'plataformatec/show_for' gem 'whenever', '0.9.0', require: false +gem 'dotenv-rails' +gem 'factory_girl_rails', '~> 4.0' +gem 'faker' + gem 'sidekiq' gem 'sinatra', require: false @@ -83,9 +87,6 @@ group :test, :development do gem 'rb-fchange', require: false gem 'vcr' # TODO: switch to stable version - gem 'dotenv-rails' - gem 'factory_girl_rails', '~> 4.0' - gem 'faker' gem 'pry-rails' gem 'rspec-rails' gem 'selenium-webdriver' diff --git a/app/controllers/admin/servers_controller.rb b/app/controllers/admin/servers_controller.rb index 89380ec3..3e2949b9 100644 --- a/app/controllers/admin/servers_controller.rb +++ b/app/controllers/admin/servers_controller.rb @@ -38,9 +38,9 @@ def destroy end def generate_config - builder = ServerConfigBuilder.new(@server) + builder = ServerConfigBuilder.new(server: @server) config_file = builder.generate_config - send_data config_file.to_text, filename: "#{@server.hostname}.ovpn" + send_data File.read(config_file.path), filename: "#{@server.hostname}.ovpn" end private diff --git a/app/mailers/invite_user_mailer.rb b/app/mailers/invite_user_mailer.rb index b00722e5..8db3ae51 100644 --- a/app/mailers/invite_user_mailer.rb +++ b/app/mailers/invite_user_mailer.rb @@ -13,7 +13,6 @@ def notify(user) private def generate_config(server) - binding.pry - ServerConfigBuilder.new(server).generate_config + ServerConfigBuilder.new(server: server).generate_config end end diff --git a/app/services/server_config_builder.rb b/app/services/server_config_builder.rb index af97b2a1..c6ba2965 100644 --- a/app/services/server_config_builder.rb +++ b/app/services/server_config_builder.rb @@ -1,42 +1,30 @@ +# frozen_string_literal: true + class ServerConfigBuilder attr_accessor :server - def initialize(server) + def initialize(server:) @server = server end def generate_config - file.each_line do |line| + sample_config.each_line do |line| new_line = rewrite_line(line) - config.append_line(new_line) + tempfile.puts new_line end - File.write(tempfile.path, config) + tempfile.close tempfile end - def to_text - config.to_text - end - private - def config - @config ||= ServerConfig.new - end - - def file - File.open(sample_config_path).read - end - def rewrite_line(line) tokens = line.strip.split(' ') - key = tokens[0] + key = tokens.first&.to_sym - if rewrite_mappings.keys.include? key - "#{key} #{rewrite_mappings[key]}" - else - line - end + return line unless rewrite_mappings.key? key + + "#{key} #{rewrite_mappings[key]}" end def sample_config_path @@ -45,8 +33,8 @@ def sample_config_path def rewrite_mappings { - 'proto' => protocol, - 'remote' => "#{host} #{port}" + proto: protocol, + remote: "#{host} #{port}" } end @@ -65,4 +53,8 @@ def port def tempfile @tempfile ||= Tempfile.new(%w[server-config- .ovpn]) end + + def sample_config + @sample_config ||= File.open(sample_config_path).read + end end diff --git a/config/environments/production.rb b/config/environments/production.rb index 6856da64..5b083239 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -81,11 +81,12 @@ config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { - address: '', + address: 'smtp.gmail.com', port: 587, - domain: '', - user_name: '', - password: '', + domain: 'example.com', + user_name: ENV['EMAIL_USER'], + password: ENV['EMAIL_PASS'], authentication: 'plain', - enable_starttls_auto: true } + enable_starttls_auto: true + } end From 69c1015889d15a09ef86ca1b776c7c63b360424e Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Sun, 13 Jan 2019 23:17:42 +0300 Subject: [PATCH 04/16] refactoring styles rubocop --- app/controllers/admin/servers_controller.rb | 20 +++++++++---------- config/application.rb | 4 +++- config/environments/production.rb | 22 +++++++++++---------- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/app/controllers/admin/servers_controller.rb b/app/controllers/admin/servers_controller.rb index 3e2949b9..4fb77442 100644 --- a/app/controllers/admin/servers_controller.rb +++ b/app/controllers/admin/servers_controller.rb @@ -1,12 +1,13 @@ +# frozen_string_literal: true + class Admin::ServersController < Admin::BaseController - before_action :load_resource, only: [:show, :edit, :update, :destroy, :generate_config] + before_action :load_resource, only: %i[show edit update destroy generate_config] def index @servers = Server.all end - def show - end + def show; end def new @server = Server.new @@ -15,18 +16,17 @@ def new def create @server = Server.new(resource_params) if @server.save - redirect_to admin_servers_path, notice: "Сервер успешно добавлен" + redirect_to admin_servers_path, notice: 'Сервер успешно добавлен' else render :new end end - def edit - end + def edit; end def update if @server.update(resource_params) - redirect_to admin_servers_path, notice: "Сервер успешно обновлен" + redirect_to admin_servers_path, notice: 'Сервер успешно обновлен' else render :edit end @@ -34,7 +34,7 @@ def update def destroy @server.delete - redirect_to admin_servers_path, notice: "Сервер удален" + redirect_to admin_servers_path, notice: 'Сервер удален' end def generate_config @@ -52,8 +52,6 @@ def load_resource def resource_params params.require(:server).permit(:hostname, :ip_address, :state, :config, :protocol, :port, :country_code, - plan_ids: [] - ) + plan_ids: []) end end - diff --git a/config/application.rb b/config/application.rb index 07a11c74..3b37867b 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,4 +1,6 @@ -require File.expand_path('../boot', __FILE__) +# frozen_string_literal: true + +require File.expand_path('boot', __dir__) require 'rails/all' diff --git a/config/environments/production.rb b/config/environments/production.rb index 5b083239..fae23e18 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Smartvpn::Application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -23,7 +25,7 @@ config.serve_static_files = true # Compress JavaScripts and CSS. - config.assets.js_compressor = :uglifier + config.assets.js_compressor = :uglifier # config.assets.css_compressor = :sass # Whether to fallback to assets pipeline if a precompiled asset is missed. @@ -40,7 +42,7 @@ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - #config.force_ssl = true + # config.force_ssl = true # Set to :debug to see everything in the log. config.log_level = :debug @@ -77,16 +79,16 @@ # Use default logging formatter so that PID and timestamp are not suppressed. config.log_formatter = ::Logger::Formatter.new - config.action_mailer.default_url_options = { :host => "smartvpn.biz" } + config.action_mailer.default_url_options = { host: 'smartvpn.biz' } config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { - address: 'smtp.gmail.com', - port: 587, - domain: 'example.com', - user_name: ENV['EMAIL_USER'], - password: ENV['EMAIL_PASS'], - authentication: 'plain', + address: 'smtp.gmail.com', + port: 587, + domain: 'example.com', + user_name: ENV['EMAIL_USER'], + password: ENV['EMAIL_PASS'], + authentication: 'plain', enable_starttls_auto: true } - end +end From 6e894016ad4870a3b8ce8dc9c640113346a55303 Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Sun, 13 Jan 2019 23:36:20 +0300 Subject: [PATCH 05/16] Modify gems --- Gemfile | 4 ---- Gemfile.lock | 12 ------------ app/models/server_config.rb | 3 +++ 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/Gemfile b/Gemfile index d2af2f86..5241c970 100644 --- a/Gemfile +++ b/Gemfile @@ -69,22 +69,18 @@ gem 'jbuilder', '~> 1.0.1' gem 'puma' group :development do - gem 'awesome_print' gem 'better_errors' gem 'foreman' gem 'letter_opener' gem 'migration_opener' gem 'rubocop', require: false - gem 'sandi_meter', require: false gem 'web-console', '~> 2.0' end group :test, :development do gem 'capybara' gem 'database_cleaner', '1.0.0.RC1' - gem 'hirb' gem 'mocha', require: false - gem 'rb-fchange', require: false gem 'vcr' # TODO: switch to stable version gem 'pry-rails' diff --git a/Gemfile.lock b/Gemfile.lock index 3d132ccc..1099eb45 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -83,7 +83,6 @@ GEM ast (2.4.0) autoprefixer-rails (9.4.4) execjs - awesome_print (1.6.1) bcrypt (3.1.12) better_errors (0.8.0) coderay (>= 1.0.0) @@ -170,7 +169,6 @@ GEM activesupport (>= 4.2.0) gyoku (1.1.1) builder (>= 2.1.2) - hirb (0.7.1) http-cookie (1.0.2) domain_name (~> 0.5) httparty (0.13.3) @@ -228,7 +226,6 @@ GEM mini_mime (1.0.1) mini_portile2 (2.4.0) minitest (5.11.3) - mixlib-cli (1.4.0) mocha (0.13.3) metaclass (~> 0.0.1) money (6.5.0) @@ -301,8 +298,6 @@ GEM activesupport (>= 3.0) i18n polyamorous (~> 1.1) - rb-fchange (0.0.6) - ffi rb-fsevent (0.10.3) rb-inotify (0.10.0) ffi (~> 1.0) @@ -345,9 +340,6 @@ GEM russian_central_bank (0.2.1) money (>= 5.0) savon (~> 2.0) - sandi_meter (1.1.6) - json - mixlib-cli sass (3.7.3) sass-listen (~> 4.0.0) sass-listen (4.0.0) @@ -448,7 +440,6 @@ PLATFORMS DEPENDENCIES active_model_serializers activemerchant - awesome_print better_errors bootstrap (~> 4.2.1) cancan @@ -469,7 +460,6 @@ DEPENDENCIES font-awesome-sass (~> 5.6.1) foreman gibbon - hirb jbuilder (~> 1.0.1) jquery-rails jquery-ui-rails @@ -488,12 +478,10 @@ DEPENDENCIES rails-i18n rails_config ransack (= 1.5.1) - rb-fchange rollbar rspec-rails rubocop russian_central_bank - sandi_meter sass-rails selenium-webdriver shoulda-matchers! diff --git a/app/models/server_config.rb b/app/models/server_config.rb index 07470a6a..b215e5c8 100644 --- a/app/models/server_config.rb +++ b/app/models/server_config.rb @@ -1,3 +1,6 @@ +# frozen_string_literal: true + +# TODO: delete class ServerConfig attr_accessor :config_lines From 5b1a0e6dfff494a923556b48ea38f3569c890d8a Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Mon, 14 Jan 2019 01:13:11 +0300 Subject: [PATCH 06/16] Fix fallen tests --- app/controllers/admin/servers_controller.rb | 82 ++++++++++--------- app/controllers/billing/servers_controller.rb | 30 ++++--- app/mailers/invite_user_mailer.rb | 11 ++- app/services/server_config_builder.rb | 6 +- config/initializers/devise.rb | 12 +-- .../admin/servers_controller_spec.rb | 79 +++++++++--------- .../billing/servers_controller_spec.rb | 14 ++-- spec/services/server_config_builder_spec.rb | 10 +-- 8 files changed, 131 insertions(+), 113 deletions(-) diff --git a/app/controllers/admin/servers_controller.rb b/app/controllers/admin/servers_controller.rb index 4fb77442..e1649be6 100644 --- a/app/controllers/admin/servers_controller.rb +++ b/app/controllers/admin/servers_controller.rb @@ -1,57 +1,59 @@ # frozen_string_literal: true -class Admin::ServersController < Admin::BaseController - before_action :load_resource, only: %i[show edit update destroy generate_config] +class Admin + class ServersController < Admin::BaseController + before_action :load_resource, only: %i[show edit update destroy generate_config] - def index - @servers = Server.all - end + def index + @servers = Server.all + end - def show; end + def show; end - def new - @server = Server.new - end + def new + @server = Server.new + end - def create - @server = Server.new(resource_params) - if @server.save - redirect_to admin_servers_path, notice: 'Сервер успешно добавлен' - else - render :new + def create + @server = Server.new(resource_params) + if @server.save + redirect_to admin_servers_path, notice: 'Сервер успешно добавлен' + else + render :new + end end - end - def edit; end + def edit; end - def update - if @server.update(resource_params) - redirect_to admin_servers_path, notice: 'Сервер успешно обновлен' - else - render :edit + def update + if @server.update(resource_params) + redirect_to admin_servers_path, notice: 'Сервер успешно обновлен' + else + render :edit + end end - end - def destroy - @server.delete - redirect_to admin_servers_path, notice: 'Сервер удален' - end + def destroy + @server.delete + redirect_to admin_servers_path, notice: 'Сервер удален' + end - def generate_config - builder = ServerConfigBuilder.new(server: @server) - config_file = builder.generate_config - send_data File.read(config_file.path), filename: "#{@server.hostname}.ovpn" - end + def generate_config + builder = ServerConfigBuilder.new(server: @server) + config_file = builder.to_text + send_data config_file, filename: "#{@server.hostname}.ovpn" + end - private + private - def load_resource - @server = Server.find(params[:id]) - end + def load_resource + @server = Server.find(params[:id]) + end - def resource_params - params.require(:server).permit(:hostname, :ip_address, :state, - :config, :protocol, :port, :country_code, - plan_ids: []) + def resource_params + params.require(:server).permit(:hostname, :ip_address, :state, + :config, :protocol, :port, :country_code, + plan_ids: []) + end end end diff --git a/app/controllers/billing/servers_controller.rb b/app/controllers/billing/servers_controller.rb index ce8136f1..122fa534 100644 --- a/app/controllers/billing/servers_controller.rb +++ b/app/controllers/billing/servers_controller.rb @@ -1,18 +1,22 @@ -class Billing::ServersController < Billing::BaseController - def index - @servers = servers - end +# frozen_string_literal: true - def download_config - @server = servers.find(params[:id]) - builder = ServerConfigBuilder.new(@server) - config_file = builder.generate_config - send_data config_file.to_text, filename: "#{@server.hostname}.ovpn" - end +module Billing + class ServersController < Billing::BaseController + def index + @servers = servers + end + + def download_config + @server = servers.find(params[:id]) + builder = ServerConfigBuilder.new(server: @server) + config_file = builder.to_text + send_data config_file, filename: "#{@server.hostname}.ovpn" + end - private + private - def servers - current_user.plan.servers.active + def servers + current_user.plan.servers.active + end end end diff --git a/app/mailers/invite_user_mailer.rb b/app/mailers/invite_user_mailer.rb index 8db3ae51..db6aa1d3 100644 --- a/app/mailers/invite_user_mailer.rb +++ b/app/mailers/invite_user_mailer.rb @@ -5,14 +5,17 @@ class InviteUserMailer < ActionMailer::Base def notify(user) @user = user - server = user.plan.servers.last - attachments["#{server.hostname}.ovpn"] = File.read(generate_config(server).path) + attachments["#{server.hostname}.ovpn"] = server_config mail(to: @user.email, subject: t('mailers.invite_user_mailer.subject')) end private - def generate_config(server) - ServerConfigBuilder.new(server: server).generate_config + def server_config + @server_config ||= ServerConfigBuilder.new(server: server).to_text + end + + def server + @server ||= @user.plan.servers.last end end diff --git a/app/services/server_config_builder.rb b/app/services/server_config_builder.rb index c6ba2965..e440bd6d 100644 --- a/app/services/server_config_builder.rb +++ b/app/services/server_config_builder.rb @@ -12,10 +12,14 @@ def generate_config new_line = rewrite_line(line) tempfile.puts new_line end - tempfile.close + tempfile.rewind tempfile end + def to_text + File.read(generate_config.path) + end + private def rewrite_line(line) diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 1c374f14..21fd924f 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + # Use this hook to configure devise mailer, warden hooks and so forth. # Many of these configuration options can be set straight in your model. Devise.setup do |config| # ==> Mailer Configuration # Configure the e-mail address which will be shown in Devise::Mailer, # note that it will be overwritten if you use your own mailer class with default "from" parameter. - config.mailer_sender = "admin@smartvpn.biz" + config.mailer_sender = 'admin@smartvpn.biz' config.secret_key = ENV['SECRET_TOKEN'] # Configure the class responsible to send e-mails. @@ -36,12 +38,12 @@ # Configure which authentication keys should be case-insensitive. # These keys will be downcased upon creating or modifying a user and when used # to authenticate or find a user. Default is :email. - config.case_insensitive_keys = [ :email ] + config.case_insensitive_keys = [:email] # Configure which authentication keys should have whitespace stripped. # These keys will have whitespace before and after removed upon creating or # modifying a user and when used to authenticate or find a user. Default is :email. - config.strip_whitespace_keys = [ :email ] + config.strip_whitespace_keys = [:email] # Tell if authentication through request.params is enabled. True by default. # config.params_authenticatable = true @@ -85,7 +87,7 @@ # ==> Configuration for :rememberable # The time the user will be remembered without asking for credentials again. - config.remember_for = 2.weeks + config.remember_for = 2.weeks # If true, a valid remember token can be re-used between multiple browsers. # config.remember_across_browsers = true @@ -164,7 +166,7 @@ # Turn scoped views on. Before rendering "sessions/new", it will first check for # "users/sessions/new". It's turned off by default because it's slower if you # are using only default views. - config.scoped_views = true + config.scoped_views = true # Configure the default scope given to Warden. By default it's the first # devise role declared in your routes (usually :user). diff --git a/spec/controllers/admin/servers_controller_spec.rb b/spec/controllers/admin/servers_controller_spec.rb index 168ea395..f2da2a4c 100644 --- a/spec/controllers/admin/servers_controller_spec.rb +++ b/spec/controllers/admin/servers_controller_spec.rb @@ -1,141 +1,143 @@ +# frozen_string_literal: true + require 'spec_helper' describe Admin::ServersController do - context "logged in as user" do + context 'logged in as user' do login_user - it "does not allow to be accessed by user" do + it 'does not allow to be accessed by user' do get :index expect(response).to redirect_to new_admin_session_path end end - context "not logged in" do - it "does not allow to be accessed by guest" do + context 'not logged in' do + it 'does not allow to be accessed by guest' do get :index expect(response).to redirect_to new_admin_session_path end end - context "logged in as admin" do + context 'logged in as admin' do login_admin - describe "GET #index" do + describe 'GET #index' do before { get :index } - it "renders server list" do + it 'renders server list' do expect(response).to render_template :index end - it "returns success status" do + it 'returns success status' do expect(response.status).to eq 200 end end - describe "GET #show" do + describe 'GET #show' do let!(:server) { create :server } before { get :show, id: server.id } - it "renders template" do + it 'renders template' do expect(response).to render_template :show end - it "returns success status" do + it 'returns success status' do expect(response.status).to eq 200 end end - describe "GET #new" do + describe 'GET #new' do before { get :new } - it "renders form" do + it 'renders form' do expect(response).to render_template :new end - it "returns success status" do + it 'returns success status' do expect(response.status).to eq 200 end end - describe "POST #create" do - context "valid attributes" do + describe 'POST #create' do + context 'valid attributes' do let(:attrs) { attributes_for(:server) } - it "creates new server" do - expect { + it 'creates new server' do + expect do post :create, server: attrs - }.to change(Server, :count).by(1) + end.to change(Server, :count).by(1) end - it "redirects to servers list" do + it 'redirects to servers list' do post :create, server: attrs expect(response).to redirect_to admin_servers_path end end - context "invalid attributes" do + context 'invalid attributes' do let(:attrs) { Hash[hostname: nil, ip_address: nil] } - it "renders server form" do + it 'renders server form' do post :create, server: attrs expect(response).to render_template :new end end end - describe "GET #edit" do + describe 'GET #edit' do let!(:server) { create(:server) } - it "renders edit server page" do + it 'renders edit server page' do get :edit, id: server.id expect(response).to render_template :edit end end - describe "PUT #update" do + describe 'PUT #update' do let!(:server) { create(:server) } - context "valid attrs" do - let(:attrs) { Hash[ hostname: "new_hostname.smartvpn.biz" ] } + context 'valid attrs' do + let(:attrs) { Hash[hostname: 'new_hostname.smartvpn.biz'] } - it "updates server" do + it 'updates server' do new_server = create(:server) put :update, id: new_server.id, server: attrs expect(new_server.reload.hostname).to eq attrs[:hostname] end - it "redirects to servers list" do + it 'redirects to servers list' do put :update, id: server.id, server: attrs expect(response).to redirect_to admin_servers_path end end - context "invalid attrs" do - let(:attrs) { Hash[ hostname: nil ] } + context 'invalid attrs' do + let(:attrs) { Hash[hostname: nil] } - it "renders edit form" do + it 'renders edit form' do put :update, id: server.id, server: attrs expect(response).to render_template :edit end end end - describe "DELETE #destroy" do + describe 'DELETE #destroy' do let!(:server) { create(:server) } - it "removes server" do - expect { + it 'removes server' do + expect do delete :destroy, id: server.id - }.to change(Server, :count).by(-1) + end.to change(Server, :count).by(-1) end end describe 'GET #generate_config' do let!(:server) { create(:server) } + let!(:config) { ServerConfigBuilder.new(server: server).to_text } it 'calls config builder' do - config = ServerConfigBuilder.new(server).generate_config - ServerConfigBuilder.any_instance.expects(:generate_config).returns(config) + ServerConfigBuilder.any_instance.expects(:to_text).returns(config) get :generate_config, id: server.id end @@ -146,4 +148,3 @@ end end end - diff --git a/spec/controllers/billing/servers_controller_spec.rb b/spec/controllers/billing/servers_controller_spec.rb index c2e1ca70..42de1242 100644 --- a/spec/controllers/billing/servers_controller_spec.rb +++ b/spec/controllers/billing/servers_controller_spec.rb @@ -1,4 +1,6 @@ -require 'spec_helper' +# frozen_string_literal: true + +require 'rails_helper' describe Billing::ServersController do subject { response } @@ -8,18 +10,18 @@ describe 'GET #index' do before { get :index } - it { should be_success } - it { should render_template :index } + it { is_expected.to be_success } + it { is_expected.to render_template :index } end describe 'GET #download_config' do - let!(:server) { create(:active_server) } + let!(:server) { create(:active_server, plans: [@user.plan]) } + let!(:config) { ServerConfigBuilder.new(server: server).to_text } before { server.plans << @user.plan } it 'calls config builder' do - config = ServerConfigBuilder.new(server).generate_config - ServerConfigBuilder.any_instance.expects(:generate_config).returns(config) + ServerConfigBuilder.any_instance.expects(:to_text).returns(config) get :download_config, id: server.id end diff --git a/spec/services/server_config_builder_spec.rb b/spec/services/server_config_builder_spec.rb index 8e266ef0..67ff97bb 100644 --- a/spec/services/server_config_builder_spec.rb +++ b/spec/services/server_config_builder_spec.rb @@ -1,14 +1,14 @@ -require 'spec_helper' +# frozen_string_literal: true + +require 'rails_helper' describe ServerConfigBuilder do let(:server) { create(:server) } - subject { described_class.new(server) } - - before { subject.generate_config } + subject { described_class.new(server: server) } describe '#generate_config' do it 'returns ServerConfig instance' do - expect(subject.generate_config.class).to eq ServerConfig + expect(subject.generate_config.class).to eq Tempfile end describe 'protocol' do From 26fd0198df757edb3117ee4fb2c1d4dc1813fde3 Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Mon, 14 Jan 2019 01:43:45 +0300 Subject: [PATCH 07/16] Add cache bundler to Travice CI config --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 17cee22b..97f19dc6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ dist: xenial language: ruby sudo: true +cache: bundler rvm: - 2.1.1 From ef2e0b99f45a40f524473d04a3cda844d653129f Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Tue, 15 Jan 2019 18:11:07 +0300 Subject: [PATCH 08/16] Change create user in admin panel --- app/controllers/admin/users_controller.rb | 6 ++++-- ...nvite_user_mailer.rb => create_user_mailer.rb} | 5 +++-- .../ops/admin/user/{invite.rb => create.rb} | 15 +++++---------- app/views/admin/users/new.html.slim | 2 ++ .../mailers/create_user_mailer/notify.html.slim | 4 ++++ .../mailers/invite_user_mailer/notify.html.slim | 3 --- app/workers/create_user_mail_worker.rb | 11 +++++++++++ app/workers/invite_user_mail_worker.rb | 11 ----------- 8 files changed, 29 insertions(+), 28 deletions(-) rename app/mailers/{invite_user_mailer.rb => create_user_mailer.rb} (75%) rename app/operations/ops/admin/user/{invite.rb => create.rb} (64%) create mode 100644 app/views/mailers/create_user_mailer/notify.html.slim delete mode 100644 app/views/mailers/invite_user_mailer/notify.html.slim create mode 100644 app/workers/create_user_mail_worker.rb delete mode 100644 app/workers/invite_user_mail_worker.rb diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 37dbd5ae..da392bde 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -26,7 +26,7 @@ def new end def create - result = ::Ops::Admin::User::Invite.new(params: resource_params).call + result = ::Ops::Admin::User::Create.new(params: resource_params).call if result[:success] redirect_to admin_users_path, notice: t('admin.users.notices.created') else @@ -111,7 +111,9 @@ def payment_params end def resource_params - params.require(:user).permit(:email, :plan_id, :state, :balance, :period_length) + params + .require(:user) + .permit(:email, :plan_id, :state, :balance, :period_length, :password, :password_confirmation) end def days_number_prolongate diff --git a/app/mailers/invite_user_mailer.rb b/app/mailers/create_user_mailer.rb similarity index 75% rename from app/mailers/invite_user_mailer.rb rename to app/mailers/create_user_mailer.rb index db6aa1d3..1ed7f0bc 100644 --- a/app/mailers/invite_user_mailer.rb +++ b/app/mailers/create_user_mailer.rb @@ -1,10 +1,11 @@ # frozen_string_literal: true -class InviteUserMailer < ActionMailer::Base +class CreateUserMailer < ActionMailer::Base default from: 'admin@smartvpn.biz' - def notify(user) + def notify(user:, crypted_password:) @user = user + @password = Base64.decode64(crypted_password) attachments["#{server.hostname}.ovpn"] = server_config mail(to: @user.email, subject: t('mailers.invite_user_mailer.subject')) end diff --git a/app/operations/ops/admin/user/invite.rb b/app/operations/ops/admin/user/create.rb similarity index 64% rename from app/operations/ops/admin/user/invite.rb rename to app/operations/ops/admin/user/create.rb index 0654e8ed..ff0674d2 100644 --- a/app/operations/ops/admin/user/invite.rb +++ b/app/operations/ops/admin/user/create.rb @@ -3,7 +3,7 @@ module Ops module Admin module User - class Invite + class Create attr_reader :params def initialize(params:) @@ -14,24 +14,19 @@ def call user.skip_confirmation_notification! return error_create_user unless user.save - build_invited_user! + build_created_user! success_result end private - def build_invited_user! + def build_created_user! user.confirm - user.send_reset_password_instructions - InviteUserMailWorker.perform_async(user.id) + CreateUserMailWorker.perform_async(user_id: user.id, crypted_password: Base64.encode64(params[:password])) end def user - @user ||= ::User.new(params.merge(password: generate_password)) - end - - def generate_password - SecureRandom.alphanumeric + @user ||= ::User.new(params) end def error_create_user diff --git a/app/views/admin/users/new.html.slim b/app/views/admin/users/new.html.slim index 9bb2d122..c720534d 100644 --- a/app/views/admin/users/new.html.slim +++ b/app/views/admin/users/new.html.slim @@ -4,6 +4,8 @@ .col = simple_form_for [:admin, @user], html: { class: 'form-horizontal' },wrapper: :horizontal_form do |f| = f.input :email + = f.input :password + = f.input :password_confirmation = f.input :balance = f.input :plan_id, as: :select, collection: Plan.all.map { |p| [p.name, p.id] }, include_blank: false = f.input :period_length, input_html: { value: f.object.period_length || User::DEFAULT_TEST_PERIOD } diff --git a/app/views/mailers/create_user_mailer/notify.html.slim b/app/views/mailers/create_user_mailer/notify.html.slim new file mode 100644 index 00000000..bb5320b7 --- /dev/null +++ b/app/views/mailers/create_user_mailer/notify.html.slim @@ -0,0 +1,4 @@ +p= "Hello #{@user.email}!" +p= 'An account has been created for you' +p= "Login: #{@user.email}, password: #{@password}" + diff --git a/app/views/mailers/invite_user_mailer/notify.html.slim b/app/views/mailers/invite_user_mailer/notify.html.slim deleted file mode 100644 index adf6d2d9..00000000 --- a/app/views/mailers/invite_user_mailer/notify.html.slim +++ /dev/null @@ -1,3 +0,0 @@ -p= "Hello #{@user.email}!" -p= 'Attached is a configuration file' - diff --git a/app/workers/create_user_mail_worker.rb b/app/workers/create_user_mail_worker.rb new file mode 100644 index 00000000..ba2ad2a4 --- /dev/null +++ b/app/workers/create_user_mail_worker.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class CreateUserMailWorker + include Sidekiq::Worker + sidekiq_options queue: :mailers + + def perform(user_params) + user = User.find(user_params['user_id']) + CreateUserMailer.notify(user: user, crypted_password: user_params['crypted_password']).deliver_now + end +end diff --git a/app/workers/invite_user_mail_worker.rb b/app/workers/invite_user_mail_worker.rb deleted file mode 100644 index 8ce1211e..00000000 --- a/app/workers/invite_user_mail_worker.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -class InviteUserMailWorker - include Sidekiq::Worker - sidekiq_options queue: :mailers - - def perform(user_id) - user = User.find(user_id) - InviteUserMailer.notify(user).deliver_now - end -end From cb6d0903645093274ea4d577afeaacf84602fcc2 Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Wed, 16 Jan 2019 04:40:25 +0300 Subject: [PATCH 09/16] Refactoring after review --- .env.sample | 1 + .env.test | 4 +- .travis.yml | 8 ++-- Gemfile | 5 ++- Gemfile.lock | 14 +++---- ...er.rb => user_connection_config_mailer.rb} | 4 +- app/mailers/user_mailer.rb | 4 +- app/operations/ops/admin/user/base.rb | 16 ++++++++ app/operations/ops/admin/user/create.rb | 9 +---- app/services/server_config_builder.rb | 38 +++---------------- app/views/admin/users/_table.html.slim | 2 +- .../notify.html.slim | 0 app/workers/create_user_mail_worker.rb | 2 +- config/environments/development.rb | 2 +- config/environments/production.rb | 2 +- config/environments/test.rb | 6 ++- config/initializers/devise.rb | 2 +- config/locales/admin/en.yml | 2 +- config/locales/admin/ru.yml | 2 +- ...artvpn.biz.ovpn => sample.server.ovpn.erb} | 4 +- config/settings.yml | 2 +- 21 files changed, 62 insertions(+), 67 deletions(-) rename app/mailers/{create_user_mailer.rb => user_connection_config_mailer.rb} (83%) create mode 100644 app/operations/ops/admin/user/base.rb rename app/views/mailers/{create_user_mailer => user_connection_config_mailer}/notify.html.slim (100%) rename config/{sample.smartvpn.biz.ovpn => sample.server.ovpn.erb} (97%) diff --git a/.env.sample b/.env.sample index bbec1e0e..13c39b24 100644 --- a/.env.sample +++ b/.env.sample @@ -1,3 +1,4 @@ SECRET_TOKEN= EMAIL_USER= EMAIL_PASS= +EMAIL_FROM= diff --git a/.env.test b/.env.test index d92e25ca..46cbda74 100644 --- a/.env.test +++ b/.env.test @@ -1 +1,3 @@ -SECRET_TOKEN=0e89a81d2e7be3cce9c45d154df16269b5878061c9967c15329adf1490941e613f0b24dd4955b9e0b0e1356180ae8314b879f20150abad78e1ff4bc039a06d75 +SECRET_TOKEN='0e89a81d2e7be3cce9c45d154df16269b5878061c9967c15329adf1490941e613f0b24dd4955b9e0b0e1356180ae8314b879f20150abad78e1ff4bc039a06d75' +DEFAULT_HOST='smartvpn.dev' +EMAIL_FROM='admin@smartvpn.biz' diff --git a/.travis.yml b/.travis.yml index 97f19dc6..c64740e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,15 +12,19 @@ matrix: allow_failures: - rvm: 2.1.1 - rvm: 2.6.0 + addons: chrome: stable + services: - postgresql - redis-server + before_install: - gem install bundler -v '1.17.3' - cp config/database.yml.sample config/database.yml - cp .env.test .env + before_script: - bundle exec rake db:create - bundle exec rake db:schema:load @@ -30,7 +34,5 @@ before_script: - sudo apt-get --only-upgrade install google-chrome-stable - sudo cp chromedriver /usr/local/bin/. - sudo chmod +x /usr/local/bin/chromedriver - - export DISPLAY=:99.0 - - sh -e /etc/init.d/xvfb start - - sleep 3 + script: bundle exec rspec diff --git a/Gemfile b/Gemfile index 5241c970..d06a1150 100644 --- a/Gemfile +++ b/Gemfile @@ -40,7 +40,6 @@ gem 'russian_central_bank' gem 'show_for', github: 'plataformatec/show_for' gem 'whenever', '0.9.0', require: false -gem 'dotenv-rails' gem 'factory_girl_rails', '~> 4.0' gem 'faker' @@ -74,16 +73,18 @@ group :development do gem 'letter_opener' gem 'migration_opener' gem 'rubocop', require: false + gem 'sandi_meter', require: false gem 'web-console', '~> 2.0' end group :test, :development do + gem 'awesome_print' gem 'capybara' gem 'database_cleaner', '1.0.0.RC1' + gem 'dotenv-rails' gem 'mocha', require: false gem 'vcr' # TODO: switch to stable version - gem 'pry-rails' gem 'rspec-rails' gem 'selenium-webdriver' gem 'shoulda-matchers', github: 'thoughtbot/shoulda-matchers' diff --git a/Gemfile.lock b/Gemfile.lock index 1099eb45..1aa8461b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -83,6 +83,7 @@ GEM ast (2.4.0) autoprefixer-rails (9.4.4) execjs + awesome_print (1.8.0) bcrypt (3.1.12) better_errors (0.8.0) coderay (>= 1.0.0) @@ -219,13 +220,13 @@ GEM ntlm-http (~> 0.1, >= 0.1.1) webrobots (>= 0.0.9, < 0.2) metaclass (0.0.1) - method_source (0.9.2) migration_opener (0.0.2) rails mime-types (1.25.1) mini_mime (1.0.1) mini_portile2 (2.4.0) minitest (5.11.3) + mixlib-cli (1.4.0) mocha (0.13.3) metaclass (~> 0.0.1) money (6.5.0) @@ -251,11 +252,6 @@ GEM activerecord (>= 3.0) popper_js (1.14.5) powerpack (0.1.2) - pry (0.12.2) - coderay (~> 1.1.0) - method_source (~> 0.9.0) - pry-rails (0.3.9) - pry (>= 0.10.4) puma (3.12.0) rack (1.6.11) rack-protection (1.5.5) @@ -340,6 +336,9 @@ GEM russian_central_bank (0.2.1) money (>= 5.0) savon (~> 2.0) + sandi_meter (1.1.6) + json + mixlib-cli sass (3.7.3) sass-listen (~> 4.0.0) sass-listen (4.0.0) @@ -440,6 +439,7 @@ PLATFORMS DEPENDENCIES active_model_serializers activemerchant + awesome_print better_errors bootstrap (~> 4.2.1) cancan @@ -472,7 +472,6 @@ DEPENDENCIES newrelic_rpm pg pghero - pry-rails puma rails (= 4.2.11) rails-i18n @@ -482,6 +481,7 @@ DEPENDENCIES rspec-rails rubocop russian_central_bank + sandi_meter sass-rails selenium-webdriver shoulda-matchers! diff --git a/app/mailers/create_user_mailer.rb b/app/mailers/user_connection_config_mailer.rb similarity index 83% rename from app/mailers/create_user_mailer.rb rename to app/mailers/user_connection_config_mailer.rb index 1ed7f0bc..f8063421 100644 --- a/app/mailers/create_user_mailer.rb +++ b/app/mailers/user_connection_config_mailer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -class CreateUserMailer < ActionMailer::Base - default from: 'admin@smartvpn.biz' +class UserConnectionConfigMailer < ActionMailer::Base + default from: ENV['EMAIL_FROM'] def notify(user:, crypted_password:) @user = user diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 7a80a04a..c7ee9ba7 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + class UserMailer < ActionMailer::Base add_template_helper(ApplicationHelper) - default from: "admin@smartvpn.biz" + default from: ENV['EMAIL_FROM'] def funds_recieved(user, amount) @user = user diff --git a/app/operations/ops/admin/user/base.rb b/app/operations/ops/admin/user/base.rb new file mode 100644 index 00000000..66ff7a4a --- /dev/null +++ b/app/operations/ops/admin/user/base.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Ops + module Admin + module User + # This base class for user operations + class Base + attr_reader :params + + def initialize(params:) + @params = params + end + end + end + end +end diff --git a/app/operations/ops/admin/user/create.rb b/app/operations/ops/admin/user/create.rb index ff0674d2..23785d1e 100644 --- a/app/operations/ops/admin/user/create.rb +++ b/app/operations/ops/admin/user/create.rb @@ -3,13 +3,8 @@ module Ops module Admin module User - class Create - attr_reader :params - - def initialize(params:) - @params = params - end - + # This class create new user and send email with connection config, user password + class Create < Base def call user.skip_confirmation_notification! return error_create_user unless user.save diff --git a/app/services/server_config_builder.rb b/app/services/server_config_builder.rb index e440bd6d..366778a3 100644 --- a/app/services/server_config_builder.rb +++ b/app/services/server_config_builder.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# This class created connection vpn config file by server from template class ServerConfigBuilder attr_accessor :server @@ -8,57 +9,30 @@ def initialize(server:) end def generate_config - sample_config.each_line do |line| - new_line = rewrite_line(line) - tempfile.puts new_line - end + tempfile.puts erb_render_sample_config tempfile.rewind tempfile end def to_text - File.read(generate_config.path) + erb_render_sample_config end private - def rewrite_line(line) - tokens = line.strip.split(' ') - key = tokens.first&.to_sym - - return line unless rewrite_mappings.key? key - - "#{key} #{rewrite_mappings[key]}" + def erb_render_sample_config + ERB.new(sample_config).result(binding) end def sample_config_path Settings.servers.sample_config_path end - def rewrite_mappings - { - proto: protocol, - remote: "#{host} #{port}" - } - end - - def protocol - @protocol ||= server.protocol - end - - def host - @host ||= server.hostname - end - - def port - @port ||= server.port - end - def tempfile @tempfile ||= Tempfile.new(%w[server-config- .ovpn]) end def sample_config - @sample_config ||= File.open(sample_config_path).read + @sample_config ||= File.read(sample_config_path) end end diff --git a/app/views/admin/users/_table.html.slim b/app/views/admin/users/_table.html.slim index b198f63d..839a4408 100644 --- a/app/views/admin/users/_table.html.slim +++ b/app/views/admin/users/_table.html.slim @@ -30,7 +30,7 @@ table.table li.pb-1 = link_to t('admin.links.edit'), edit_admin_user_path(user), class: 'btn btn-sm btn-info' li - = link_to t('admin.links.write_off'), withdraw_admin_user_path(user), method: :put, class: 'btn btn-sm btn-warning' + = link_to t('admin.links.withdraw'), withdraw_admin_user_path(user), method: :put, class: 'btn btn-sm btn-warning' = render partial: 'admin/shared/paginate', locals: {collection: @users} diff --git a/app/views/mailers/create_user_mailer/notify.html.slim b/app/views/mailers/user_connection_config_mailer/notify.html.slim similarity index 100% rename from app/views/mailers/create_user_mailer/notify.html.slim rename to app/views/mailers/user_connection_config_mailer/notify.html.slim diff --git a/app/workers/create_user_mail_worker.rb b/app/workers/create_user_mail_worker.rb index ba2ad2a4..7d1a965c 100644 --- a/app/workers/create_user_mail_worker.rb +++ b/app/workers/create_user_mail_worker.rb @@ -6,6 +6,6 @@ class CreateUserMailWorker def perform(user_params) user = User.find(user_params['user_id']) - CreateUserMailer.notify(user: user, crypted_password: user_params['crypted_password']).deliver_now + UserConnectionConfigMailer.notify(user: user, crypted_password: user_params['crypted_password']).deliver_now end end diff --git a/config/environments/development.rb b/config/environments/development.rb index 6c535503..5b9f5d3b 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -28,5 +28,5 @@ config.assets.debug = true config.action_mailer.delivery_method = :letter_opener - config.action_mailer.default_url_options = { host: 'localhost:3000' } + config.action_mailer.default_url_options = { host: ENV['DEFAULT_HOST'] } end diff --git a/config/environments/production.rb b/config/environments/production.rb index fae23e18..c53bb178 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -79,7 +79,7 @@ # Use default logging formatter so that PID and timestamp are not suppressed. config.log_formatter = ::Logger::Formatter.new - config.action_mailer.default_url_options = { host: 'smartvpn.biz' } + config.action_mailer.default_url_options = { host: ENV['DEFAULT_HOST'] } config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { diff --git a/config/environments/test.rb b/config/environments/test.rb index 413fa027..71ce0025 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Smartvpn::Application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -14,7 +16,7 @@ # Configure static asset server for tests with Cache-Control for performance. config.serve_static_files = true - config.static_cache_control = "public, max-age=3600" + config.static_cache_control = 'public, max-age=3600' # Show full error reports and disable caching. config.consider_all_requests_local = true @@ -33,5 +35,5 @@ # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr - config.action_mailer.default_url_options = { :host => "smartvpn.dev" } + config.action_mailer.default_url_options = { host: ENV['DEFAULT_HOST'] } end diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 21fd924f..2467028d 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -6,7 +6,7 @@ # ==> Mailer Configuration # Configure the e-mail address which will be shown in Devise::Mailer, # note that it will be overwritten if you use your own mailer class with default "from" parameter. - config.mailer_sender = 'admin@smartvpn.biz' + config.mailer_sender = ENV['EMAIL_FROM'] config.secret_key = ENV['SECRET_TOKEN'] # Configure the class responsible to send e-mails. diff --git a/config/locales/admin/en.yml b/config/locales/admin/en.yml index 6d86a2dc..defbc94c 100644 --- a/config/locales/admin/en.yml +++ b/config/locales/admin/en.yml @@ -21,7 +21,7 @@ en: edit: 'Edit' email_list: 'Email list' create: 'Create' - write_off: 'Write off' + withdraw: 'Withdraw' buttons: filter: 'Filter' apply: 'Apply' diff --git a/config/locales/admin/ru.yml b/config/locales/admin/ru.yml index 2898edf6..d7c196d0 100644 --- a/config/locales/admin/ru.yml +++ b/config/locales/admin/ru.yml @@ -21,7 +21,7 @@ ru: edit: 'Редактировать' email_list: 'Список email' create: 'Создать' - write_off: 'Списать' + withdraw: 'Списать' buttons: filter: 'Фильтер' apply: 'Применить' diff --git a/config/sample.smartvpn.biz.ovpn b/config/sample.server.ovpn.erb similarity index 97% rename from config/sample.smartvpn.biz.ovpn rename to config/sample.server.ovpn.erb index a832adb4..06ccb229 100644 --- a/config/sample.smartvpn.biz.ovpn +++ b/config/sample.server.ovpn.erb @@ -2,9 +2,9 @@ client dev tun -proto unknown_proto +proto <%= server.protocol %> -remote unknown_host unknown_port +remote <%= server.hostname %> <%= server.port %> resolv-retry infinite nobind diff --git a/config/settings.yml b/config/settings.yml index 682fd2ba..e981d099 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -2,7 +2,7 @@ partners: referrer_percent: 20 servers: - sample_config_path: 'config/sample.smartvpn.biz.ovpn' + sample_config_path: 'config/sample.server.ovpn.erb' mailchimp: all_clients_list_id: '' From 7b02935fed64c12ee13b41c37021be5ea1029ed4 Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Wed, 16 Jan 2019 19:53:02 +0300 Subject: [PATCH 10/16] Add tests --- Gemfile | 5 ++-- Gemfile.lock | 17 +++++------ app/mailers/user_connection_config_mailer.rb | 2 +- app/operations/ops/admin/user/base.rb | 4 +++ config/locales/en.yml | 2 +- config/locales/ru.yml | 2 +- .../user_connection_config_mailer_spec.rb | 30 +++++++++++++++++++ spec/operations/ops/admin/user/create_spec.rb | 28 +++++++++++++++++ 8 files changed, 76 insertions(+), 14 deletions(-) create mode 100644 spec/mailers/user_connection_config_mailer_spec.rb create mode 100644 spec/operations/ops/admin/user/create_spec.rb diff --git a/Gemfile b/Gemfile index d06a1150..c2c727ff 100644 --- a/Gemfile +++ b/Gemfile @@ -84,10 +84,11 @@ group :test, :development do gem 'dotenv-rails' gem 'mocha', require: false gem 'vcr' + gem 'shoulda-matchers', '4.0.0.rc1' + gem 'rspec-rails', '~> 3.8' + gem 'rspec-its' # TODO: switch to stable version - gem 'rspec-rails' gem 'selenium-webdriver' - gem 'shoulda-matchers', github: 'thoughtbot/shoulda-matchers' gem 'timecop' end diff --git a/Gemfile.lock b/Gemfile.lock index 1aa8461b..c0ac8912 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -18,13 +18,6 @@ GIT specs: state_machine (1.2.0) -GIT - remote: git://github.com/thoughtbot/shoulda-matchers.git - revision: 380d18f0621c66a79445ebc6dcc0048fcc969911 - specs: - shoulda-matchers (2.6.1) - activesupport (>= 3.0.0) - GEM remote: http://rubygems.org/ specs: @@ -310,6 +303,9 @@ GEM rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) + rspec-its (1.2.0) + rspec-core (>= 3.0.0) + rspec-expectations (>= 3.0.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) @@ -370,6 +366,8 @@ GEM selenium-webdriver (3.141.0) childprocess (~> 0.5) rubyzip (~> 1.2, >= 1.2.2) + shoulda-matchers (4.0.0.rc1) + activesupport (>= 4.2.0) sidekiq (5.2.3) connection_pool (~> 2.2, >= 2.2.2) rack-protection (>= 1.5.0) @@ -478,13 +476,14 @@ DEPENDENCIES rails_config ransack (= 1.5.1) rollbar - rspec-rails + rspec-its + rspec-rails (~> 3.8) rubocop russian_central_bank sandi_meter sass-rails selenium-webdriver - shoulda-matchers! + shoulda-matchers (= 4.0.0.rc1) show_for! sidekiq simple_form diff --git a/app/mailers/user_connection_config_mailer.rb b/app/mailers/user_connection_config_mailer.rb index f8063421..f3d7e048 100644 --- a/app/mailers/user_connection_config_mailer.rb +++ b/app/mailers/user_connection_config_mailer.rb @@ -7,7 +7,7 @@ def notify(user:, crypted_password:) @user = user @password = Base64.decode64(crypted_password) attachments["#{server.hostname}.ovpn"] = server_config - mail(to: @user.email, subject: t('mailers.invite_user_mailer.subject')) + mail(to: @user.email, subject: t('mailers.user_connection_config_mailer.subject')) end private diff --git a/app/operations/ops/admin/user/base.rb b/app/operations/ops/admin/user/base.rb index 66ff7a4a..8ef58b69 100644 --- a/app/operations/ops/admin/user/base.rb +++ b/app/operations/ops/admin/user/base.rb @@ -10,6 +10,10 @@ class Base def initialize(params:) @params = params end + + def call + raise NotImplementedError + end end end end diff --git a/config/locales/en.yml b/config/locales/en.yml index faff92ff..e4d1da8f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,6 +1,6 @@ en: mailers: - invite_user_mailer: + user_connection_config_mailer: subject: 'An account has been created for you' date: formats: diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 39f7b642..c39e6433 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -1,6 +1,6 @@ ru: mailers: - invite_user_mailer: + user_connection_config_mailer: subject: 'Вам был создан аккаунт' date: formats: diff --git a/spec/mailers/user_connection_config_mailer_spec.rb b/spec/mailers/user_connection_config_mailer_spec.rb new file mode 100644 index 00000000..2c058d75 --- /dev/null +++ b/spec/mailers/user_connection_config_mailer_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe UserConnectionConfigMailer do + describe '#notify' do + subject { described_class.notify(user: user, crypted_password: crypted_password) } + let!(:user) { create(:user) } + let!(:server) { create(:server) } + let!(:plan) { create(:plan, users: [user], servers: [server]) } + let(:server_config) { ServerConfigBuilder.new(server: server).to_text } + let(:crypted_password) { Base64.encode64('123456') } + + its(:subject) { is_expected.to eq I18n.t('mailers.user_connection_config_mailer.subject') } + its(:to) { is_expected.to eq [user.email] } + its(:from) { is_expected.to eq [ENV['EMAIL_FROM']] } + + it 'email have 1 attachment' do + expect(subject.attachments.count).to eq 1 + end + + it 'attachment name' do + expect(subject.attachments.first.filename).to eq "#{server.hostname}.ovpn" + end + + it 'renders user password' do + expect(subject.body.encoded).to match('123456') + end + end +end diff --git a/spec/operations/ops/admin/user/create_spec.rb b/spec/operations/ops/admin/user/create_spec.rb new file mode 100644 index 00000000..9e3c01ad --- /dev/null +++ b/spec/operations/ops/admin/user/create_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe Ops::Admin::User::Create do + subject { described_class.new(params: params) } + let!(:plan) { create(:plan) } + + context 'valid params' do + let(:params) do + { + email: 'user@gmail.com', + password: '123456', + password_confirmation: '123456', + plan_id: plan.id + } + end + + it 'returns success result' do + expect(subject.call).to eq(success: true, user: User.last) + end + + it 'returns success result' do + expect(CreateUserMailWorker).to receive(:perform_async).with(any_args) + subject.call + end + end +end From 1cdf2712e0be318380047ecc94dddc0e03591413 Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Thu, 17 Jan 2019 08:26:20 +0300 Subject: [PATCH 11/16] Fix fallen tests, change to new style --- Gemfile | 8 +- Gemfile.lock | 4 - .../admin/connections_controller_spec.rb | 22 ++- .../admin/options_controller_spec.rb | 18 +- .../admin/promos_controller_spec.rb | 64 +++--- .../admin/referrers_controller_spec.rb | 6 +- .../admin/servers_controller_spec.rb | 2 +- .../admin/traffic_reports_controller_spec.rb | 30 +-- .../admin/users_controller_spec.rb | 104 +++++----- .../api/authentication_controller_spec.rb | 20 +- .../api/connection_controller_spec.rb | 38 ++-- .../billing/options_controller_spec.rb | 10 +- .../billing/payments_controller_spec.rb | 28 +-- .../billing/referrers_controller_spec.rb | 6 +- .../billing/robokassa_controller_spec.rb | 32 +-- .../billing/servers_controller_spec.rb | 2 +- .../billing/webmoney_controller_spec.rb | 74 ++++--- spec/features/billing/payments_page_spec.rb | 8 +- spec/lib/currencies/course_converter_spec.rb | 12 +- spec/lib/currencies/course_spec.rb | 40 ++-- spec/models/connect_spec.rb | 13 +- spec/models/disconnect_spec.rb | 10 +- spec/models/dto/admin/descrete_base_spec.rb | 4 +- spec/models/option_spec.rb | 20 +- spec/models/options/hooks/proxy_spec.rb | 8 +- spec/models/pay_system_spec.rb | 35 ++-- spec/models/payment_spec.rb | 66 +++---- spec/models/plan_has_server_spec.rb | 7 +- spec/models/plan_spec.rb | 37 ++-- spec/models/promo_spec.rb | 54 ++--- spec/models/promotion_spec.rb | 19 +- spec/models/proxy/connect_spec.rb | 6 +- spec/models/proxy/node_spec.rb | 10 +- spec/models/referrer/reward_spec.rb | 8 +- spec/models/server_spec.rb | 26 +-- spec/models/traffic_report_spec.rb | 39 ++-- spec/models/transaction_spec.rb | 26 ++- spec/models/user_option_spec.rb | 12 +- spec/models/user_spec.rb | 184 +++++++++--------- spec/models/withdrawal_prolongation_spec.rb | 8 +- spec/models/withdrawal_spec.rb | 39 ++-- spec/operations/ops/admin/user/create_spec.rb | 36 ++++ spec/services/option/activator_spec.rb | 16 +- spec/services/proxy/fetchers/base_spec.rb | 8 +- spec/services/proxy/updater_spec.rb | 8 +- .../referrer/reward_calculator_spec.rb | 4 +- spec/services/withdrawer_spec.rb | 59 +++--- spec/spec_helper.rb | 12 +- 48 files changed, 708 insertions(+), 594 deletions(-) diff --git a/Gemfile b/Gemfile index c2c727ff..ad85fd35 100644 --- a/Gemfile +++ b/Gemfile @@ -82,11 +82,11 @@ group :test, :development do gem 'capybara' gem 'database_cleaner', '1.0.0.RC1' gem 'dotenv-rails' - gem 'mocha', require: false - gem 'vcr' - gem 'shoulda-matchers', '4.0.0.rc1' - gem 'rspec-rails', '~> 3.8' + # gem 'mocha', require: false gem 'rspec-its' + gem 'rspec-rails', '~> 3.8' + gem 'shoulda-matchers', '4.0.0.rc1' + gem 'vcr' # TODO: switch to stable version gem 'selenium-webdriver' gem 'timecop' diff --git a/Gemfile.lock b/Gemfile.lock index c0ac8912..35e2d5a8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -212,7 +212,6 @@ GEM nokogiri (~> 1.4) ntlm-http (~> 0.1, >= 0.1.1) webrobots (>= 0.0.9, < 0.2) - metaclass (0.0.1) migration_opener (0.0.2) rails mime-types (1.25.1) @@ -220,8 +219,6 @@ GEM mini_portile2 (2.4.0) minitest (5.11.3) mixlib-cli (1.4.0) - mocha (0.13.3) - metaclass (~> 0.0.1) money (6.5.0) i18n (>= 0.6.4, <= 0.7.0) multi_json (1.13.1) @@ -466,7 +463,6 @@ DEPENDENCIES letter_opener mechanize migration_opener - mocha newrelic_rpm pg pghero diff --git a/spec/controllers/admin/connections_controller_spec.rb b/spec/controllers/admin/connections_controller_spec.rb index ac1fc54c..b757bd61 100644 --- a/spec/controllers/admin/connections_controller_spec.rb +++ b/spec/controllers/admin/connections_controller_spec.rb @@ -1,40 +1,42 @@ +# frozen_string_literal: true + require 'rails_helper' describe Admin::ConnectionsController do subject { response } login_admin - describe "GET #index" do + describe 'GET #index' do before { get :index } - it { should render_template :index } + it { is_expected.to render_template :index } - it "returns success status" do + it 'returns success status' do expect(subject.status).to eq 200 end end - describe "GET #active" do + describe 'GET #active' do before { get :active } - it { should render_template :active } + it { is_expected.to render_template :active } - it "returns success status" do + it 'returns success status' do expect(subject.status).to eq 200 end - it "loads active connections" do + it 'loads active connections' do expect(assigns(:connections)).to eq Connection.active.to_a end end - describe "GET #show" do + describe 'GET #show' do let(:connection) { create(:connect) } before { get :show, id: connection.id } - it { should be_success } - it { should render_template :show } + it { is_expected.to be_success } + it { is_expected.to render_template :show } it { expect(response.status).to eq 200 } end end diff --git a/spec/controllers/admin/options_controller_spec.rb b/spec/controllers/admin/options_controller_spec.rb index 15b3107c..4a3b3bd0 100644 --- a/spec/controllers/admin/options_controller_spec.rb +++ b/spec/controllers/admin/options_controller_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Admin::OptionsController do @@ -7,15 +9,15 @@ describe 'GET #index' do before { get :index } - it { should be_success } - it { should render_template :index } + it { is_expected.to be_success } + it { is_expected.to render_template :index } end describe 'GET #new' do before { get :new } - it { should be_success } - it { should render_template :new } + it { is_expected.to be_success } + it { is_expected.to render_template :new } end describe 'POST #create' do @@ -23,9 +25,9 @@ let(:attrs) { attributes_for(:option) } it 'creates new option' do - expect { + expect do post :create, option: attrs - }.to change(Option.all, :count).by(1) + end.to change(Option.all, :count).by(1) end it 'redirects to options path' do @@ -48,8 +50,8 @@ let(:option) { create(:option) } before { get :edit, id: option.id } - it { should be_success } - it { should render_template :edit } + it { is_expected.to be_success } + it { is_expected.to render_template :edit } end describe 'PUT #update' do diff --git a/spec/controllers/admin/promos_controller_spec.rb b/spec/controllers/admin/promos_controller_spec.rb index e6c0c59c..b6a7a623 100644 --- a/spec/controllers/admin/promos_controller_spec.rb +++ b/spec/controllers/admin/promos_controller_spec.rb @@ -1,100 +1,102 @@ +# frozen_string_literal: true + require 'spec_helper' describe Admin::PromosController do subject { response } - context "logged in as user" do + context 'logged in as user' do login_user - it "does not allow to be accessed by user" do + it 'does not allow to be accessed by user' do get :index expect(response).to redirect_to new_admin_session_path end end - context "logged in as admin" do + context 'logged in as admin' do login_admin - describe "GET #index" do + describe 'GET #index' do before { get :index } - it { should render_template :index } + it { is_expected.to render_template :index } it { expect(subject.status).to eq 200 } end - describe "GET #new" do + describe 'GET #new' do before { get :new } - it { should render_template :new } + it { is_expected.to render_template :new } it { expect(subject.status).to eq 200 } end - describe "POST #create" do - context "valid params" do - let(:attrs) { Hash[name: "new name", type: "withdrawal", promoter_type: "discount"] } + describe 'POST #create' do + context 'valid params' do + let(:attrs) { Hash[name: 'new name', type: 'withdrawal', promoter_type: 'discount'] } - it "redirects to promos path" do + it 'redirects to promos path' do post :create, promo: attrs expect(subject).to redirect_to edit_admin_promo_path(Promo.last) end - it "creates new promo" do - expect { + it 'creates new promo' do + expect do post :create, promo: attrs - }.to change(Promo, :count).by(1) + end.to change(Promo, :count).by(1) end end - context "invalid params" do + context 'invalid params' do let(:attrs) { Hash[name: nil] } - it "renders new template" do + it 'renders new template' do post :create, promo: attrs expect(subject).to render_template :new end - it "does not create promo" do - expect { + it 'does not create promo' do + expect do post :create, promo: attrs - }.not_to change(Promo, :count) + end.not_to change(Promo, :count) end end end - describe "GET #edit" do + describe 'GET #edit' do let(:promo) { create(:promo) } - before { get :edit, id: promo.id} + before { get :edit, id: promo.id } - it { should render_template :edit } + it { is_expected.to render_template :edit } it { expect(subject.status).to eq 200 } end - describe "PUT #update" do + describe 'PUT #update' do let(:promo) { create(:promo) } - context "valid params" do - let(:attrs) { Hash[name: "new name", type: "withdrawal", promoter_type: "discount"] } + context 'valid params' do + let(:attrs) { Hash[name: 'new name', type: 'withdrawal', promoter_type: 'discount'] } - it "redirects to edit page" do + it 'redirects to edit page' do put :update, promo: attrs, id: promo.id expect(subject).to redirect_to edit_admin_promo_path(promo) end - it "updates promo" do + it 'updates promo' do put :update, promo: attrs, id: promo.id expect(promo.reload.name).to eq attrs[:name] end end - context "invalid params" do - let(:attrs) { Hash[name: "new name", type: nil, promoter_type: "discount"] } + context 'invalid params' do + let(:attrs) { Hash[name: 'new name', type: nil, promoter_type: 'discount'] } - it "renders edit form" do + it 'renders edit form' do put :update, promo: attrs, id: promo.id expect(subject).to render_template :edit end - it "does not update promo" do + it 'does not update promo' do put :update, promo: attrs, id: promo.id expect(promo.reload.name).not_to eq attrs[:name] end diff --git a/spec/controllers/admin/referrers_controller_spec.rb b/spec/controllers/admin/referrers_controller_spec.rb index f5511887..d9be2c00 100644 --- a/spec/controllers/admin/referrers_controller_spec.rb +++ b/spec/controllers/admin/referrers_controller_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Admin::ReferrersController do @@ -11,8 +13,8 @@ describe 'GET #index' do before { get :index } - it { should be_success } - it { should render_template :index } + it { is_expected.to be_success } + it { is_expected.to render_template :index } end end end diff --git a/spec/controllers/admin/servers_controller_spec.rb b/spec/controllers/admin/servers_controller_spec.rb index f2da2a4c..d9170ca0 100644 --- a/spec/controllers/admin/servers_controller_spec.rb +++ b/spec/controllers/admin/servers_controller_spec.rb @@ -137,7 +137,7 @@ let!(:config) { ServerConfigBuilder.new(server: server).to_text } it 'calls config builder' do - ServerConfigBuilder.any_instance.expects(:to_text).returns(config) + allow_any_instance_of(ServerConfigBuilder).to receive(:to_text).and_return(config) get :generate_config, id: server.id end diff --git a/spec/controllers/admin/traffic_reports_controller_spec.rb b/spec/controllers/admin/traffic_reports_controller_spec.rb index c4aff823..ccf5b433 100644 --- a/spec/controllers/admin/traffic_reports_controller_spec.rb +++ b/spec/controllers/admin/traffic_reports_controller_spec.rb @@ -1,34 +1,36 @@ +# frozen_string_literal: true + require 'spec_helper' describe Admin::TrafficReportsController do login_admin subject { response } - describe "GET #index" do + describe 'GET #index' do before { get :index } - it { should be_success } - it { should render_template :index } + it { is_expected.to be_success } + it { is_expected.to render_template :index } end - describe "GET #users" do - before { get :users} + describe 'GET #users' do + before { get :users } - it { should be_success } - it { should render_template :users } + it { is_expected.to be_success } + it { is_expected.to render_template :users } end - describe "GET #date" do + describe 'GET #date' do before { get :date } - it { should be_success } - it { should render_template :date } + it { is_expected.to be_success } + it { is_expected.to render_template :date } end - describe "GET #servers" do - before { get :servers} + describe 'GET #servers' do + before { get :servers } - it { should be_success } - it { should render_template :servers } + it { is_expected.to be_success } + it { is_expected.to render_template :servers } end end diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index 34ff0876..a3188112 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Admin::UsersController do @@ -5,121 +7,121 @@ login_admin subject { response } - describe "GET #index" do + describe 'GET #index' do before { get :index } - it { should be_success } - it { should render_template :index } + it { is_expected.to be_success } + it { is_expected.to render_template :index } end - describe "GET #payers" do + describe 'GET #payers' do before { get :payers } - it { should be_success } - it { should render_template :payers } + it { is_expected.to be_success } + it { is_expected.to render_template :payers } end - describe "GET #this_month_payers" do + describe 'GET #this_month_payers' do before { get :this_month_payers } - it { should be_success } - it { should render_template :this_month_payers } + it { is_expected.to be_success } + it { is_expected.to render_template :this_month_payers } end - describe "GET #show" do + describe 'GET #show' do let(:user) { create(:user) } - before { get :show, id: user.id} + before { get :show, id: user.id } - it { should be_success } - it { should render_template :show } + it { is_expected.to be_success } + it { is_expected.to render_template :show } end - describe "GET #edit" do + describe 'GET #edit' do let(:user) { create(:user) } - before { get :edit, id: user.id} + before { get :edit, id: user.id } - it { should be_success } - it { should render_template :edit } + it { is_expected.to be_success } + it { is_expected.to render_template :edit } end - describe "PUT #update" do + describe 'PUT #update' do let(:user) { create(:user) } before { put :update, id: user.id, user: attrs } - context "params correct" do - let(:attrs) { Hash[email: "new@mail.ru"] } + context 'params correct' do + let(:attrs) { Hash[email: 'new@mail.ru'] } - it "redirects to users path" do - subject.should redirect_to admin_users_path + it 'redirects to users path' do + expect(subject).to redirect_to admin_users_path end end - context "params invalid" do + context 'params invalid' do let(:attrs) { Hash[plan_id: nil] } - it "renders edit form" do + it 'renders edit form' do expect(subject).to render_template :edit end end end - describe "PUT #withdraw" do + describe 'PUT #withdraw' do let(:user) { create(:user_with_balance) } - it "creates new withdrawal" do - expect { + it 'creates new withdrawal' do + expect do put :withdraw, id: user.id - }.to change(Withdrawal, :count).by(1) + end.to change(Withdrawal, :count).by(1) end end - describe "PUT #prolongate" do + describe 'PUT #prolongate' do let!(:user) { create(:user_with_balance) } let!(:withdrawal) { create(:withdrawal, user: user) } let(:attrs) { Hash[days_number: 10] } - it "creates new withdrawal prolongation" do - expect { + it 'creates new withdrawal prolongation' do + expect do put :prolongate, id: user.id, withdrawal_prolongation: attrs - }.to change(WithdrawalProlongation, :count).by(1) + end.to change(WithdrawalProlongation, :count).by(1) end - it "prolongation is created for last withdrawal" do - expect { + it 'prolongation is created for last withdrawal' do + expect do put :prolongate, id: user.id, withdrawal_prolongation: attrs - }.to change(user.withdrawals.last.withdrawal_prolongations, :count).by(1) + end.to change(user.withdrawals.last.withdrawal_prolongations, :count).by(1) end - it "prolongation days number equals form data" do + it 'prolongation days number equals form data' do put :prolongate, id: user.id, withdrawal_prolongation: attrs expect(user.withdrawals.last.withdrawal_prolongations.last.days_number).to eq attrs[:days_number] end end - describe "PUT #payment" do + describe 'PUT #payment' do let!(:user) { create(:user) } let!(:pay_system) { create(:pay_system) } - let(:attrs) { Hash[amount: 100, pay_system_id: pay_system.id, comment: "some comment"] } + let(:attrs) { Hash[amount: 100, pay_system_id: pay_system.id, comment: 'some comment'] } - it "creates new payment" do - expect { + it 'creates new payment' do + expect do put :payment, id: user.id, payment: attrs - }.to change(Payment, :count).by(1) + end.to change(Payment, :count).by(1) end - context "after request" do + context 'after request' do before { put :payment, id: user.id, payment: attrs } - it "payment is accepted" do + it 'payment is accepted' do expect(Payment.last.accepted?).to be true end - it "payment has comment from attrs" do + it 'payment has comment from attrs' do expect(Payment.last.comment).to eq attrs[:comment] end - it "payment is marked as manual" do + it 'payment is marked as manual' do expect(Payment.last.manual_payment).to be true end end @@ -131,7 +133,7 @@ get :emails_export end - it { should be_success } + it { is_expected.to be_success } it 'contains emails of all users' do emails = User.all.map(&:email).join(',') @@ -148,10 +150,10 @@ end it 'send email' do - User.any_instance.stubs(:test_period_started_at).returns(Date.current) - expect { + allow_any_instance_of(User).to receive(:test_period_started_at).and_return(Date.current) + expect do put :enable_test_period, id: user.id - }.to change(ActionMailer::Base.deliveries, :size).by(1) + end.to change(ActionMailer::Base.deliveries, :size).by(1) end it 'redirects to user path' do @@ -164,7 +166,7 @@ let(:user) { create(:user) } it 'calles disable action' do - TestPeriod.any_instance.expects(:disable!) + allow_any_instance_of(TestPeriod).to receive(:disable!) put :disable_test_period, id: user.id end @@ -178,7 +180,7 @@ let(:user) { create(:user) } it 'calls disconnector' do - ForcedDisconnect.any_instance.expects(:invoke) + allow_any_instance_of(ForcedDisconnect).to receive(:invoke) put :force_disconnect, id: user.id end diff --git a/spec/controllers/api/authentication_controller_spec.rb b/spec/controllers/api/authentication_controller_spec.rb index 9be4a950..6bc4d1cf 100644 --- a/spec/controllers/api/authentication_controller_spec.rb +++ b/spec/controllers/api/authentication_controller_spec.rb @@ -1,36 +1,36 @@ +# frozen_string_literal: true + require 'spec_helper' describe Api::AuthenticationController do - it_behaves_like "validating signature", :auth + it_behaves_like 'validating signature', :auth - describe "POST #auth" do + describe 'POST #auth' do let(:user) { create(:user_with_balance) } let(:server) { create(:server) } before do user.plan.servers << server - Api::AuthenticationController.any_instance.stubs(:valid_api_call?).returns(true) + allow_any_instance_of(Api::AuthenticationController).to receive(:valid_api_call?).and_return(true) end - context "valid credentials" do + context 'valid credentials' do let(:params) { Hash[login: user.vpn_login, password: user.vpn_password, hostname: server.hostname] } before { create(:withdrawal, user: user) } - it "returns 200 status" do + it 'returns 200 status' do post :auth, params expect(response.status).to eq 200 end end - context "invalid credentials" do - let(:params) { Hash[login: user.vpn_login, password: "asd", hostname: server.hostname] } + context 'invalid credentials' do + let(:params) { Hash[login: user.vpn_login, password: 'asd', hostname: server.hostname] } - it "returns 404 status" do + it 'returns 404 status' do post :auth, params expect(response.status).to eq 404 end end end - end - diff --git a/spec/controllers/api/connection_controller_spec.rb b/spec/controllers/api/connection_controller_spec.rb index 6ec71c29..caced7cd 100644 --- a/spec/controllers/api/connection_controller_spec.rb +++ b/spec/controllers/api/connection_controller_spec.rb @@ -1,28 +1,30 @@ +# frozen_string_literal: true + require 'spec_helper' describe Api::ConnectionController do let(:user) { create(:user) } let(:server) { create(:server) } - let(:attrs) { Hash[login: user.vpn_login, hostname: server.hostname, traffic_in: 10, traffic_out: 15] } + let(:attrs) { { login: user.vpn_login, hostname: server.hostname, traffic_in: '10', traffic_out: '15' } } subject { response } - it_behaves_like "validating signature", :connect - it_behaves_like "validating signature", :disconnect + it_behaves_like 'validating signature', :connect + it_behaves_like 'validating signature', :disconnect - describe "api calls" do + describe 'api calls' do before do - Api::ConnectionController.any_instance.stubs(:valid_api_call?).returns(true) + allow_any_instance_of(Api::ConnectionController).to receive(:valid_api_call?).and_return(true) end - describe "POST #connect" do - it "calls connector" do - Connector.any_instance.expects(:invoke).once + describe 'POST #connect' do + it 'calls connector' do + allow_any_instance_of(Connector).to receive(:invoke).once post :connect, attrs end - it "passed connect action to connector" do - connector = Connector.new(attrs.merge!(action: "connect")) - Connector.expects(:new).with() { |params| params.include?(:action) }.returns(connector) + it 'passed connect action to connector' do + connector = Connector.new(attrs.merge!(action: 'connect')) + expect(Connector).to receive(:new).with(attrs).and_return(connector) post :connect, attrs end @@ -36,7 +38,7 @@ post :connect, params end - it { should be_json } + it { is_expected.to be_json } it 'response includes options list' do expect(json).to have_key('options') @@ -44,15 +46,15 @@ end end - describe "POST #disconnect" do - it "calls connector" do - Connector.any_instance.expects(:invoke).once + describe 'POST #disconnect' do + it 'calls connector' do + allow_any_instance_of(Connector).to receive(:invoke).once post :disconnect, attrs end - it "passed disconnect action to connector" do - connector = Connector.new(attrs.merge!(action: "connect")) - Connector.expects(:new).with() { |params| params.include?(:action) }.returns(connector) + it 'passed disconnect action to connector' do + connector = Connector.new(attrs.merge!(action: 'disconnect')) + expect(Connector).to receive(:new).with(attrs).and_return(connector) post :disconnect, attrs end end diff --git a/spec/controllers/billing/options_controller_spec.rb b/spec/controllers/billing/options_controller_spec.rb index 45ce9d66..5e455a41 100644 --- a/spec/controllers/billing/options_controller_spec.rb +++ b/spec/controllers/billing/options_controller_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Billing::OptionsController do @@ -6,8 +8,8 @@ describe 'GET #index' do before { get :index } - it { should be_success } - it { should render_template :index } + it { is_expected.to be_success } + it { is_expected.to render_template :index } end describe 'POST #create' do @@ -15,7 +17,7 @@ let(:option_code) { option.code } before do - Option::Activator.stubs(:run).with(@user, option_code).returns(activation_result) + allow(Option::Activator).to receive(:run).with(@user, option_code).and_return(activation_result) post :create, code: option_code end @@ -62,7 +64,7 @@ let!(:user_option) { create(:user_option, state: 'enabled', user: @user, option: option) } it 'calles toggle! on option' do - UserOption.any_instance.expects(:toggle!) + allow_any_instance_of(UserOption).to receive(:toggle!) put :toggle, id: option.id end end diff --git a/spec/controllers/billing/payments_controller_spec.rb b/spec/controllers/billing/payments_controller_spec.rb index 8bf9b3c9..76efd411 100644 --- a/spec/controllers/billing/payments_controller_spec.rb +++ b/spec/controllers/billing/payments_controller_spec.rb @@ -1,44 +1,44 @@ +# frozen_string_literal: true + require 'spec_helper' describe Billing::PaymentsController do - - context "when not authorized" do - it "does not respond" do + context 'when not authorized' do + it 'does not respond' do get :index expect(response).to redirect_to new_user_session_path end end - context "when regular user" do + context 'when regular user' do let(:pay_system) { create(:pay_system) } login_user - it "displays pay systems list" do + it 'displays pay systems list' do get :index - response.should render_template :index + expect(response).to render_template :index end - it "displays new payment form" do + it 'displays new payment form' do get :new, code: pay_system.code - response.should render_template :new + expect(response).to render_template :new end - it "redirects to merchant form page on payment create" do + it 'redirects to merchant form page on payment create' do post :create, payment: attributes_for(:payment).merge!(pay_system_id: pay_system.id) - response.should redirect_to merchant_billing_payment_path(Payment.last) + expect(response).to redirect_to merchant_billing_payment_path(Payment.last) end - context "when payment is already accepted" do + context 'when payment is already accepted' do before do @payment = create(:payment, user: @user) @payment.accept! end - it "redirects to pay systems list" do + it 'redirects to pay systems list' do get :merchant, id: @payment.id - response.should redirect_to billing_payments_path + expect(response).to redirect_to billing_payments_path end end end - end diff --git a/spec/controllers/billing/referrers_controller_spec.rb b/spec/controllers/billing/referrers_controller_spec.rb index 6d4fe622..4e1d33ae 100644 --- a/spec/controllers/billing/referrers_controller_spec.rb +++ b/spec/controllers/billing/referrers_controller_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Billing::ReferrersController do @@ -6,7 +8,7 @@ describe 'GET #index' do before { get :index } - it { should be_success } - it { should render_template :index } + it { is_expected.to be_success } + it { is_expected.to render_template :index } end end diff --git a/spec/controllers/billing/robokassa_controller_spec.rb b/spec/controllers/billing/robokassa_controller_spec.rb index 03feea35..f96c864a 100644 --- a/spec/controllers/billing/robokassa_controller_spec.rb +++ b/spec/controllers/billing/robokassa_controller_spec.rb @@ -1,42 +1,46 @@ +# frozen_string_literal: true + require 'spec_helper' describe Billing::RobokassaController do render_views subject { response } - it_behaves_like "validating pay_system state", :result, "InvId" + it_behaves_like 'validating pay_system state', :result, 'InvId' it_behaves_like 'has success and fail responders' - describe "POST #result" do - context "notification signature is not valid" do + describe 'POST #result' do + context 'notification signature is not valid' do let(:attrs) { Hash[] } - it "raises error" do - expect { + it 'raises error' do + expect do post :result, attrs - }.to raise_error "Invalid robokassa notification" + end.to raise_error 'Invalid robokassa notification' end end - context "valid notification" do + context 'valid notification' do let!(:payment) { create :payment } - let(:attrs) { Hash["OutSum"=>"9.99", "InvId"=>"10", "SignatureValue"=>"D25F8F107E3482EF3CCAFC620CC8BA3E"] } + let(:attrs) { Hash['OutSum' => '9.99', 'InvId' => '10', 'SignatureValue' => 'D25F8F107E3482EF3CCAFC620CC8BA3E'] } before do - ActiveMerchant::Billing::Integrations::Robokassa::Notification.any_instance.expects(:acknowledge).returns(true) - Payment.stubs(:find).returns(payment) + allow_any_instance_of(ActiveMerchant::Billing::Integrations::Robokassa::Notification) + .to receive(:acknowledge) + .and_return(true) + allow(Payment).to receive(:find).and_return(payment) post :result, attrs end - it "returns 200 state" do + it 'returns 200 state' do expect(subject.status).to eq 200 end - it "renders text" do - expect(subject.body).to include "Done" + it 'renders text' do + expect(subject.body).to include 'Done' end - it "changes payment state to accepted" do + it 'changes payment state to accepted' do expect(payment.reload.accepted?).to be true end end diff --git a/spec/controllers/billing/servers_controller_spec.rb b/spec/controllers/billing/servers_controller_spec.rb index 42de1242..0dea13ca 100644 --- a/spec/controllers/billing/servers_controller_spec.rb +++ b/spec/controllers/billing/servers_controller_spec.rb @@ -21,7 +21,7 @@ before { server.plans << @user.plan } it 'calls config builder' do - ServerConfigBuilder.any_instance.expects(:to_text).returns(config) + allow_any_instance_of(ServerConfigBuilder).to receive(:to_text).and_return(config) get :download_config, id: server.id end diff --git a/spec/controllers/billing/webmoney_controller_spec.rb b/spec/controllers/billing/webmoney_controller_spec.rb index 0d65815f..04e7df24 100644 --- a/spec/controllers/billing/webmoney_controller_spec.rb +++ b/spec/controllers/billing/webmoney_controller_spec.rb @@ -1,71 +1,91 @@ +# frozen_string_literal: true + require 'spec_helper' describe Billing::WebmoneyController do render_views subject { response } - it_behaves_like "validating pay_system state", :result, "LMI_PAYMENT_NO" + it_behaves_like 'validating pay_system state', :result, 'LMI_PAYMENT_NO' it_behaves_like 'has success and fail responders' - describe "POST #result" do - describe "test request" do - context "key param is not present" do + describe 'POST #result' do + describe 'test request' do + context 'key param is not present' do let(:attrs) { Hash[] } before { post :result, attrs } - it "renders YES text" do - expect(subject.body).to include "YES" + it 'renders YES text' do + expect(subject.body).to include 'YES' end end end - describe "final request" do - context "transaction_key_id is not defined" do - let(:attrs) { Hash["LMI_HASH" => "test_hash"] } + describe 'final request' do + context 'transaction_key_id is not defined' do + let(:attrs) { { 'LMI_HASH' => 'test_hash' } } - it "raises error" do - expect { + it 'raises error' do + expect do post :result, attrs - }.to raise_error "Undefined transaction_item_id" + end.to raise_error 'Undefined transaction_item_id' end end - context "notification signature is not valid" do + context 'notification signature is not valid' do let!(:payment) { create :payment } - let(:attrs) { Hash["LMI_HASH" => "test_hash", "LMI_PAYMENT_NO" => payment.id, "LMI_PAYMENT_AMOUNT" => "123"] } + let(:attrs) { { 'LMI_HASH' => 'test_hash', 'LMI_PAYMENT_NO' => payment.id, 'LMI_PAYMENT_AMOUNT' => '123' } } - it "raises error" do - expect { + it 'raises error' do + expect do post :result, attrs - }.to raise_error "Invalid webmoney verification key" + end.to raise_error 'Invalid webmoney verification key' end end - context "valid notification" do + context 'valid notification' do let!(:payment) { create :payment } - let(:attrs) { Hash["LMI_MODE"=>"1", "LMI_PAYMENT_AMOUNT"=>"9.99", "LMI_PAYEE_PURSE"=>"Z164234536204", "LMI_PAYMENT_NO"=>"15", "LMI_PAYER_WM"=>"273350110703", "LMI_PAYER_PURSE"=>"Z133417776395", "LMI_SYS_INVS_NO"=>"407", "LMI_SYS_TRANS_NO"=>"601", "LMI_SYS_TRANS_DATE"=>"20131129 16:39:38", "LMI_HASH"=>"EDB5707A4FFC27225E59BFBB1CFB5CEA", "LMI_PAYMENT_DESC"=>"#15", "LMI_LANG"=>"ru-RU"] } + let(:attrs) do + { + 'LMI_MODE' => '1', + 'LMI_PAYMENT_AMOUNT' => '9.99', + 'LMI_PAYEE_PURSE' => 'Z164234536204', + 'LMI_PAYMENT_NO' => '15', + 'LMI_PAYER_WM' => '273350110703', + 'LMI_PAYER_PURSE' => 'Z133417776395', + 'LMI_SYS_INVS_NO' => '407', + 'LMI_SYS_TRANS_NO' => '601', + 'LMI_SYS_TRANS_DATE' => '20131129 16:39:38', + 'LMI_HASH' => 'EDB5707A4FFC27225E59BFBB1CFB5CEA', + 'LMI_PAYMENT_DESC' => '#15', + 'LMI_LANG' => 'ru-RU' + } + end before do - ActiveMerchant::Billing::Integrations::Webmoney::Notification.any_instance.expects(:recognizes?).returns(true) - ActiveMerchant::Billing::Integrations::Webmoney::Notification.any_instance.expects(:acknowledge).returns(true) - Payment.stubs(:find).returns(payment) + allow_any_instance_of(ActiveMerchant::Billing::Integrations::Webmoney::Notification) + .to receive(:recognizes?) + .and_return(true) + allow_any_instance_of(ActiveMerchant::Billing::Integrations::Webmoney::Notification) + .to receive(:acknowledge) + .and_return(true) + allow(Payment).to receive(:find).and_return(payment) post :result, attrs end - it "returns 200 state" do + it 'returns 200 state' do expect(subject.status).to eq 200 end - it "renders text" do - expect(subject.body).to include "Done" + it 'renders text' do + expect(subject.body).to include 'Done' end - it "changes payment state to accepted" do + it 'changes payment state to accepted' do expect(payment.reload.accepted?).to be true end end end end - end diff --git a/spec/features/billing/payments_page_spec.rb b/spec/features/billing/payments_page_spec.rb index 067d1d3a..8448772c 100644 --- a/spec/features/billing/payments_page_spec.rb +++ b/spec/features/billing/payments_page_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'Payments page' do @@ -5,7 +7,7 @@ it_behaves_like 'creates payment for pay system', 'wmr' it_behaves_like 'creates payment for pay system', 'yandex' - describe "pay systems list" do + describe 'pay systems list' do let!(:disabled_pay_system) { create(:pay_system) } let!(:enabled_pay_system) { create(:enabled_pay_system) } @@ -18,7 +20,7 @@ expect(page).to have_link enabled_pay_system.name end - it "does not display link to disabled pay system" do + it 'does not display link to disabled pay system' do expect(page).not_to have_link disabled_pay_system.name end end @@ -43,7 +45,7 @@ let(:amount) { 650 } it 'contains price in rubles' do - Currencies::CourseConverter.any_instance.expects(:convert_amount).returns(amount) + allow_any_instance_of(Currencies::CourseConverter).to receive(:convert_amount).and_return(amount) visit(new_payment_page_path) expect(page).to have_selector("input[value='#{amount}']") end diff --git a/spec/lib/currencies/course_converter_spec.rb b/spec/lib/currencies/course_converter_spec.rb index 4eccdc18..59895bdc 100644 --- a/spec/lib/currencies/course_converter_spec.rb +++ b/spec/lib/currencies/course_converter_spec.rb @@ -1,20 +1,22 @@ +# frozen_string_literal: true + require 'spec_helper' describe Currencies::CourseConverter do - subject { described_class.new(currency_from: "eur", currency_to: "usd", amount: 100) } + subject { described_class.new(currency_from: 'eur', currency_to: 'usd', amount: 100) } - describe "amount conversion" do + describe 'amount conversion' do let(:course) { 2 } - before { Currencies::Course.any_instance.stubs(:get).returns(course) } + before { allow_any_instance_of(Currencies::Course).to receive(:get).and_return(course) } it 'devides currency by amount' do expect(subject.convert_amount).to eq 200 end context 'course is string' do - let(:course) { "2" } + let(:course) { '2' } - it "converts string to int" do + it 'converts string to int' do expect(subject.convert_amount).to eq 200 end end diff --git a/spec/lib/currencies/course_spec.rb b/spec/lib/currencies/course_spec.rb index 2e3eac61..1ecfb6cd 100644 --- a/spec/lib/currencies/course_spec.rb +++ b/spec/lib/currencies/course_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Currencies::Course do @@ -5,10 +7,10 @@ let(:redis) { Redis.new } before do - described_class.stubs(:fetch_course_from_web).returns(online_course) + allow(described_class).to receive(:fetch_course_from_web).and_return(online_course) end - describe "updating all courses" do + describe 'updating all courses' do subject { described_class } before do @@ -16,35 +18,35 @@ subject.update_courses end - it "sets course for eur" do - expect(redis.get("smartvpn:eur_usd")).not_to be_nil + it 'sets course for eur' do + expect(redis.get('smartvpn:eur_usd')).not_to be_nil end - it "sets course for usd" do - expect(redis.get("smartvpn:rub_usd")).not_to be_nil + it 'sets course for usd' do + expect(redis.get('smartvpn:rub_usd')).not_to be_nil end - it "sets updated_at value" do - expect(redis.get("smartvpn:courses:updated_at")).not_to be_nil + it 'sets updated_at value' do + expect(redis.get('smartvpn:courses:updated_at')).not_to be_nil end end - describe "fetching course" do - subject { described_class.new("eur", "usd") } + describe 'fetching course' do + subject { described_class.new('eur', 'usd') } before { redis.flushall } context 'currency from equal to currency to' do - subject { described_class.new("usd", "usd") } + subject { described_class.new('usd', 'usd') } it 'returns 1' do expect(subject.get).to eq 1 end end - context "redis es empty" do + context 'redis es empty' do it 'fetching from web' do - subject.expects(:parse_from_web).once + expect(subject).to receive(:parse_from_web).once subject.get end @@ -53,11 +55,11 @@ end end - context "record exists in redis" do - let(:cached_course) { "2" } + context 'record exists in redis' do + let(:cached_course) { '2' } before do - redis.set("smartvpn:eur_usd", cached_course) - redis.set("smartvpn:courses:updated_at", Time.current) + redis.set('smartvpn:eur_usd', cached_course) + redis.set('smartvpn:courses:updated_at', Time.current) end it 'returns update date' do @@ -65,7 +67,7 @@ end it 'loading record from redis' do - subject.expects(:fetch_from_redis) + expect(subject).to receive(:fetch_from_redis) subject.get end @@ -74,7 +76,7 @@ end it 'does not fetch web' do - subject.expects(:parse_from_web).never + expect(subject).not_to receive(:parse_from_web) subject.get end end diff --git a/spec/models/connect_spec.rb b/spec/models/connect_spec.rb index 3d3c0ea4..398aae23 100644 --- a/spec/models/connect_spec.rb +++ b/spec/models/connect_spec.rb @@ -1,16 +1,18 @@ +# frozen_string_literal: true + require 'spec_helper' describe Connect do subject { build(:connect) } - it { should be_valid } - it { should belong_to(:user) } - it { should belong_to(:server) } + it { is_expected.to be_valid } + it { is_expected.to belong_to(:user) } + it { is_expected.to belong_to(:server) } - describe "instance" do + describe 'instance' do subject { create(:connect) } - it "returns server hostname" do + it 'returns server hostname' do expect(subject.hostname).to eq subject.server.hostname end end @@ -29,4 +31,3 @@ # created_at :datetime # updated_at :datetime # - diff --git a/spec/models/disconnect_spec.rb b/spec/models/disconnect_spec.rb index 30cec63c..1ac153c9 100644 --- a/spec/models/disconnect_spec.rb +++ b/spec/models/disconnect_spec.rb @@ -5,12 +5,12 @@ describe Disconnect do subject { build(:disconnect) } - it { should be_valid } - it { should belong_to(:user) } - it { should belong_to(:server) } + it { is_expected.to be_valid } + it { is_expected.to belong_to(:user) } + it { is_expected.to belong_to(:server) } - it { should validate_presence_of(:traffic_in) } - it { should validate_presence_of(:traffic_out) } + it { is_expected.to validate_presence_of(:traffic_in) } + it { is_expected.to validate_presence_of(:traffic_out) } it_behaves_like 'loads created by last days', :disconnect diff --git a/spec/models/dto/admin/descrete_base_spec.rb b/spec/models/dto/admin/descrete_base_spec.rb index 7fa75092..4120d34a 100644 --- a/spec/models/dto/admin/descrete_base_spec.rb +++ b/spec/models/dto/admin/descrete_base_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Dto::Admin::DescreteBase do @@ -6,7 +8,7 @@ describe '#amounts' do before do - described_class.any_instance.expects(:values_by_days).at_least_once.returns({}) + allow_any_instance_of(described_class).to receive(:values_by_days).and_return({}) end it 'calls values_by_days method' do diff --git a/spec/models/option_spec.rb b/spec/models/option_spec.rb index 56d4767a..810eed76 100644 --- a/spec/models/option_spec.rb +++ b/spec/models/option_spec.rb @@ -1,17 +1,19 @@ +# frozen_string_literal: true + require 'spec_helper' describe Option do - it { should validate_presence_of :name } - it { should validate_presence_of :code } - it { should have_and_belong_to_many(:plans) } - it { should have_many(:users) } - it { should have_many(:user_options) } + it { is_expected.to validate_presence_of :name } + it { is_expected.to validate_presence_of :code } + it { is_expected.to have_and_belong_to_many(:plans) } + it { is_expected.to have_many(:users) } + it { is_expected.to have_many(:user_options) } - describe ".state" do + describe '.state' do subject { described_class.new } - context "when new" do - it "has disabled state" do + context 'when new' do + it 'has disabled state' do expect(subject.disabled?).to be true end end @@ -48,7 +50,7 @@ let(:code) { 'proxy' } it 'builds hook instance' do - Options::Hooks::Proxy.expects(:new).with(user, subject) + allow(Options::Hooks::Proxy).to receive(:new).with(user, subject) hook end diff --git a/spec/models/options/hooks/proxy_spec.rb b/spec/models/options/hooks/proxy_spec.rb index 8ee620d5..37ed2d9d 100644 --- a/spec/models/options/hooks/proxy_spec.rb +++ b/spec/models/options/hooks/proxy_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Options::Hooks::Proxy do @@ -8,7 +10,7 @@ describe '.connect' do before do - ::Proxy::Rater.any_instance.expects(:find_best).returns(proxy) + allow_any_instance_of(::Proxy::Rater).to receive(:find_best).and_return(proxy) end it 'calls proxy rater' do @@ -16,9 +18,9 @@ end it 'creates proxy connect record' do - expect { + expect do subject.connect - }.to change(proxy.connects, :count).by(1) + end.to change(proxy.connects, :count).by(1) end it 'returns hash' do diff --git a/spec/models/pay_system_spec.rb b/spec/models/pay_system_spec.rb index ec167946..6ebbd631 100644 --- a/spec/models/pay_system_spec.rb +++ b/spec/models/pay_system_spec.rb @@ -1,14 +1,16 @@ +# frozen_string_literal: true + require 'spec_helper' describe PaySystem do subject { build(:pay_system) } - it { should be_valid } - it { should validate_presence_of(:name) } - it { should validate_presence_of(:code) } - it { should have_many(:payments) } + it { is_expected.to be_valid } + it { is_expected.to validate_presence_of(:name) } + it { is_expected.to validate_presence_of(:code) } + it { is_expected.to have_many(:payments) } - describe ".enabled scope" do + describe '.enabled scope' do subject { described_class } before do @@ -16,33 +18,33 @@ create_list(:pay_system, 3) end - it "returns only enabled pay systems" do + it 'returns only enabled pay systems' do expect(subject.enabled.size).to eq 2 end end - describe "states" do + describe 'states' do subject { build(:pay_system) } - it "initially in disabled state" do + it 'initially in disabled state' do expect(subject.disabled?).to be true end - context "enable! action" do - it "changes state to enabled" do - expect { + context 'enable! action' do + it 'changes state to enabled' do + expect do subject.enable! - }.to change(subject, :state).to("enabled") + end.to change(subject, :state).to('enabled') end end - context "disable! action" do + context 'disable! action' do before { subject.enable! } - it "changes state to disabled" do - expect { + it 'changes state to disabled' do + expect do subject.disable! - }.to change(subject, :state).to("disabled") + end.to change(subject, :state).to('disabled') end end end @@ -59,4 +61,3 @@ # updated_at :datetime # description :text # - diff --git a/spec/models/payment_spec.rb b/spec/models/payment_spec.rb index f49c0726..edb39d53 100644 --- a/spec/models/payment_spec.rb +++ b/spec/models/payment_spec.rb @@ -1,11 +1,13 @@ +# frozen_string_literal: true + require 'spec_helper' describe Payment do subject { build(:payment) } - it { should be_valid } - it { should validate_presence_of(:user_id) } - it { should validate_presence_of(:amount) } + it { is_expected.to be_valid } + it { is_expected.to validate_presence_of(:user_id) } + it { is_expected.to validate_presence_of(:amount) } it_behaves_like 'loads created by last days', :disconnect @@ -15,7 +17,7 @@ let(:course) { 0.032 } before do - Currencies::CourseConverter.any_instance.stubs(:course).returns(course) + allow_any_instance_of(Currencies::CourseConverter).to receive(:course).and_return(course) end it 'saves usd amount' do @@ -23,34 +25,33 @@ end it 'converts rub by course' do - expect(payment.usd_amount).to eq payment.amount * course + expect(payment.usd_amount).to eq(payment.amount * course) end end - context "when created" do + context 'when created' do let(:user) { create(:user) } let(:pay_system) { create(:pay_system) } - it "is in peding state" do + it 'is in peding state' do payment = Payment.create!(user_id: user.id, pay_system_id: pay_system.id, amount: 10) - expect(payment.state).to eq "pending" + expect(payment.state).to eq 'pending' end end - context "on accept event" do - - before { Currencies::CourseConverter.any_instance.stubs(:course).returns(0.5) } + context 'on accept event' do + before { allow_any_instance_of(Currencies::CourseConverter).to receive(:course).and_return(0.5) } - describe "balance increase" do + describe 'balance increase' do let(:user) { create(:user_with_balance) } let(:pay_system) { create(:pay_system) } let!(:withdrawal) { create(:withdrawal, user: user) } let!(:payment) { create(:payment, user: user, pay_system: pay_system) } - it "changes user balance on amount" do + it 'changes user balance on amount' do initial_balance = user.reload.balance payment.accept! - expect(user.reload.balance).to eq (initial_balance + payment.amount) + expect(user.reload.balance).to eq(initial_balance + payment.amount) end context 'pay system in non-usd' do @@ -59,55 +60,47 @@ it 'adds usd_amount' do initial_balance = user.reload.balance payment.accept! - expect(user.reload.balance).to eq (initial_balance + payment.usd_amount) + expect(user.reload.balance).to eq(initial_balance + payment.usd_amount) end it 'does not add non-usd amount' do initial_balance = user.reload.balance payment.accept! - expect(user.reload.balance).not_to eq (initial_balance + payment.amount) + expect(user.reload.balance).not_to eq(initial_balance + payment.amount) end end end - describe "balance withdrawal" do + describe 'balance withdrawal' do subject { create(:payment, user: user) } - context "user is unpaid" do + context 'user is unpaid' do let(:user) { create(:user_with_balance) } - it "creates new withdrawal" do - expect { - subject.accept! - }.to change(Withdrawal, :count).by(1) + it 'creates new withdrawal' do + expect { subject.accept! }.to change(Withdrawal, :count).by(1) end end - context "user is paid" do + context 'user is paid' do let(:user) { create(:user_with_balance) } before { create :withdrawal, user: user } - it "does not create withdrawal" do - expect { - subject.accept! - }.not_to change(Withdrawal, :count) + it 'does not create withdrawal' do + expect { subject.accept! }.not_to change(Withdrawal, :count) end end - context "user unpaid and has no balance,", focus: true do + context 'user unpaid and has no balance,', focus: true do let(:user) { create(:user) } subject { create(:payment, amount: 5, user: user) } - it "does not create withdrawal" do - expect { - subject.accept! - }.not_to change(Withdrawal, :count) + it 'does not create withdrawal' do + expect { subject.accept! }.not_to change(Withdrawal, :count) end - it "sends notification" do - expect { - subject.accept! - }.to change(CanNotWithdrawNotificationWorker.jobs, :size).by(1) + it 'sends notification' do + expect { subject.accept! }.to change(CanNotWithdrawNotificationWorker.jobs, :size).by(1) end end end @@ -126,4 +119,3 @@ # created_at :datetime # updated_at :datetime # - diff --git a/spec/models/plan_has_server_spec.rb b/spec/models/plan_has_server_spec.rb index 2adf4fec..361867a2 100644 --- a/spec/models/plan_has_server_spec.rb +++ b/spec/models/plan_has_server_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + require 'spec_helper' describe PlanHasServer do - it { should belong_to(:server) } - it { should belong_to(:plan) } + it { is_expected.to belong_to(:server) } + it { is_expected.to belong_to(:plan) } end # == Schema Information @@ -15,4 +17,3 @@ # created_at :datetime # updated_at :datetime # - diff --git a/spec/models/plan_spec.rb b/spec/models/plan_spec.rb index eff1d7ac..a53317a1 100644 --- a/spec/models/plan_spec.rb +++ b/spec/models/plan_spec.rb @@ -1,52 +1,54 @@ +# frozen_string_literal: true + require 'spec_helper' describe Plan do subject(:plan) { build(:plan) } - it { should be_valid } - it { should validate_presence_of(:name) } - it { should validate_presence_of(:price) } - it { should validate_presence_of(:code) } - it { should validate_presence_of(:description) } + it { is_expected.to be_valid } + it { is_expected.to validate_presence_of(:name) } + it { is_expected.to validate_presence_of(:price) } + it { is_expected.to validate_presence_of(:code) } + it { is_expected.to validate_presence_of(:description) } - it { should have_many(:users) } - it { should have_many(:included_servers) } - it { should have_many(:servers) } + it { is_expected.to have_many(:users) } + it { is_expected.to have_many(:included_servers) } + it { is_expected.to have_many(:servers) } - it { should have_and_belong_to_many(:options) } + it { is_expected.to have_and_belong_to_many(:options) } - describe "regular plans scope" do + describe 'regular plans scope' do let!(:special_plan) { create(:plan, special: true) } let!(:regular_plan1) { create(:plan) } let!(:regular_plan2) { create(:plan) } subject { Plan.regular } - it "returns non-special plans" do + it 'returns non-special plans' do expect(subject).to eq [regular_plan1, regular_plan2] end - it "does not return special plans" do + it 'does not return special plans' do expect(subject).not_to include special_plan end end - describe "enabled" do + describe 'enabled' do let(:enabled_plan1) { create(:plan) } let(:enabled_plan2) { create(:plan) } let(:disabled_plan) { create(:plan, enabled: false) } subject { Plan.enabled } - it "returns only enabled plans" do + it 'returns only enabled plans' do expect(subject).to eq [enabled_plan1, enabled_plan2] end - it "does not return disabled plan" do + it 'does not return disabled plan' do expect(subject).not_to include disabled_plan end end - describe ".to_s" do - it "returns its name" do + describe '.to_s' do + it 'returns its name' do expect(subject.to_s).to eq subject.name end end @@ -76,4 +78,3 @@ # special :boolean default(FALSE) # enabled :boolean default(FALSE) # - diff --git a/spec/models/promo_spec.rb b/spec/models/promo_spec.rb index 1e501ace..5cc2dae1 100644 --- a/spec/models/promo_spec.rb +++ b/spec/models/promo_spec.rb @@ -1,73 +1,78 @@ +# frozen_string_literal: true + require 'spec_helper' describe Promo do let(:promo) { build(:promo, promoter_type: 'discount') } subject { promo } - describe "validations" do - it { should validate_presence_of :name } - it { should validate_presence_of :type } - it { should validate_presence_of :promoter_type } + describe 'validations' do + it { is_expected.to validate_presence_of :name } + it { is_expected.to validate_presence_of :type } + it { is_expected.to validate_presence_of :promoter_type } end - describe ".withdrawal scope" do + describe '.withdrawal scope' do let!(:withdrawal1) { create(:promo) } let!(:withdrawal2) { create(:promo) } let!(:withdrawal3) { create(:option_promo) } subject { described_class.withdrawal } - it "returns only withdrawal promos" do + it 'returns only withdrawal promos' do expect(subject).to eq [withdrawal1, withdrawal2] end end - describe ".active scope" do + describe '.active scope' do let!(:active) { create(:active_promo, date_from: 1.week.ago, date_to: 1.week.from_now) } let!(:inactive) { create(:promo) } let!(:active_but_expired) { create(:promo, date_from: 1.month.ago, date_to: 1.week.ago) } - it "returns promos with active state and that runs today" do + it 'returns promos with active state and that runs today' do expect(described_class.active).to include active end - it "does not return promo with expired date" do + it 'does not return promo with expired date' do expect(described_class.active).not_to include active_but_expired end - it "does not returns promo with inactive state" do + it 'does not returns promo with inactive state' do expect(described_class.active).not_to include inactive end end - describe "states" do - it "initial state" do - expect(promo.state).to eq "pending" + describe 'states' do + it 'initial state' do + expect(promo.state).to eq 'pending' end - context "start! event" do + context 'start! event' do before { subject.start! } - it "turns to active" do - expect(subject.state).to eq "active" + it 'turns to active' do + expect(subject.state).to eq 'active' end end - context "stop!" do - before { subject.start!; subject.stop! } + context 'stop!' do + before do + subject.start! + subject.stop! + end - it "turns to pending" do - expect(subject.state).to eq "pending" + it 'turns to pending' do + expect(subject.state).to eq 'pending' end end end - describe "#promoter" do - it "calls promoters repository" do - PromotersRepository.expects(:find_by_type).with(promo.promoter_type) + describe '#promoter' do + it 'calls promoters repository' do + expect(PromotersRepository).to receive(:find_by_type).with(promo.promoter_type) subject.promoter end - it "returns according promoter" do + it 'returns according promoter' do expect(subject.promoter).to eq DiscountPromoter end end @@ -88,4 +93,3 @@ # updated_at :datetime # attrs :hstore default({}) # - diff --git a/spec/models/promotion_spec.rb b/spec/models/promotion_spec.rb index 38e4ee8a..89af0a65 100644 --- a/spec/models/promotion_spec.rb +++ b/spec/models/promotion_spec.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + require 'spec_helper' describe Promotion do - it { should belong_to :user } - it { should belong_to :promo } + it { is_expected.to belong_to :user } + it { is_expected.to belong_to :promo } - describe "uniqueness validation" do + describe 'uniqueness validation' do let(:promo1) { create(:promo) } let(:promo2) { create(:promo) } let(:user) { create(:user) } @@ -13,18 +15,18 @@ create(:promotion, user: user, promo: promo1) end - it "does not allow to create second promotion with same promo for user" do + it 'does not allow to create second promotion with same promo for user' do second_promotion = build(:promotion, user: user, promo: promo1) expect(second_promotion).not_to be_valid end - it "allows user to have multiple promotions with different promos" do + it 'allows user to have multiple promotions with different promos' do second_promotion = build(:promotion, user: user, promo: promo2) expect(second_promotion).to be_valid end end - describe "with_active_promos scope" do + describe 'with_active_promos scope' do subject { described_class } before do @@ -43,13 +45,13 @@ end end - describe "#apply method" do + describe '#apply method' do let(:promo) { create(:promo) } let(:promotion) { create(:promotion, promo: promo) } let(:amount) { 100 } it 'calls apply method on promo promoter' do - promo.promoter.expects(:apply).with(promo, amount) + expect(promo.promoter).to receive(:apply).with(promo, amount) promotion.apply(amount) end end @@ -65,4 +67,3 @@ # created_at :datetime # updated_at :datetime # - diff --git a/spec/models/proxy/connect_spec.rb b/spec/models/proxy/connect_spec.rb index b4bf1be9..d966ec93 100644 --- a/spec/models/proxy/connect_spec.rb +++ b/spec/models/proxy/connect_spec.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + require 'spec_helper' describe Proxy::Connect do subject { build :proxy_connect } - it { should belong_to :proxy } - it { should belong_to :user } + it { is_expected.to belong_to :proxy } + it { is_expected.to belong_to :user } it 'has initial state' do expect(subject.state).to eq 'active' diff --git a/spec/models/proxy/node_spec.rb b/spec/models/proxy/node_spec.rb index 72625d26..ea07682e 100644 --- a/spec/models/proxy/node_spec.rb +++ b/spec/models/proxy/node_spec.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + require 'spec_helper' describe Proxy::Node do subject { build(:proxy_node) } - it { should validate_presence_of :host } - it { should validate_presence_of :port } - it { should validate_presence_of :country } - it { should have_many :connects } + it { is_expected.to validate_presence_of :host } + it { is_expected.to validate_presence_of :port } + it { is_expected.to validate_presence_of :country } + it { is_expected.to have_many :connects } end diff --git a/spec/models/referrer/reward_spec.rb b/spec/models/referrer/reward_spec.rb index c20984b0..18650633 100644 --- a/spec/models/referrer/reward_spec.rb +++ b/spec/models/referrer/reward_spec.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + require 'spec_helper' describe Referrer::Reward do subject { build(:referrer_reward) } - it { should validate_presence_of :referrer_id } - it { should validate_presence_of :operation_id } - it { should validate_presence_of :amount } + it { is_expected.to validate_presence_of :referrer_id } + it { is_expected.to validate_presence_of :operation_id } + it { is_expected.to validate_presence_of :amount } end diff --git a/spec/models/server_spec.rb b/spec/models/server_spec.rb index 58a6e4ec..57fb6706 100644 --- a/spec/models/server_spec.rb +++ b/spec/models/server_spec.rb @@ -1,13 +1,15 @@ +# frozen_string_literal: true + require 'spec_helper' describe Server do subject { build(:server) } - it { should be_valid } - it { should have_many(:connects) } - it { should have_many(:disconnects) } - it { should have_many(:included_plans) } - it { should have_many(:plans) } + it { is_expected.to be_valid } + it { is_expected.to have_many(:connects) } + it { is_expected.to have_many(:disconnects) } + it { is_expected.to have_many(:included_plans) } + it { is_expected.to have_many(:plans) } it { validate_presence_of(:hostname) } it { validate_presence_of(:ip_address) } @@ -20,26 +22,25 @@ expect(subject).not_to be_valid end - context "after creation" do - it "generates auth key" do + context 'after creation' do + it 'generates auth key' do expect(subject.save).not_to be_nil end - it "auth key is random" do + it 'auth key is random' do expect(subject.save).not_to eq create(:server).auth_key end - it "is in pending state" do + it 'is in pending state' do expect(subject.pending?).to be true end end - describe ".to_s" do - it "returns hostname" do + describe '.to_s' do + it 'returns hostname' do expect(subject.to_s).to eq subject.hostname end end - end # == Schema Information @@ -55,4 +56,3 @@ # updated_at :datetime # config :string(255) # - diff --git a/spec/models/traffic_report_spec.rb b/spec/models/traffic_report_spec.rb index bd8211c0..73e4425a 100644 --- a/spec/models/traffic_report_spec.rb +++ b/spec/models/traffic_report_spec.rb @@ -1,44 +1,47 @@ +# frozen_string_literal: true + require 'spec_helper' describe TrafficReport do let(:params) { Hash[] } subject { described_class.new(params) } - describe "report building" do + describe 'report building' do + let(:report_ar_relation) { double('TrafficReport') } before do - report_ar_relation = mock() - report_ar_relation.expects(:where).returns([]) - TrafficReport.any_instance.expects(:build_report).returns(report_ar_relation) + allow_any_instance_of(TrafficReport).to receive(:build_report).and_return(report_ar_relation) + allow(report_ar_relation).to receive(:where).and_return([]) end - it "builds report on result call" do + it 'builds report on result call' do expect(subject.result).not_to be_nil end end - context "params on initialization passed" do - let(:params) { { - date_from: "01-10-2013", - date_to: "31-10-2013" - } } + context 'params on initialization passed' do + let(:params) do + { + date_from: '01-10-2013', + date_to: '31-10-2013' + } + end - it "date_from returns date from params" do - expect(subject.date_from).to eq "01-10-2013" + it 'date_from returns date from params' do + expect(subject.date_from).to eq '01-10-2013' end - it "date_to returns date from params" do - expect(subject.date_to).to eq "31-10-2013" + it 'date_to returns date from params' do + expect(subject.date_to).to eq '31-10-2013' end end - context "no params passed" do - it "date from equals beginning of month" do + context 'no params passed' do + it 'date from equals beginning of month' do expect(subject.date_from).to eq Date.current.beginning_of_month end - it "date to equals end of month" do + it 'date to equals end of month' do expect(subject.date_to).to eq Date.current.end_of_month end end - end diff --git a/spec/models/transaction_spec.rb b/spec/models/transaction_spec.rb index 32ffca4c..d9ea5539 100644 --- a/spec/models/transaction_spec.rb +++ b/spec/models/transaction_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Transaction do @@ -9,14 +11,14 @@ let(:withdrawal) { create(:withdrawal, created_at: 2.day.ago, user: user) } before do - Payment.any_instance.stubs(:try_to_withdraw_funds) + allow_any_instance_of(Payment).to receive(:try_to_withdraw_funds) payment.accept! withdrawal create(:withdrawal) create(:payment) end - it "returns user transactions list" do + it 'returns user transactions list' do expect(subject.user_transactions(user).size).to eq 2 end @@ -26,27 +28,33 @@ end end - describe ".all" do + describe '.all' do subject { described_class.all } let!(:transaction1) { create(:payment, created_at: 1.day.ago, state: 'accepted') } let!(:transaction2) { create(:payment, created_at: 3.day.ago, state: 'accepted') } let!(:transaction3) { create(:withdrawal, created_at: 4.day.ago) } let!(:transaction4) { create(:withdrawal, created_at: 2.day.ago) } - it "returns array" do + it 'returns array' do expect(subject.class).to eq Array end - it "returns collection of payments and withdrawals" do + it 'returns collection of payments and withdrawals' do expect(subject.count).to eq 4 end - it "orders transactions on created_at value" do - expect(subject.map{ |t| t.created_at.to_i }).to eq [transaction1.created_at.to_i, transaction4.created_at.to_i, transaction2.created_at.to_i, transaction3.created_at.to_i] + it 'orders transactions on created_at value' do + expect(subject.map { |t| t.created_at.to_i }) + .to eq [ + transaction1.created_at.to_i, + transaction4.created_at.to_i, + transaction2.created_at.to_i, + transaction3.created_at.to_i + ] end end - describe "numerates transactions" do + describe 'numerates transactions' do let!(:other_transaction1) { create(:withdrawal) } let!(:other_transaction2) { create(:withdrawal) } let!(:user_transaction1) { create(:withdrawal, user: user) } @@ -59,7 +67,7 @@ end end - describe "#amount" do + describe '#amount' do subject { Transaction.new(1, object) } context 'payment transaction' do diff --git a/spec/models/user_option_spec.rb b/spec/models/user_option_spec.rb index ebeee131..25f71257 100644 --- a/spec/models/user_option_spec.rb +++ b/spec/models/user_option_spec.rb @@ -1,12 +1,14 @@ -require 'spec_helper' +# frozen_string_literal: true + +require 'rails_helper' describe UserOption do subject { build(:user_option) } - it { should validate_presence_of(:user_id) } - it { should validate_presence_of(:option_id) } - it { should belong_to :user } - it { should belong_to :option } + it { is_expected.to validate_presence_of(:user_id) } + it { is_expected.to validate_presence_of(:option_id) } + it { is_expected.to belong_to :user } + it { is_expected.to belong_to :option } it 'is enabled' do expect(subject.enabled?).to be true diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 0951fcec..c40bf0c4 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,22 +1,24 @@ +# frozen_string_literal: true + require 'spec_helper' describe User do let(:user) { build(:user) } subject { user } - it { should be_valid } + it { is_expected.to be_valid } - it { should belong_to :referrer } - it { should have_many :referrals } + it { is_expected.to belong_to :referrer } + it { is_expected.to have_many :referrals } - it { should validate_presence_of(:plan_id) } - it { should validate_acceptance_of(:accept_agreement) } + it { is_expected.to validate_presence_of(:plan_id) } + it { is_expected.to validate_acceptance_of(:accept_agreement) } - it { should have_many(:connects) } - it { should have_many(:disconnects) } - it { should have_many(:promotions) } - it { should have_many(:options) } - it { should have_many(:user_options) } + it { is_expected.to have_many(:connects) } + it { is_expected.to have_many(:disconnects) } + it { is_expected.to have_many(:promotions) } + it { is_expected.to have_many(:options) } + it { is_expected.to have_many(:user_options) } it 'returns only active options' do user = create(:user) @@ -31,34 +33,34 @@ it_behaves_like 'loads created by last days', :user end -describe User, "custom validations" do +describe User, 'custom validations' do subject { build(:user, plan_id: plan.id) } - context "user with regular plan" do + context 'user with regular plan' do let(:plan) { create(:plan) } - it { should be_valid } + it { is_expected.to be_valid } end - context "user with special plan created" do + context 'user with special plan created' do let(:plan) { create(:plan, special: true) } - it { should_not be_valid } + it { is_expected.not_to be_valid } end - context "user changed plan from regular to special" do + context 'user changed plan from regular to special' do let(:plan) { create(:plan) } let(:new_plan) { create(:plan, special: true) } subject { create(:user, plan_id: plan.id) } - it "allowes user to change plan" do + it 'allowes user to change plan' do subject.plan_id = new_plan.id expect(subject).to be_valid end end end -describe User, "public methods" do +describe User, 'public methods' do subject { create(:user_with_balance) } describe '#test period' do @@ -89,56 +91,52 @@ end end - describe User, "balance increase" do + describe User, 'balance increase' do before { IncreaseBalanceMailWorker.jobs.clear } - it "allowes to increase balance" do + it 'allowes to increase balance' do subject.increase_balance(100) - subject.reload.balance.should be_eql 200 + expect(subject.reload.balance).to eq 200 end - it "adds email task to queue" do - expect { - subject.increase_balance(100) - }.to change(IncreaseBalanceMailWorker.jobs, :size).by(1) + it 'adds email task to queue' do + expect { subject.increase_balance(100) }.to change(IncreaseBalanceMailWorker.jobs, :size).by(1) end - it "notifies user by email" do - expect { + it 'notifies user by email' do + expect do subject.increase_balance(100) IncreaseBalanceMailWorker.drain - }.to change(ActionMailer::Base.deliveries, :count).by(1) + end.to change(ActionMailer::Base.deliveries, :count).by(1) end end - describe User, "balance decrease" do + describe User, 'balance decrease' do before { DecreaseBalanceMailWorker.jobs.clear } - it "allowes to decrease balance" do + it 'allowes to decrease balance' do subject.decrease_balance(100) - subject.reload.balance.should be_eql 0 + expect(subject.reload.balance).to eq 0 end - it "adds email task to queue" do - expect { - subject.decrease_balance(100) - }.to change(DecreaseBalanceMailWorker.jobs, :size).by(1) + it 'adds email task to queue' do + expect { subject.decrease_balance(100) }.to change(DecreaseBalanceMailWorker.jobs, :size).by(1) end - it "notifies user by email" do - expect { + it 'notifies user by email' do + expect do subject.decrease_balance(100) DecreaseBalanceMailWorker.drain - }.to change(ActionMailer::Base.deliveries, :count).by(1) + end.to change(ActionMailer::Base.deliveries, :count).by(1) end end - describe ".last_connect" do + describe '.last_connect' do before do create(:connect, user: subject) end - it "returns last connect" do + it 'returns last connect' do last_connect = create(:connect, user: subject) expect(subject.last_connect).to eq last_connect end @@ -160,83 +158,83 @@ end end - describe ".service_enabled?" do + describe '.service_enabled?' do let(:user) { create(:user_with_balance) } subject { user.service_enabled? } - context "user has paid in current billing interval" do + context 'user has paid in current billing interval' do before { create(:withdrawal, user: user) } - it "service is enabled" do - should be true + it 'service is enabled' do + is_expected.to be true end end context "user hasn't paid" do - it "service is disabled" do - should be false + it 'service is disabled' do + is_expected.to be false end end end - describe ".paid?" do + describe '.paid?' do let(:user) { create(:user_with_balance) } - context "user is paid" do + context 'user is paid' do let!(:withdrawal) { create(:withdrawal, user: subject) } - it "returns true" do + it 'returns true' do expect(subject.paid?).to be true end - context "user is prolongated" do + context 'user is prolongated' do before { create(:withdrawal_prolongation, withdrawal: withdrawal) } - it "returns true" do + it 'returns true' do expect(subject.paid?).to be true end end end - context "user payment expired, but prolongated" do + context 'user payment expired, but prolongated' do let!(:withdrawal) { create(:withdrawal, user: subject, created_at: 2.month.ago) } let!(:prolongation) { create(:withdrawal_prolongation, withdrawal: withdrawal, days_number: 100) } - it "returns true" do + it 'returns true' do expect(subject.paid?).to be true end end - context "user payment expired, prolongation expired too" do + context 'user payment expired, prolongation expired too' do let!(:withdrawal) { create(:withdrawal, user: subject, created_at: 2.month.ago) } let!(:prolongation) { create(:withdrawal_prolongation, withdrawal: withdrawal, days_number: 10) } - it "returns false" do + it 'returns false' do expect(subject.paid?).to be false end end - context "user is unpaid" do - it "returns false" do + context 'user is unpaid' do + it 'returns false' do expect(subject.paid?).not_to be true end end end end -describe User, "callbacks on create" do +describe User, 'callbacks on create' do subject { create(:user) } - describe "vpn credentials creation" do - it "generates login" do + describe 'vpn credentials creation' do + it 'generates login' do expect(subject.vpn_login).not_to be_nil end - it "generates password" do + it 'generates password' do expect(subject.vpn_password).not_to be_nil end - it "vpn password is 12 digits long" do + it 'vpn password is 12 digits long' do expect(subject.vpn_password.length).to eq 12 end end @@ -249,16 +247,15 @@ describe 'newsletter subscription' do it 'adds to newsletter' do - expect { + expect do create(:user) - }.to change(AddUserToNewsletterWorker.jobs, :size).by(1) + end.to change(AddUserToNewsletterWorker.jobs, :size).by(1) end end end -describe User, "scopes" do - - describe "by payments" do +describe User, 'scopes' do + describe 'by payments' do subject { described_class } let!(:paid_user) { create(:user) } let!(:earliar_paid_user) { create(:user) } @@ -270,24 +267,24 @@ old_payment.update(created_at: 2.month.ago) end - describe ".payers" do - it "returns this month payers" do + describe '.payers' do + it 'returns this month payers' do expect(subject.payers).to include paid_user end - it "returns old payers" do + it 'returns old payers' do expect(subject.payers).to include earliar_paid_user end end - describe ".this_month_payers" do - it "returns obly who paid at this month" do + describe '.this_month_payers' do + it 'returns obly who paid at this month' do expect(subject.payers).to include paid_user end end end - describe "#non_paid_clients" do + describe '#non_paid_clients' do before do t = Time.local(2014, 9, 15, 12, 0, 0) Timecop.travel(t) @@ -311,23 +308,23 @@ old_withdrawal2.update(created_at: 5.month.ago) end - it "returns 3 clients" do + it 'returns 3 clients' do expect(result.size).to eq 3 end - it "sorts by client registration" do + it 'sorts by client registration' do expect(result).to eq [new_client, non_paid_client, non_paid_client2] end - it "contains new client" do + it 'contains new client' do expect(result).to include new_client end - it "contains non paid client" do + it 'contains non paid client' do expect(result).to include non_paid_client end - it "contains non paid client2" do + it 'contains non paid client2' do expect(result).to include non_paid_client2 end end @@ -347,19 +344,19 @@ old_withdrawal.update(created_at: 2.month.ago) end - it "returns 1 client" do + it 'returns 1 client' do expect(result.size).to eq 1 end - it "contains new client" do + it 'contains new client' do expect(result).to include new_client end - it "does not contain long ago client" do + it 'does not contain long ago client' do expect(result).not_to include paid_long_ago_client end - it "does not contain paid client" do + it 'does not contain paid client' do expect(result).not_to include paid_client end end @@ -390,30 +387,30 @@ end end -describe User, "states" do +describe User, 'states' do subject { build(:user) } - context "new" do - it "has active status" do + context 'new' do + it 'has active status' do expect(subject.active?).to be true end end - context ".disable! called" do - it "changes state to disabled" do - expect { + context '.disable! called' do + it 'changes state to disabled' do + expect do subject.disable! - }.to change(subject, :state).to("disabled") + end.to change(subject, :state).to('disabled') end end - context ".activate! called" do + context '.activate! called' do before { subject.disable! } - it "changes state to active" do - expect { + it 'changes state to active' do + expect do subject.activate! - }.to change(subject, :state).to("active") + end.to change(subject, :state).to('active') end end end @@ -448,4 +445,3 @@ # state :string(255) # can_not_withdraw_counter :integer default(0) # - diff --git a/spec/models/withdrawal_prolongation_spec.rb b/spec/models/withdrawal_prolongation_spec.rb index db19224d..a713be00 100644 --- a/spec/models/withdrawal_prolongation_spec.rb +++ b/spec/models/withdrawal_prolongation_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + require 'spec_helper' describe WithdrawalProlongation do - it { should belong_to :withdrawal } + it { is_expected.to belong_to :withdrawal } - it { should validate_presence_of :withdrawal_id } - it { should validate_presence_of :days_number } + it { is_expected.to validate_presence_of :withdrawal_id } + it { is_expected.to validate_presence_of :days_number } end diff --git a/spec/models/withdrawal_spec.rb b/spec/models/withdrawal_spec.rb index d862e5a1..af985b93 100644 --- a/spec/models/withdrawal_spec.rb +++ b/spec/models/withdrawal_spec.rb @@ -1,54 +1,54 @@ +# frozen_string_literal: true + require 'spec_helper' describe Withdrawal do subject { build(:withdrawal) } - it { should be_valid } - it { should validate_presence_of(:plan_id) } - it { should validate_presence_of(:user_id) } - it { should validate_presence_of(:amount) } + it { is_expected.to be_valid } + it { is_expected.to validate_presence_of(:plan_id) } + it { is_expected.to validate_presence_of(:user_id) } + it { is_expected.to validate_presence_of(:amount) } end -describe Withdrawal, "prolongation" do - it { should have_many :withdrawal_prolongations } +describe Withdrawal, 'prolongation' do + it { is_expected.to have_many :withdrawal_prolongations } - describe "#prolongation_days" do + describe '#prolongation_days' do subject { create(:withdrawal) } - context "prolongated" do + context 'prolongated' do before { create_list(:withdrawal_prolongation, 2, days_number: 1, withdrawal: subject) } - it "returns sum of prolongation days" do + it 'returns sum of prolongation days' do expect(subject.prolongation_days).to eq 2 end end - context "no prolongation" do - it "returns zero" do + context 'no prolongation' do + it 'returns zero' do expect(subject.prolongation_days).to eq 0 end end end end -describe Withdrawal, "user balance decreases" do +describe Withdrawal, 'user balance decreases' do let(:user) { create(:user_with_balance) } let(:plan) { create(:plan) } let(:amount) { 1 } - it "decreases users balance on create" do + it 'decreases users balance on create' do balance_before = user.balance create(:withdrawal, user: user, plan: plan, amount: 1) - expect(user.reload.balance).to eq (balance_before - amount) + expect(user.reload.balance).to eq(balance_before - amount) end - context "user has not enough funds" do + context 'user has not enough funds' do let(:user) { create(:user) } - it "does not decrease balance" do - expect { - create(:withdrawal, user: user, plan: plan) - }.to raise_error ActiveRecord::RecordInvalid + it 'does not decrease balance' do + expect { create(:withdrawal, user: user, plan: plan) }.to raise_error ActiveRecord::RecordInvalid end end end @@ -64,4 +64,3 @@ # created_at :datetime # updated_at :datetime # - diff --git a/spec/operations/ops/admin/user/create_spec.rb b/spec/operations/ops/admin/user/create_spec.rb index 9e3c01ad..4d701011 100644 --- a/spec/operations/ops/admin/user/create_spec.rb +++ b/spec/operations/ops/admin/user/create_spec.rb @@ -20,9 +20,45 @@ expect(subject.call).to eq(success: true, user: User.last) end + it 'will be created user' do + expect { subject.call }.to change(User, :count).by(1) + end + it 'returns success result' do expect(CreateUserMailWorker).to receive(:perform_async).with(any_args) subject.call end + + it 'adds email task to queue' do + expect { subject.call }.to change(CreateUserMailWorker.jobs, :size).by(1) + end + end + + context 'invalid params' do + let(:params) do + { + email: 'user@gmail.com', + password: '123456', + password_confirmation: '12345678', + plan_id: plan.id + } + end + + it 'returns failed result' do + expect(subject.call[:success]).to eq false + end + + it 'will be created user' do + expect { subject.call }.to change(User, :count).by(0) + end + + it 'returns success result' do + expect(CreateUserMailWorker).not_to receive(:perform_async).with(any_args) + subject.call + end + + it 'adds email task to queue' do + expect { subject.call }.not_to(change(CreateUserMailWorker.jobs, :size)) + end end end diff --git a/spec/services/option/activator_spec.rb b/spec/services/option/activator_spec.rb index ad0c98da..4621da25 100644 --- a/spec/services/option/activator_spec.rb +++ b/spec/services/option/activator_spec.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + require 'spec_helper' describe Option::Activator do subject { described_class } let!(:option) { create(:active_option) } - before { subject.any_instance.stubs(:activation_price).returns(1) } + before { allow_any_instance_of(subject).to receive(:activation_price).and_return(1) } describe '.run' do let!(:user) { create(:user_with_balance) } @@ -13,9 +15,9 @@ context 'user has enough funds' do it 'activates option for user' do - expect { + expect do subject.run(user, option.code) - }.to change(user.options, :count).by(1) + end.to change(user.options, :count).by(1) end it 'returns true' do @@ -27,9 +29,9 @@ let(:user) { create(:user, balance: 0) } it 'does not activate option for user' do - expect { + expect do subject.run(user, option.code) - }.to change(user.options.reload, :count).by(0) + end.to change(user.options.reload, :count).by(0) end it 'returns false' do @@ -40,9 +42,9 @@ context 'option is not permitted for users plan' do it 'does not activate option' do - expect { + expect do subject.run(user, option.code) - }.to change(user.options, :count).by(0) + end.to change(user.options, :count).by(0) end it 'returns false' do diff --git a/spec/services/proxy/fetchers/base_spec.rb b/spec/services/proxy/fetchers/base_spec.rb index 87cd3bf8..3905d19e 100644 --- a/spec/services/proxy/fetchers/base_spec.rb +++ b/spec/services/proxy/fetchers/base_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Proxy::Fetchers::Base do @@ -6,16 +8,14 @@ describe '.fetch' do context 'child class' do it 'calls #fetch_proxy_list' do - subject.any_instance.expects(:fetch_proxy_list) + allow_any_instance_of(subject).to receive(:fetch_proxy_list) subject.fetch end end context 'parent class' do it 'raises error' do - expect { - subject.fetch - }.to raise_error NotImplementedException + expect { subject.fetch }.to raise_error NotImplementedException end end end diff --git a/spec/services/proxy/updater_spec.rb b/spec/services/proxy/updater_spec.rb index 0f6c8c2d..e9b24ade 100644 --- a/spec/services/proxy/updater_spec.rb +++ b/spec/services/proxy/updater_spec.rb @@ -1,13 +1,15 @@ +# frozen_string_literal: true + require 'spec_helper' describe Proxy::Updater do describe '.update' do - let(:fetcher_class) { mock() } + let(:fetcher_class) { double('fetcher_class') } let(:proxies) { [] } subject { described_class } before do - fetcher_class.expects(:fetch).returns(proxies) + expect(fetcher_class).to receive(:fetch).and_return(proxies) end it 'gets proxies from fetcher' do @@ -15,7 +17,7 @@ end it 'persists proxies collection' do - Proxy::Repository.expects(:persist).with(proxies) + expect(Proxy::Repository).to receive(:persist).with(proxies) subject.update(fetcher_class) end end diff --git a/spec/services/referrer/reward_calculator_spec.rb b/spec/services/referrer/reward_calculator_spec.rb index bec1a21b..258b6874 100644 --- a/spec/services/referrer/reward_calculator_spec.rb +++ b/spec/services/referrer/reward_calculator_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Referrer::RewardCalculator do @@ -6,7 +8,7 @@ describe '#amount' do before do - described_class.any_instance.expects(:percent).returns(10) + allow_any_instance_of(described_class).to receive(:percent).and_return(10) end it 'returns 10% of payment' do diff --git a/spec/services/withdrawer_spec.rb b/spec/services/withdrawer_spec.rb index ee2dd032..19c97913 100644 --- a/spec/services/withdrawer_spec.rb +++ b/spec/services/withdrawer_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Withdrawer do @@ -13,34 +15,34 @@ old_withdrawal.update(created_at: 2.month.ago) end - describe ".mass_withdrawal" do + describe '.mass_withdrawal' do let!(:non_paid_clients_number) { User.non_paid_users.size } - it "creates withdrawal for each non paid client" do - expect { + it 'creates withdrawal for each non paid client' do + expect do subject.mass_withdrawal - }.to change(Withdrawal, :count).by(non_paid_clients_number) + end.to change(Withdrawal, :count).by(non_paid_clients_number) end end - describe ".single_withdraw" do - context "user is unpaid" do - context "user has enough funds" do + describe '.single_withdraw' do + context 'user is unpaid' do + context 'user has enough funds' do let!(:user) { create :user_with_balance } - it "creates withdraw" do - expect { + it 'creates withdraw' do + expect do subject.single_withdraw(user) - }.to change(Withdrawal, :count).by(1) + end.to change(Withdrawal, :count).by(1) end - it "gets withdrawal sum from calculator" do - WithdrawalAmountCalculator.any_instance.expects(:amount_to_withdraw).returns(10) + it 'gets withdrawal sum from calculator' do + allow_any_instance_of(WithdrawalAmountCalculator).to receive(:amount_to_withdraw).and_return(10) subject.single_withdraw(user) end it 'tries to create withdrawal' do - Withdrawer.any_instance.expects(:add_funds_to_referrer) + allow_any_instance_of(WithdrawalAmountCalculator).to receive(:add_funds_to_referrer) subject.single_withdraw(user) end @@ -48,21 +50,21 @@ before { user.update(can_not_withdraw_counter: 1) } it 'resets the counter' do - expect { + expect do subject.single_withdraw(user) - }.to change(user.reload, :can_not_withdraw_counter).to(0) + end.to change(user.reload, :can_not_withdraw_counter).to(0) end end end - context "user has not funds" do + context 'user has not funds' do context 'first attempt to withdraw funds' do let(:user) { create :user } - it "notifies user by email" do - expect { + it 'notifies user by email' do + expect do subject.single_withdraw(user) - }.to change(CanNotWithdrawNotificationWorker.jobs, :size).by(1) + end.to change(CanNotWithdrawNotificationWorker.jobs, :size).by(1) end end @@ -75,30 +77,29 @@ end it 'does not send mail' do - expect { + expect do subject.single_withdraw(user) - }.not_to change(CanNotWithdrawNotificationWorker.jobs, :size) + end.not_to change(CanNotWithdrawNotificationWorker.jobs, :size) end end end end - context "user is paid" do + context 'user is paid' do let(:user) { create :user_with_balance } before { create(:withdrawal, user: user, plan: user.plan) } - it "does not create withdrawal" do - expect { + it 'does not create withdrawal' do + expect do subject.single_withdraw(user) - }.not_to change(Withdrawal, :count) + end.not_to change(Withdrawal, :count) end - it "does not notify user" do - expect { + it 'does not notify user' do + expect do subject.single_withdraw(user) - }.not_to change(CanNotWithdrawNotificationWorker.jobs, :size) + end.not_to change(CanNotWithdrawNotificationWorker.jobs, :size) end end end - end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e9162ff6..265ed777 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -10,7 +10,6 @@ require 'capybara/rails' require 'capybara/rspec' require 'capybara/email/rspec' -require 'shoulda-matchers' Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } Dir[Rails.root.join('app/helpers/**/*.rb')].each { |f| require f } Dir[Rails.root.join('spec/shared_examples/*.rb')].each { |f| require f } @@ -22,10 +21,15 @@ ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration) RSpec.configure do |config| - config.expect_with :rspec do |c| - c.syntax = %i[should expect] + Shoulda::Matchers.configure do |shoulda_config| + shoulda_config.integrate do |with| + with.test_framework :rspec + + with.library :active_record + with.library :active_model + with.library :action_controller + end end - config.mock_with :mocha config.fixture_path = "#{::Rails.root}/spec/fixtures" config.use_transactional_fixtures = false From c41cabe1609039cfcfca58a9b1d05902f8b5c76a Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Thu, 17 Jan 2019 09:38:14 +0300 Subject: [PATCH 12/16] Add tests --- config/environments/test.rb | 2 + .../admin/users_controller_spec.rb | 58 +++++++++++++++++++ spec/operations/ops/admin/user/base_spec.rb | 20 +++++++ spec/spec_helper.rb | 4 ++ spec/workers/create_user_mail_worker_spec.rb | 27 +++++++++ 5 files changed, 111 insertions(+) create mode 100644 spec/operations/ops/admin/user/base_spec.rb create mode 100644 spec/workers/create_user_mail_worker_spec.rb diff --git a/config/environments/test.rb b/config/environments/test.rb index 71ce0025..e7ddde30 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -3,6 +3,8 @@ Smartvpn::Application.configure do # Settings specified here will take precedence over those in config/application.rb. + config.active_job.queue_adapter = :sidekiq + # The test environment is used exclusively to run your application's # test suite. You never need to work with it otherwise. Remember that # your test database is "scratch space" for the test suite and is wiped diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index a3188112..c6a267fa 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -44,6 +44,64 @@ it { is_expected.to render_template :edit } end + describe 'GET #new' do + before { get :new } + + it { is_expected.to be_success } + it { is_expected.to render_template :new } + end + + describe 'POST #create' do + let!(:user) { create(:user) } + let!(:plan) { create(:plan) } + let!(:operation) { double('Ops::Admin::User::Create') } + before { allow(Ops::Admin::User::Create).to receive(:new).with(params: params).and_return(operation) } + + context 'params correct' do + let(:params) do + { + email: 'user@gmail.com', + password: '123456', + password_confirmation: '123456', + plan_id: plan.id.to_s + }.as_json + end + + it 'run operation' do + expect(operation).to receive(:call).and_return(success: true, user: user) + post :create, user: params + end + + it 'redirects to users path' do + allow(operation).to receive(:call).and_return(success: true, user: user) + post :create, user: params + expect(subject).to redirect_to admin_users_path + end + end + + context 'params invalid' do + let(:params) do + { + email: 'user@gmail.com', + password: '123456', + password_confirmation: '12345678', + plan_id: plan.id.to_s + }.as_json + end + + it 'run operation' do + expect(operation).to receive(:call).and_return(success: false, user: user) + post :create, user: params + end + + it 'redirects to users path' do + allow(operation).to receive(:call).and_return(success: false, user: user) + post :create, user: params + expect(subject).to render_template :new + end + end + end + describe 'PUT #update' do let(:user) { create(:user) } diff --git a/spec/operations/ops/admin/user/base_spec.rb b/spec/operations/ops/admin/user/base_spec.rb new file mode 100644 index 00000000..f5863d5f --- /dev/null +++ b/spec/operations/ops/admin/user/base_spec.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe Ops::Admin::User::Base do + subject { described_class.new(params: params) } + let(:plan) { create(:plan) } + let(:params) do + { + email: 'user@gmail.com', + password: '123456', + password_confirmation: '123456', + plan_id: plan.id + } + end + + it 'returns raise' do + expect { subject.call }.to raise_error NotImplementedError + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 265ed777..b751abb6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -10,6 +10,10 @@ require 'capybara/rails' require 'capybara/rspec' require 'capybara/email/rspec' + +require 'sidekiq/testing' +Sidekiq::Testing.fake! + Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } Dir[Rails.root.join('app/helpers/**/*.rb')].each { |f| require f } Dir[Rails.root.join('spec/shared_examples/*.rb')].each { |f| require f } diff --git a/spec/workers/create_user_mail_worker_spec.rb b/spec/workers/create_user_mail_worker_spec.rb new file mode 100644 index 00000000..aa5b3f56 --- /dev/null +++ b/spec/workers/create_user_mail_worker_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe CreateUserMailWorker do + subject { described_class.new } + + context '#perform' do + let(:user) { create(:user) } + let(:server) { create(:server) } + let!(:plan) { create(:plan, users: [user], servers: [server]) } + let(:params) { { user_id: user.id, crypted_password: '123456' }.as_json } + let(:mailer) { double } + + it 'notifies user by email' do + expect { subject.perform(params) }.to change(ActionMailer::Base.deliveries, :count).by(1) + end + + it 'will be run mail to user' do + expect(UserConnectionConfigMailer) + .to receive(:notify) + .with(user: user, crypted_password: params['crypted_password']).and_return(mailer) + allow(mailer).to receive(:deliver_now) + subject.perform(params) + end + end +end From 129530c2c17208d0982f3cd60f960f062110474d Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Thu, 17 Jan 2019 19:18:40 +0300 Subject: [PATCH 13/16] Refactorin after review --- Gemfile | 6 ++---- app/controllers/admin/servers_controller.rb | 6 +++--- app/models/server_config.rb | 1 + app/operations/ops/admin/user/base.rb | 2 +- app/operations/ops/admin/user/create.rb | 4 ++-- app/services/server_config_builder.rb | 18 ++++-------------- config/locales/admin/en.yml | 5 +++++ config/locales/admin/ru.yml | 5 +++++ spec/services/server_config_builder_spec.rb | 12 +++--------- 9 files changed, 26 insertions(+), 33 deletions(-) diff --git a/Gemfile b/Gemfile index ad85fd35..579c36dc 100644 --- a/Gemfile +++ b/Gemfile @@ -40,9 +40,6 @@ gem 'russian_central_bank' gem 'show_for', github: 'plataformatec/show_for' gem 'whenever', '0.9.0', require: false -gem 'factory_girl_rails', '~> 4.0' -gem 'faker' - gem 'sidekiq' gem 'sinatra', require: false @@ -82,7 +79,8 @@ group :test, :development do gem 'capybara' gem 'database_cleaner', '1.0.0.RC1' gem 'dotenv-rails' - # gem 'mocha', require: false + gem 'factory_girl_rails', '~> 4.0' + gem 'faker' gem 'rspec-its' gem 'rspec-rails', '~> 3.8' gem 'shoulda-matchers', '4.0.0.rc1' diff --git a/app/controllers/admin/servers_controller.rb b/app/controllers/admin/servers_controller.rb index e1649be6..dff4b513 100644 --- a/app/controllers/admin/servers_controller.rb +++ b/app/controllers/admin/servers_controller.rb @@ -17,7 +17,7 @@ def new def create @server = Server.new(resource_params) if @server.save - redirect_to admin_servers_path, notice: 'Сервер успешно добавлен' + redirect_to admin_servers_path, notice: t('admin.servers.notices.created') else render :new end @@ -27,7 +27,7 @@ def edit; end def update if @server.update(resource_params) - redirect_to admin_servers_path, notice: 'Сервер успешно обновлен' + redirect_to admin_servers_path, notice: t('admin.servers.notices.updated') else render :edit end @@ -35,7 +35,7 @@ def update def destroy @server.delete - redirect_to admin_servers_path, notice: 'Сервер удален' + redirect_to admin_servers_path, notice: t('admin.servers.notices.destroyed') end def generate_config diff --git a/app/models/server_config.rb b/app/models/server_config.rb index b215e5c8..91174b54 100644 --- a/app/models/server_config.rb +++ b/app/models/server_config.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true # TODO: delete +# This model for parse server config, storage array strings class ServerConfig attr_accessor :config_lines diff --git a/app/operations/ops/admin/user/base.rb b/app/operations/ops/admin/user/base.rb index 8ef58b69..05980863 100644 --- a/app/operations/ops/admin/user/base.rb +++ b/app/operations/ops/admin/user/base.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true +# This base class for user operations module Ops module Admin module User - # This base class for user operations class Base attr_reader :params diff --git a/app/operations/ops/admin/user/create.rb b/app/operations/ops/admin/user/create.rb index 23785d1e..0c9c9206 100644 --- a/app/operations/ops/admin/user/create.rb +++ b/app/operations/ops/admin/user/create.rb @@ -7,7 +7,7 @@ module User class Create < Base def call user.skip_confirmation_notification! - return error_create_user unless user.save + return error_result unless user.save build_created_user! success_result @@ -24,7 +24,7 @@ def user @user ||= ::User.new(params) end - def error_create_user + def error_result { success: false, user: user } end diff --git a/app/services/server_config_builder.rb b/app/services/server_config_builder.rb index 366778a3..817896a4 100644 --- a/app/services/server_config_builder.rb +++ b/app/services/server_config_builder.rb @@ -8,12 +8,6 @@ def initialize(server:) @server = server end - def generate_config - tempfile.puts erb_render_sample_config - tempfile.rewind - tempfile - end - def to_text erb_render_sample_config end @@ -24,15 +18,11 @@ def erb_render_sample_config ERB.new(sample_config).result(binding) end - def sample_config_path - Settings.servers.sample_config_path - end - - def tempfile - @tempfile ||= Tempfile.new(%w[server-config- .ovpn]) - end - def sample_config @sample_config ||= File.read(sample_config_path) end + + def sample_config_path + Settings.servers.sample_config_path + end end diff --git a/config/locales/admin/en.yml b/config/locales/admin/en.yml index defbc94c..4365e38e 100644 --- a/config/locales/admin/en.yml +++ b/config/locales/admin/en.yml @@ -25,6 +25,11 @@ en: buttons: filter: 'Filter' apply: 'Apply' + servers: + notices: + created: 'Server successfully added' + updated: 'Server successfully updated' + destroyed: 'Server deleted' users: title: 'Users' all: 'All' diff --git a/config/locales/admin/ru.yml b/config/locales/admin/ru.yml index d7c196d0..e68f0fd5 100644 --- a/config/locales/admin/ru.yml +++ b/config/locales/admin/ru.yml @@ -25,6 +25,11 @@ ru: buttons: filter: 'Фильтер' apply: 'Применить' + servers: + notices: + created: 'Сервер успешно добавлен' + updated: 'Сервер успешно обновлен' + destroyed: 'Сервер удален' users: title: 'Пользователи' all: 'Все' diff --git a/spec/services/server_config_builder_spec.rb b/spec/services/server_config_builder_spec.rb index 67ff97bb..4254d124 100644 --- a/spec/services/server_config_builder_spec.rb +++ b/spec/services/server_config_builder_spec.rb @@ -6,9 +6,9 @@ let(:server) { create(:server) } subject { described_class.new(server: server) } - describe '#generate_config' do - it 'returns ServerConfig instance' do - expect(subject.generate_config.class).to eq Tempfile + describe '#to_text' do + it 'returns ServerConfig text' do + expect(subject.to_text.class).to eq String end describe 'protocol' do @@ -41,10 +41,4 @@ end end end - - describe '#to_text' do - it 'returns string' do - expect(subject.to_text.class).to eq String - end - end end From 1c309b162802f3f1ae0f054476e1e85d30886a42 Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Sat, 19 Jan 2019 09:38:22 +0300 Subject: [PATCH 14/16] Add congig rollbar through ENV --- .env.sample | 3 +++ Gemfile | 1 - config/initializers/rollbar.rb | 14 +++++++------- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.env.sample b/.env.sample index 13c39b24..c80f53de 100644 --- a/.env.sample +++ b/.env.sample @@ -1,4 +1,7 @@ SECRET_TOKEN= + EMAIL_USER= EMAIL_PASS= EMAIL_FROM= + +ROLLBAR_ACCESS_TOKEN= diff --git a/Gemfile b/Gemfile index 579c36dc..605a2d80 100644 --- a/Gemfile +++ b/Gemfile @@ -43,7 +43,6 @@ gem 'whenever', '0.9.0', require: false gem 'sidekiq' gem 'sinatra', require: false -# TODO: make it optional via ENV flag gem 'rollbar' # TODO: make it optional via ENV flag gem 'newrelic_rpm' diff --git a/config/initializers/rollbar.rb b/config/initializers/rollbar.rb index d0d65394..9685838e 100644 --- a/config/initializers/rollbar.rb +++ b/config/initializers/rollbar.rb @@ -1,13 +1,14 @@ +# frozen_string_literal: true + require 'rollbar/rails' + Rollbar.configure do |config| - config.access_token = '' + config.access_token = ENV['ROLLBAR_ACCESS_TOKEN'] - # Without configuration, Rollbar is enabled by in all environments. + # Without configuration, Rollbar is enabled by in all environments. # To disable in specific environments, set config.enabled=false. # Here we'll disable in 'test': - if Rails.env.test? || Rails.env.development? - config.enabled = false - end + config.enabled = false if Rails.env.test? || Rails.env.development? # By default, Rollbar will try to call the `current_user` controller method # to fetch the logged-in user object, and then call that object's `id`, @@ -27,10 +28,9 @@ # via the rollbar interface. # Valid levels: 'critical', 'error', 'warning', 'info', 'debug', 'ignore' # 'ignore' will cause the exception to not be reported at all. - config.exception_level_filters.merge!('AbstractController::ActionNotFound' => 'ignore') + config.exception_level_filters['AbstractController::ActionNotFound'] = 'ignore' config.exception_level_filters.merge!('ActionController::RoutingError' => 'ignore') - # You can also specify a callable, which will be called with the exception instance. # config.exception_level_filters.merge!('MyCriticalException' => lambda { |e| 'critical' }) From 63d9d8c3cd1bbcec4d81fd59919bf8193c55acc0 Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Sat, 19 Jan 2019 09:45:48 +0300 Subject: [PATCH 15/16] Add enviroment variable with license key newrelic to config file --- .env.sample | 2 ++ config/newrelic.yml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.env.sample b/.env.sample index c80f53de..f5e0861c 100644 --- a/.env.sample +++ b/.env.sample @@ -5,3 +5,5 @@ EMAIL_PASS= EMAIL_FROM= ROLLBAR_ACCESS_TOKEN= + +NEWRELIC_LICENSE_KEY= diff --git a/config/newrelic.yml b/config/newrelic.yml index 0aaedc33..331b0753 100644 --- a/config/newrelic.yml +++ b/config/newrelic.yml @@ -15,7 +15,7 @@ common: &default_settings # You must specify the license key associated with your New Relic # account. This key binds your Agent's data to your account in the # New Relic service. - license_key: '' + license_key: <%= ENV['NEWRELIC_LICENSE_KEY'] %> # Agent Enabled (Ruby/Rails Only) # Use this setting to force the agent to run or not run. From 1fcb1e599fcd53ecd4198bf7416128b3dff9fbbb Mon Sep 17 00:00:00 2001 From: Aleksandr Dyuzhikov Date: Sat, 19 Jan 2019 09:58:45 +0300 Subject: [PATCH 16/16] Add config settings robokassa and another through enviroment variables --- .env.sample | 11 +++++++++++ .env.test | 10 ++++++++++ config/settings.yml | 13 ++++++++++++- config/settings/development.yml | 10 ---------- config/settings/production.yml | 11 ----------- config/settings/test.yml | 10 ---------- 6 files changed, 33 insertions(+), 32 deletions(-) diff --git a/.env.sample b/.env.sample index f5e0861c..7d4c7703 100644 --- a/.env.sample +++ b/.env.sample @@ -7,3 +7,14 @@ EMAIL_FROM= ROLLBAR_ACCESS_TOKEN= NEWRELIC_LICENSE_KEY= + +ROBOKASSA_LOGIN= +ROBOKASSA_SECRET1= +ROBOKASSA_SECRET2= + +WEBMONEY_SECRET= +WEBMONEY_WALLET_WMZ= +WEBMONEY_WALLET_WMR= + +MAILCHIMP_API_KEY= +MAILCHIMP_ALL_CLIENTS_LIST_ID= diff --git a/.env.test b/.env.test index 46cbda74..c45c7998 100644 --- a/.env.test +++ b/.env.test @@ -1,3 +1,13 @@ SECRET_TOKEN='0e89a81d2e7be3cce9c45d154df16269b5878061c9967c15329adf1490941e613f0b24dd4955b9e0b0e1356180ae8314b879f20150abad78e1ff4bc039a06d75' DEFAULT_HOST='smartvpn.dev' EMAIL_FROM='admin@smartvpn.biz' + +ROBOKASSA_LOGIN='login' +ROBOKASSA_SECRET1='password' +ROBOKASSA_SECRET2='password2' + +WEBMONEY_SECRET='secret value' +WEBMONEY_WALLET_WMZ='Z1234567890' + +MAILCHIMP_API_KEY='mailchimp-key' +MAILCHIMP_ALL_CLIENTS_LIST_ID='test' diff --git a/config/settings.yml b/config/settings.yml index e981d099..1fd2ab40 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -5,4 +5,15 @@ servers: sample_config_path: 'config/sample.server.ovpn.erb' mailchimp: - all_clients_list_id: '' + api_key: <%= ENV['MAILCHIMP_API_KEY'] %> + all_clients_list_id: <%= ENV['MAILCHIMP_ALL_CLIENTS_LIST_ID'] %> + +robokassa: + login: <%= ENV['ROBOKASSA_LOGIN'] %> + secret1: <%= ENV['ROBOKASSA_SECRET1'] %> + secret2: <%= ENV['ROBOKASSA_SECRET2'] %> +webmoney: + secret: <%= ENV['WEBMONEY_SECRET'] %> + wallet: + wmz: <%= ENV['WEBMONEY_WALLET_WMZ'] %> + wmr: <%= ENV['WEBMONEY_WALLET_WMR'] %> diff --git a/config/settings/development.yml b/config/settings/development.yml index 7c2fdbe5..e69de29b 100644 --- a/config/settings/development.yml +++ b/config/settings/development.yml @@ -1,10 +0,0 @@ -robokassa: - login: "" - secret1: "" - secret2: "" -webmoney: - secret: "" - wallet: - wmz: "" -mailchimp: - api_key: '' diff --git a/config/settings/production.yml b/config/settings/production.yml index 638e805a..e69de29b 100644 --- a/config/settings/production.yml +++ b/config/settings/production.yml @@ -1,11 +0,0 @@ -robokassa: - login: "" - secret1: "" - secret2: "" -webmoney: - secret: "" - wallet: - wmz: "" - wmr: "" -mailchimp: - api_key: '' diff --git a/config/settings/test.yml b/config/settings/test.yml index 86dd8b78..e69de29b 100644 --- a/config/settings/test.yml +++ b/config/settings/test.yml @@ -1,10 +0,0 @@ -robokassa: - login: "login" - secret1: "password" - secret2: "password2" -webmoney: - secret: "secret value" - wallet: - wmz: "Z1234567890" -mailchimp: - api_key: 'mailchimp-key'