diff --git a/Gemfile b/Gemfile index 13d8aeb47..976c4e2cd 100644 --- a/Gemfile +++ b/Gemfile @@ -53,7 +53,7 @@ gem 'kaminari', '~> 0.16.1' gem 'ransack', '~> 1.3.0' # for rights -gem 'cancan', '~> 1.6.10' +gem 'cancancan', '~> 1.9.2' # for login gem 'devise', '~> 3.3.0' @@ -96,7 +96,7 @@ group :development, :test do gem 'epp', '~> 1.4.0' # EPP XMLs - gem 'epp-xml', '~> 0.8.1' + gem 'epp-xml', '~> 0.10.1' # Replacement for fixtures gem 'fabrication', '~> 2.11.3' @@ -135,6 +135,9 @@ group :development, :test do # faster dev load time gem 'unicorn' + + # for opening browser automatically + gem 'launchy', '~> 2.4.3' end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index e6b6cfc1d..53f75e730 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -29,6 +29,7 @@ GEM minitest (~> 5.1) thread_safe (~> 0.1) tzinfo (~> 1.1) + addressable (2.3.6) arel (5.0.1.20140414130214) ast (2.0.0) astrolabe (1.3.0) @@ -64,7 +65,7 @@ GEM bundler-audit (0.3.1) bundler (~> 1.2) thor (~> 0.18) - cancan (1.6.10) + cancancan (1.9.2) capybara (2.4.3) mime-types (>= 1.16) nokogiri (>= 1.3.3) @@ -106,7 +107,7 @@ GEM epp (1.4.0) hpricot libxml-ruby - epp-xml (0.8.1) + epp-xml (0.10.1) activesupport (~> 4.1) builder (~> 3.2) equalizer (0.0.9) @@ -161,6 +162,8 @@ GEM actionpack (>= 3.0.0) activesupport (>= 3.0.0) kgio (2.9.2) + launchy (2.4.3) + addressable (~> 2.3) libv8 (3.16.14.7) libxml-ruby (2.7.0) listen (2.7.11) @@ -177,7 +180,7 @@ GEM open4 (~> 1.3.4) rake mini_portile (0.6.0) - minitest (5.4.3) + minitest (5.5.0) multi_json (1.10.1) nokogiri (1.6.2.1) mini_portile (= 0.6.0) @@ -376,7 +379,7 @@ DEPENDENCIES brakeman (~> 2.6.2) bullet (~> 4.14.0) bundler-audit - cancan (~> 1.6.10) + cancancan (~> 1.9.2) capybara (~> 2.4.1) coffee-rails (~> 4.0.0) daemons @@ -384,7 +387,7 @@ DEPENDENCIES delayed_job_active_record (~> 4.0.2) devise (~> 3.3.0) epp (~> 1.4.0) - epp-xml (~> 0.8.1) + epp-xml (~> 0.10.1) fabrication (~> 2.11.3) faker (~> 1.3.0) guard (~> 2.6.1) @@ -395,6 +398,7 @@ DEPENDENCIES jbuilder (~> 2.0) jquery-rails kaminari (~> 0.16.1) + launchy (~> 2.4.3) mina (~> 0.3.1) nokogiri (~> 1.6.2.1) nprogress-rails (~> 0.1.3.1) diff --git a/app/controllers/admin/contacts_controller.rb b/app/controllers/admin/contacts_controller.rb index 8dd1f4ec9..5135f2c7f 100644 --- a/app/controllers/admin/contacts_controller.rb +++ b/app/controllers/admin/contacts_controller.rb @@ -1,4 +1,5 @@ class Admin::ContactsController < AdminController + load_and_authorize_resource before_action :set_contact, only: [:show] def index diff --git a/app/controllers/admin/dashboards_controller.rb b/app/controllers/admin/dashboards_controller.rb new file mode 100644 index 000000000..3ff70e8e0 --- /dev/null +++ b/app/controllers/admin/dashboards_controller.rb @@ -0,0 +1,5 @@ +class Admin::DashboardsController < AdminController + authorize_resource class: false + + def show; end +end diff --git a/app/controllers/admin/delayed_jobs_controller.rb b/app/controllers/admin/delayed_jobs_controller.rb index 88e5b9afe..a879c7db8 100644 --- a/app/controllers/admin/delayed_jobs_controller.rb +++ b/app/controllers/admin/delayed_jobs_controller.rb @@ -1,4 +1,6 @@ class Admin::DelayedJobsController < AdminController + authorize_resource class: false + def index @jobs = Delayed::Job.all end diff --git a/app/controllers/admin/domain_versions_controller.rb b/app/controllers/admin/domain_versions_controller.rb index 71a063417..dd8696d4a 100644 --- a/app/controllers/admin/domain_versions_controller.rb +++ b/app/controllers/admin/domain_versions_controller.rb @@ -1,4 +1,6 @@ class Admin::DomainVersionsController < AdminController + load_and_authorize_resource + def index @q = DomainVersion.deleted.search(params[:q]) @domains = @q.result.page(params[:page]) diff --git a/app/controllers/admin/domains_controller.rb b/app/controllers/admin/domains_controller.rb index f0bbd3abf..e282a9ef1 100644 --- a/app/controllers/admin/domains_controller.rb +++ b/app/controllers/admin/domains_controller.rb @@ -1,4 +1,5 @@ class Admin::DomainsController < AdminController + load_and_authorize_resource before_action :set_domain, only: [:show, :edit, :update, :zonefile] def index diff --git a/app/controllers/admin/epp_users_controller.rb b/app/controllers/admin/epp_users_controller.rb index c2d68d7f0..196a82edf 100644 --- a/app/controllers/admin/epp_users_controller.rb +++ b/app/controllers/admin/epp_users_controller.rb @@ -1,4 +1,5 @@ class Admin::EppUsersController < AdminController + load_and_authorize_resource before_action :set_epp_user, only: [:show, :edit, :update, :destroy] def index diff --git a/app/controllers/admin/registrars_controller.rb b/app/controllers/admin/registrars_controller.rb index 4059e1dcb..2bd15550f 100644 --- a/app/controllers/admin/registrars_controller.rb +++ b/app/controllers/admin/registrars_controller.rb @@ -1,4 +1,5 @@ class Admin::RegistrarsController < AdminController + load_and_authorize_resource before_action :set_registrar, only: [:show, :edit, :update, :destroy] def search render json: Registrar.search_by_query(params[:q]) diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb index b8e6048aa..c421781cd 100644 --- a/app/controllers/admin/settings_controller.rb +++ b/app/controllers/admin/settings_controller.rb @@ -1,4 +1,5 @@ class Admin::SettingsController < AdminController + load_and_authorize_resource before_action :set_setting_group, only: [:show, :update] def index diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index b5d9e3265..9fc95229a 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -1,4 +1,5 @@ class Admin::UsersController < AdminController + load_and_authorize_resource before_action :set_user, only: [:show, :edit, :update, :destroy] def index @@ -54,6 +55,6 @@ class Admin::UsersController < AdminController def user_params params.require(:user).permit(:username, :password, :identity_code, :email, - :admin, :country_id) + :role_id, :country_id) end end diff --git a/app/controllers/admin/zonefile_settings_controller.rb b/app/controllers/admin/zonefile_settings_controller.rb index da4c8a557..72030ebdf 100644 --- a/app/controllers/admin/zonefile_settings_controller.rb +++ b/app/controllers/admin/zonefile_settings_controller.rb @@ -1,4 +1,5 @@ class Admin::ZonefileSettingsController < ApplicationController + load_and_authorize_resource before_action :set_zonefile_setting, only: [:update, :edit] def index @zonefile_settings = ZonefileSetting.all diff --git a/app/controllers/admin/zonefiles_controller.rb b/app/controllers/admin/zonefiles_controller.rb index d99494ee5..9977d30b6 100644 --- a/app/controllers/admin/zonefiles_controller.rb +++ b/app/controllers/admin/zonefiles_controller.rb @@ -1,8 +1,7 @@ class Admin::ZonefilesController < ApplicationController + authorize_resource class: false # TODO: Refactor this # rubocop:disable Metrics/MethodLength - def index - end def create if ZonefileSetting.pluck(:origin).include?(params[:origin]) diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index f1834a20a..19f70495d 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -1,7 +1,3 @@ class AdminController < ApplicationController - # before_action :verify_admin - - def verify_admin - redirect_to client_root_path unless current_user.try(:admin?) - end + check_authorization end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index bae69e876..ba39047af 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -14,3 +14,9 @@ class ApplicationController < ActionController::Base admin_root_path end end + +class ApplicationController < ActionController::Base + rescue_from CanCan::AccessDenied do |exception| + redirect_to admin_dashboard_path, alert: exception.message + end +end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index cdefd70ae..66ea1425f 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -8,8 +8,6 @@ class SessionsController < Devise::SessionsController return redirect_to :back, alert: 'No user' if @user.blank? - session[:current_user_registrar_id] = Registrar.first.id if @user.admin? - flash[:notice] = I18n.t('shared.welcome') sign_in_and_redirect @user, event: :authentication # end @@ -18,10 +16,4 @@ class SessionsController < Devise::SessionsController def login render 'layouts/login', layout: false end - - def switch_registrar - authorize! :switch, :registrar - session[:current_user_registrar_id] = params[:registrar_id] - redirect_to client_root_path - end end diff --git a/app/models/ability.rb b/app/models/ability.rb index f26b3022b..c9e558299 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -8,38 +8,33 @@ class Ability user ||= User.new - if Rails.env.production? - case REGISTRY_ENV - when :eedirekt - can :view, :eedirekt - can :create, :session - admin = false - when :registrar - can :view, :registrar - can :create, :session - admin = false - when :admin - can :create, :admin_session - admin = user.admin? - end - else - can :create, :session - can :create, :admin_session - admin = user.admin? + admin_role = (user.role.try(:code) == 'admin') + user_role = (user.role.try(:code) == 'user') + customer_service_role = (user.role.try(:code) == 'customer_service') + no_role = user.role.nil? + + if admin_role + can :manage, Domain + can :manage, Contact + can :manage, Registrar + can :manage, Setting + can :manage, ZonefileSetting + can :manage, DomainVersion + can :manage, User + can :manage, EppUser + can :index, :delayed_job + can :create, :zonefile + can :access, :settings_menu + elsif customer_service_role + can :manage, Domain + can :manage, Contact + can :manage, Registrar + elsif user_role + elsif no_role + can :show, :dashboard end - if admin - can :manage, Domain - can :switch, :registrar - can :crud, DomainTransfer - can :approve_as_client, DomainTransfer, status: DomainTransfer::PENDING - elsif user.persisted? - can :manage, Domain, registrar_id: user.registrar.id - can :read, DomainTransfer, transfer_to_id: user.registrar.id - can :read, DomainTransfer, transfer_from_id: user.registrar.id - can :approve_as_client, DomainTransfer, - transfer_from_id: user.registrar.id, status: DomainTransfer::PENDING - end + can :show, :dashboard if user.persisted? # Define abilities for the passed in user here. For example: # diff --git a/app/models/role.rb b/app/models/role.rb index c2a1d26d2..f886c2e23 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -3,4 +3,10 @@ class Role < ActiveRecord::Base # rubocop: disable Rails/HasAndBelongsToMany has_and_belongs_to_many :rights # rubocop: enbale Rails/HasAndBelongsToMany + + validates :code, uniqueness: true + + def to_s + code + end end diff --git a/app/views/admin/dashboards/show.haml b/app/views/admin/dashboards/show.haml new file mode 100644 index 000000000..e69de29bb diff --git a/app/views/admin/domains/index.haml b/app/views/admin/domains/index.haml index dc27ba247..fc3eab342 100644 --- a/app/views/admin/domains/index.haml +++ b/app/views/admin/domains/index.haml @@ -33,7 +33,7 @@ - @domains.each do |x| %tr %td= link_to(x, admin_domain_path(x)) - %td= link_to(x.registrar, root_path) if x.registrar + %td= link_to(x.registrar, admin_registrar_path(x.registrar)) if x.registrar %td= link_to(x.owner_contact, [:admin, x.owner_contact]) %td= l(x.valid_to, format: :short) .row diff --git a/app/views/admin/users/_form.haml b/app/views/admin/users/_form.haml index 811121767..c3818109f 100644 --- a/app/views/admin/users/_form.haml +++ b/app/views/admin/users/_form.haml @@ -21,15 +21,14 @@ = f.label :identity_code = f.text_field(:identity_code, class: 'form-control') - .col-md-6.text-left + .col-md-6 .form-group = f.label :email = f.text_field(:email, class: 'form-control') .form-group - .checkbox - %label{for: 'user_admin'} - = f.check_box(:admin, class: 'js-admin') - = t('shared.admin') + = f.label :role_id + = f.select(:role_id, Role.all.map {|x| [t(x.code), x.id] }, {}, { class: 'form-control selectize' }) + %hr .row .col-md-12.text-right diff --git a/app/views/admin/users/index.haml b/app/views/admin/users/index.haml index 697bf8f16..f5030f35d 100644 --- a/app/views/admin/users/index.haml +++ b/app/views/admin/users/index.haml @@ -18,14 +18,17 @@ %th{class: 'col-xs-2'} = sort_link(@q, 'identity_code', t('shared.identity_code')) %th{class: 'col-xs-2'} - = sort_link(@q, 'admin', t('shared.admin')) + = sort_link(@q, 'role', t('role')) %tbody - @users.each do |x| %tr %td= link_to(x, [:admin, x]) %td= x.email %td= x.identity_code - %td= x.admin + - if x.role + %td= t(x.role) + - else + %td .row .col-md-12 = paginate @users diff --git a/app/views/admin/users/show.haml b/app/views/admin/users/show.haml index c82e71c70..b9661ee0f 100644 --- a/app/views/admin/users/show.haml +++ b/app/views/admin/users/show.haml @@ -39,5 +39,8 @@ %dt= t('shared.email') %dd= @user.email - %dt= t('shared.admin') - %dd= @user.admin + %dt= t('role') + - if @user.role + %dd= t(@user.role) + - else + %dd diff --git a/app/views/admin/zonefiles/index.haml b/app/views/admin/zonefiles/index.haml deleted file mode 100644 index bbd11577f..000000000 --- a/app/views/admin/zonefiles/index.haml +++ /dev/null @@ -1,9 +0,0 @@ -.row - .col-sm-12 - %h2.text-center-xs - = "#{t('zonefile')}" -%hr -.row - .col-md-12 - = preserve do - %pre= @zonefile diff --git a/app/views/layouts/application.haml b/app/views/layouts/application.haml index ff3bba9ff..a2c66e5ea 100644 --- a/app/views/layouts/application.haml +++ b/app/views/layouts/application.haml @@ -26,21 +26,22 @@ %li= link_to t('shared.domains'), admin_domains_path %li= link_to t('shared.contacts'), admin_contacts_path %li= link_to t('shared.registrars'), admin_registrars_path - %li.dropdown - %a.dropdown-toggle{"data-toggle" => "dropdown", href: "#"} - = t('shared.settings') - %span.caret - %ul.dropdown-menu{role: "menu"} - %li.dropdown-header= t('shared.system') - %li= link_to t('shared.settings'), admin_settings_path - %li= link_to t('zonefile'), admin_zonefile_settings_path - %li= link_to t(:domains_history), admin_domain_versions_path - %li= link_to t(:background_jobs), admin_delayed_jobs_path + - if can?(:access, :settings_menu) + %li.dropdown + %a.dropdown-toggle{"data-toggle" => "dropdown", href: "#"} + = t('shared.settings') + %span.caret + %ul.dropdown-menu{role: "menu"} + %li.dropdown-header= t('shared.system') + %li= link_to t('shared.settings'), admin_settings_path + %li= link_to t('zonefile'), admin_zonefile_settings_path + %li= link_to t(:domains_history), admin_domain_versions_path + %li= link_to t(:background_jobs), admin_delayed_jobs_path - %li.divider - %li.dropdown-header= t('shared.users') - %li= link_to t(:admin_users), admin_users_path - %li= link_to t(:epp_users), admin_epp_users_path + %li.divider + %li.dropdown-header= t('shared.users') + %li= link_to t(:admin_users), admin_users_path + %li= link_to t(:epp_users), admin_epp_users_path %ul.nav.navbar-nav.navbar-right %li= link_to t('shared.log_out', user: current_user), '/logout' diff --git a/app/views/layouts/login.haml b/app/views/layouts/login.haml index e516d6817..b3b2ab6e2 100644 --- a/app/views/layouts/login.haml +++ b/app/views/layouts/login.haml @@ -21,9 +21,8 @@ %h2.form-signin-heading.text-center Eesti Interneti SA %hr / TODO: Refactor this when ID card login is done - - if can? :create, :admin_session - = button_to 'ID card (user1)', 'sessions', - class: 'btn btn-lg btn-primary btn-block', name: 'user1' - = button_to 'ID card (user2)', 'sessions', - class: 'btn btn-lg btn-primary btn-block', name: 'user2' + = button_to 'ID card (user1)', 'sessions', + class: 'btn btn-lg btn-primary btn-block', name: 'user1' + = button_to 'ID card (user2)', 'sessions', + class: 'btn btn-lg btn-primary btn-block', name: 'user2' diff --git a/config/locales/en.yml b/config/locales/en.yml index fd503b4a3..aa4d36337 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -439,3 +439,7 @@ en: domains_history: Domains history admin_users: Admin users epp_users: EPP users + role: 'Role' + admin: 'Administrator' + user: 'User' + customer_service: 'Customer service' diff --git a/config/routes.rb b/config/routes.rb index 82dc72ae1..3a60e54b8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -31,6 +31,8 @@ Rails.application.routes.draw do resources :delayed_jobs + resource :dashboard + root 'domains#index' end diff --git a/db/migrate/20141218154829_populate_roles.rb b/db/migrate/20141218154829_populate_roles.rb new file mode 100644 index 000000000..126b758d7 --- /dev/null +++ b/db/migrate/20141218154829_populate_roles.rb @@ -0,0 +1,12 @@ +class PopulateRoles < ActiveRecord::Migration + def change + rename_column :roles, :name, :code + remove_column :users, :admin, :boolean + + Role.create(code: 'admin') + Role.create(code: 'user') + Role.create(code: 'customer_service') + + User.update_all(role_id: Role.first.id) + end +end diff --git a/db/schema.rb b/db/schema.rb index 7337f1ac8..e00caf67b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20141216133831) do +ActiveRecord::Schema.define(version: 20141218154829) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -304,7 +304,7 @@ ActiveRecord::Schema.define(version: 20141216133831) do end create_table "roles", force: true do |t| - t.string "name" + t.string "code" t.datetime "created_at" t.datetime "updated_at" end @@ -327,12 +327,11 @@ ActiveRecord::Schema.define(version: 20141216133831) do t.datetime "created_at" t.datetime "updated_at" t.string "email" - t.integer "sign_in_count", default: 0, null: false + t.integer "sign_in_count", default: 0, null: false t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" t.inet "current_sign_in_ip" t.inet "last_sign_in_ip" - t.boolean "admin", default: false t.string "identity_code" t.integer "country_id" end diff --git a/spec/epp/contact_spec.rb b/spec/epp/contact_spec.rb index 75c0b4d07..b9e0ae2cf 100644 --- a/spec/epp/contact_spec.rb +++ b/spec/epp/contact_spec.rb @@ -15,6 +15,7 @@ describe 'EPP Contact', epp: true do let(:server_elkdata) { Epp::Server.new({ server: 'localhost', tag: 'elkdata', password: 'ghyt9e4fu', port: 701 }) } let(:elkdata) { Fabricate(:registrar, { name: 'Elkdata', reg_no: '123' }) } let(:zone) { Registrar.where(reg_no: '12345678').first || Fabricate(:registrar) } + let(:epp_xml) { EppXml::Contact.new(cl_trid: 'ABC-12345') } context 'with valid user' do before(:each) do @@ -27,7 +28,7 @@ describe 'EPP Contact', epp: true do context 'create command' do it 'fails if request xml is missing' do - xml = EppXml::Contact.create + xml = epp_xml.create response = epp_request(xml, :xml) expect(response[:results][0][:result_code]).to eq('2001') @@ -36,7 +37,7 @@ describe 'EPP Contact', epp: true do end it 'fails if request xml is missing' do - xml = EppXml::Contact.create( + xml = epp_xml.create( postalInfo: { addr: { value: nil } } ) response = epp_request(xml, :xml) @@ -145,7 +146,7 @@ describe 'EPP Contact', epp: true do context 'update command' do it 'fails if request is invalid' do - xml = EppXml::Contact.update + xml = epp_xml.update response = epp_request(xml, :xml) # epp_request('contacts/update_missing_attr.xml') expect(response[:results][0][:result_code]).to eq('2003') @@ -227,7 +228,7 @@ describe 'EPP Contact', epp: true do context 'delete command' do it 'fails if request is invalid' do - xml = EppXml::Contact.delete({ uid: { value: '23123' } }) + xml = epp_xml.delete({ uid: { value: '23123' } }) response = epp_request(xml, :xml) expect(response[:results][0][:result_code]).to eq('2003') @@ -274,7 +275,7 @@ describe 'EPP Contact', epp: true do context 'check command' do it 'fails if request is invalid' do - xml = EppXml::Contact.check({ uid: { value: '123asde' } }) + xml = epp_xml.check({ uid: { value: '123asde' } }) response = epp_request(xml, :xml) expect(response[:results][0][:result_code]).to eq('2003') @@ -304,7 +305,7 @@ describe 'EPP Contact', epp: true do @contact = Fabricate(:contact, registrar: zone, code: 'info-4444', name: 'Johnny Awesome', auth_info: 'asde', address: Fabricate(:address), disclosure: Fabricate(:contact_disclosure, name: false)) - xml = EppXml::Contact.info({ id: { value: @contact.code } }) + xml = epp_xml.info({ id: { value: @contact.code } }) response = epp_request(xml, :xml, :zone) contact = response[:parsed].css('resData chkData') @@ -317,7 +318,7 @@ describe 'EPP Contact', epp: true do @contact = Fabricate(:contact, registrar: elkdata, code: 'info-4444', name: 'Johnny Awesome', auth_info: 'asde', address: Fabricate(:address), disclosure: Fabricate(:contact_disclosure, name: false)) - xml = EppXml::Contact.info({ id: { value: @contact.code }, authInfo: { pw: { value: 'asdesde' } } }) + xml = epp_xml.info({ id: { value: @contact.code }, authInfo: { pw: { value: 'asdesde' } } }) response = epp_request(xml, :xml, :zone) expect(response[:result_code]).to eq('2200') @@ -329,7 +330,7 @@ describe 'EPP Contact', epp: true do name: 'Johnny Awesome', auth_info: 'password', address: Fabricate(:address), disclosure: Fabricate(:contact_disclosure, name: false)) - xml = EppXml::Contact.info({ id: { value: @contact.code }, authInfo: { pw: { value: 'password' } } }) + xml = epp_xml.info({ id: { value: @contact.code }, authInfo: { pw: { value: 'password' } } }) response = epp_request(xml, :xml, :zone) contact = response[:parsed].css('resData chkData') @@ -343,7 +344,7 @@ describe 'EPP Contact', epp: true do auth_info: 'password', address: Fabricate(:address), disclosure: Fabricate(:contact_disclosure, name: false)) - xml = EppXml::Contact.info({ id: { value: @contact.code } }) + xml = epp_xml.info({ id: { value: @contact.code } }) response = epp_request(xml, :xml, :zone) contact = response[:parsed].css('resData chkData') @@ -353,7 +354,7 @@ describe 'EPP Contact', epp: true do end it 'fails if request invalid' do - response = epp_request(EppXml::Contact.info({ uid: { value: '123123' } }), :xml) + response = epp_request(epp_xml.info({ uid: { value: '123123' } }), :xml) expect(response[:results][0][:result_code]).to eq('2003') expect(response[:results][0][:msg]).to eq('Required parameter missing: id') @@ -371,7 +372,7 @@ describe 'EPP Contact', epp: true do @contact = Fabricate(:contact, registrar: zone, code: 'info-4444', name: 'Johnny Awesome', address: Fabricate(:address)) - xml = EppXml::Contact.info(id: { value: @contact.code }) + xml = epp_xml.info(id: { value: @contact.code }) response = epp_request(xml, :xml, :zone) contact = response[:parsed].css('resData chkData') @@ -385,7 +386,7 @@ describe 'EPP Contact', epp: true do Fabricate(:contact, code: 'info-4444', auth_info: '2fooBAR', registrar: elkdata, disclosure: Fabricate(:contact_disclosure, name: true, email: false, phone: false)) - xml = EppXml::Contact.info({ id: { value: 'info-4444' }, authInfo: { pw: { value: '2fooBAR' } } }) + xml = epp_xml.info({ id: { value: 'info-4444' }, authInfo: { pw: { value: '2fooBAR' } } }) response = epp_request(xml, :xml, :zone) contact = response[:parsed].css('resData chkData') @@ -402,7 +403,7 @@ describe 'EPP Contact', epp: true do it 'doesn\'t display unassociated object without password' do @contact = Fabricate(:contact, code: 'info-4444', registrar: zone) - xml = EppXml::Contact.info(id: { value: @contact.code }) + xml = epp_xml.info(id: { value: @contact.code }) response = epp_request(xml, :xml, :elkdata) expect(response[:result_code]).to eq('2003') expect(response[:msg]).to eq('Required parameter missing: pw') @@ -411,7 +412,7 @@ describe 'EPP Contact', epp: true do it 'doesn\'t display unassociated object with wrong password' do @contact = Fabricate(:contact, code: 'info-4444', registrar: zone) - xml = EppXml::Contact.info(id: { value: @contact.code }, authInfo: { pw: { value: 'qwe321' } }) + xml = epp_xml.info(id: { value: @contact.code }, authInfo: { pw: { value: 'qwe321' } }) response = epp_request(xml, :xml, :elkdata) expect(response[:result_code]).to eq('2200') expect(response[:msg]).to eq('Authentication error') diff --git a/spec/epp/domain_spec.rb b/spec/epp/domain_spec.rb index a0d479969..0e0cec11d 100644 --- a/spec/epp/domain_spec.rb +++ b/spec/epp/domain_spec.rb @@ -15,6 +15,7 @@ describe 'EPP Domain', epp: true do let(:server_elkdata) { Epp::Server.new({ server: 'localhost', tag: 'elkdata', password: 'ghyt9e4fu', port: 701 }) } let(:elkdata) { Fabricate(:registrar, { name: 'Elkdata', reg_no: '123' }) } let(:zone) { Fabricate(:registrar) } + let(:epp_xml) { EppXml.new(cl_trid: 'ABC-12345') } before(:each) { create_settings } @@ -113,7 +114,7 @@ describe 'EPP Domain', epp: true do # should show up in other registrar's poll - response = epp_request(EppXml::Session.poll, :xml, :elkdata) + response = epp_request(epp_xml.session.poll, :xml, :elkdata) expect(response[:msg]).to eq('Command completed successfully; ack to dequeue') msg_q = response[:parsed].css('msgQ') expect(msg_q.css('qDate').text).to_not be_blank @@ -121,7 +122,7 @@ describe 'EPP Domain', epp: true do expect(msg_q.first['id']).to_not be_blank expect(msg_q.first['count']).to eq('1') - xml = EppXml::Session.poll(poll: { + xml = epp_xml.session.poll(poll: { value: '', attrs: { op: 'ack', msgID: msg_q.first['id'] } }) @@ -751,7 +752,7 @@ describe 'EPP Domain', epp: true do it 'renews a domain' do exp_date = (Date.today + 1.year) - xml = EppXml::Domain.renew( + xml = epp_xml.domain.renew( name: { value: 'example.ee' }, curExpDate: { value: exp_date.to_s }, period: { value: '1', attrs: { unit: 'y' } } @@ -765,7 +766,7 @@ describe 'EPP Domain', epp: true do end it 'returns an error when given and current exp dates do not match' do - xml = EppXml::Domain.renew( + xml = epp_xml.domain.renew( name: { value: 'example.ee' }, curExpDate: { value: '2016-08-07' }, period: { value: '1', attrs: { unit: 'y' } } @@ -779,7 +780,7 @@ describe 'EPP Domain', epp: true do it 'returns an error when period is invalid' do exp_date = (Date.today + 1.year) - xml = EppXml::Domain.renew( + xml = epp_xml.domain.renew( name: { value: 'example.ee' }, curExpDate: { value: exp_date.to_s }, period: { value: '4', attrs: { unit: 'y' } } @@ -1134,7 +1135,7 @@ describe 'EPP Domain', epp: true do it 'deletes domain' do expect(DomainContact.count).to eq(2) - response = epp_request(EppXml::Domain.delete(name: { value: 'example.ee' }), :xml) + response = epp_request(epp_xml.domain.delete(name: { value: 'example.ee' }), :xml) expect(response[:result_code]).to eq('1000') expect(Domain.first).to eq(nil) @@ -1144,7 +1145,7 @@ describe 'EPP Domain', epp: true do it 'does not delete domain with specific status' do d = Domain.first d.domain_statuses.create(value: DomainStatus::CLIENT_DELETE_PROHIBITED) - response = epp_request(EppXml::Domain.delete(name: { value: 'example.ee' }), :xml) + response = epp_request(epp_xml.domain.delete(name: { value: 'example.ee' }), :xml) expect(response[:result_code]).to eq('2304') expect(response[:msg]).to eq('Domain status prohibits operation') end diff --git a/spec/epp/keyrelay_spec.rb b/spec/epp/keyrelay_spec.rb index bcdcddd6b..3349c7195 100644 --- a/spec/epp/keyrelay_spec.rb +++ b/spec/epp/keyrelay_spec.rb @@ -6,6 +6,7 @@ describe 'EPP Keyrelay', epp: true do let(:elkdata) { Fabricate(:registrar, { name: 'Elkdata', reg_no: '123' }) } let(:zone) { Fabricate(:registrar) } let(:domain) { Fabricate(:domain, name: 'example.ee', registrar: zone, dnskeys: [Fabricate.build(:dnskey)]) } + let(:epp_xml) { EppXml::Keyrelay.new } before(:each) { create_settings } @@ -16,7 +17,7 @@ describe 'EPP Keyrelay', epp: true do end it 'makes a keyrelay request' do - xml = EppXml::Keyrelay.keyrelay({ + xml = epp_xml.keyrelay({ name: { value: 'example.ee' }, keyData: { flags: { value: '256' }, diff --git a/spec/epp/poll_spec.rb b/spec/epp/poll_spec.rb index 030b9b022..6eed885ec 100644 --- a/spec/epp/poll_spec.rb +++ b/spec/epp/poll_spec.rb @@ -5,6 +5,7 @@ describe 'EPP Poll', epp: true do let(:server_elkdata) { Epp::Server.new({ server: 'localhost', tag: 'elkdata', password: 'ghyt9e4fu', port: 701 }) } let(:elkdata) { Fabricate(:registrar, { name: 'Elkdata', reg_no: '123' }) } let(:zone) { Fabricate(:registrar) } + let(:epp_xml) { EppXml::Session.new } before(:each) { create_settings } @@ -15,7 +16,7 @@ describe 'EPP Poll', epp: true do end it 'returns no messages in poll' do - response = epp_request(EppXml::Session.poll, :xml) + response = epp_request(epp_xml.poll, :xml) expect(response[:msg]).to eq('Command completed successfully; no messages') expect(response[:result_code]).to eq('1300') @@ -24,11 +25,11 @@ describe 'EPP Poll', epp: true do it 'queues and dequeues messages' do msg = zone.messages.create({ body: 'Balance low.' }) - response = epp_request(EppXml::Session.poll, :xml, :elkdata) + response = epp_request(epp_xml.poll, :xml, :elkdata) expect(response[:msg]).to eq('Command completed successfully; no messages') expect(response[:result_code]).to eq('1300') - response = epp_request(EppXml::Session.poll, :xml, :zone) + response = epp_request(epp_xml.poll, :xml, :zone) expect(response[:msg]).to eq('Command completed successfully; ack to dequeue') expect(response[:result_code]).to eq('1301') msg_q = response[:parsed].css('msgQ') @@ -37,7 +38,7 @@ describe 'EPP Poll', epp: true do expect(msg_q.first['count']).to eq('1') expect(msg_q.first['id']).to eq(msg.id.to_s) - xml = EppXml::Session.poll(poll: { + xml = epp_xml.poll(poll: { value: '', attrs: { op: 'ack', msgID: msg_q.first['id'] } }) @@ -59,7 +60,7 @@ describe 'EPP Poll', epp: true do end it 'returns an error on incorrect op' do - xml = EppXml::Session.poll(poll: { + xml = epp_xml.poll(poll: { value: '', attrs: { op: 'bla' } }) @@ -72,7 +73,7 @@ describe 'EPP Poll', epp: true do zone.messages.create({ body: 'Something.' }) zone.messages.create({ body: 'Smth else.' }) - response = epp_request(EppXml::Session.poll, :xml, :zone) + response = epp_request(epp_xml.poll, :xml, :zone) expect(response[:msg]).to eq('Command completed successfully; ack to dequeue') expect(response[:result_code]).to eq('1301') msg_q = response[:parsed].css('msgQ') @@ -80,7 +81,7 @@ describe 'EPP Poll', epp: true do expect(msg_q.css('msg').text).to eq('Smth else.') expect(msg_q.first['count']).to eq('3') - xml = EppXml::Session.poll(poll: { + xml = epp_xml.poll(poll: { value: '', attrs: { op: 'ack', msgID: msg_q.first['id'] } }) @@ -90,7 +91,7 @@ describe 'EPP Poll', epp: true do expect(msg_q.first['id']).to_not be_blank expect(msg_q.first['count']).to eq('2') - response = epp_request(EppXml::Session.poll, :xml, :zone) + response = epp_request(epp_xml.poll, :xml, :zone) expect(response[:msg]).to eq('Command completed successfully; ack to dequeue') expect(response[:result_code]).to eq('1301') msg_q = response[:parsed].css('msgQ') @@ -98,7 +99,7 @@ describe 'EPP Poll', epp: true do expect(msg_q.css('msg').text).to eq('Something.') expect(msg_q.first['count']).to eq('2') - xml = EppXml::Session.poll(poll: { + xml = epp_xml.poll(poll: { value: '', attrs: { op: 'ack', msgID: msg_q.first['id'] } }) @@ -108,7 +109,7 @@ describe 'EPP Poll', epp: true do expect(msg_q.first['id']).to_not be_blank expect(msg_q.first['count']).to eq('1') - response = epp_request(EppXml::Session.poll, :xml, :zone) + response = epp_request(epp_xml.poll, :xml, :zone) expect(response[:msg]).to eq('Command completed successfully; ack to dequeue') expect(response[:result_code]).to eq('1301') msg_q = response[:parsed].css('msgQ') @@ -116,7 +117,7 @@ describe 'EPP Poll', epp: true do expect(msg_q.css('msg').text).to eq('Balance low.') expect(msg_q.first['count']).to eq('1') - xml = EppXml::Session.poll(poll: { + xml = epp_xml.poll(poll: { value: '', attrs: { op: 'ack', msgID: msg_q.first['id'] } }) @@ -126,7 +127,7 @@ describe 'EPP Poll', epp: true do expect(msg_q.first['id']).to_not be_blank expect(msg_q.first['count']).to eq('0') - response = epp_request(EppXml::Session.poll, :xml, :zone) + response = epp_request(epp_xml.poll, :xml, :zone) expect(response[:msg]).to eq('Command completed successfully; no messages') expect(response[:result_code]).to eq('1300') end diff --git a/spec/epp/session_spec.rb b/spec/epp/session_spec.rb index c6ba1e1f8..2806f87da 100644 --- a/spec/epp/session_spec.rb +++ b/spec/epp/session_spec.rb @@ -2,7 +2,8 @@ require 'rails_helper' describe 'EPP Session', epp: true do let(:server_gitlab) { Epp::Server.new({ server: 'localhost', tag: 'gitlab', password: 'ghyt9e4fu', port: 701 }) } - let(:login_xml_cache) { EppXml::Session.login(clID: { value: 'gitlab' }, pw: { value: 'ghyt9e4fu' }) } + let(:epp_xml) { EppXml.new(cl_trid: 'ABC-12345') } + let(:login_xml_cache) { epp_xml.session.login(clID: { value: 'gitlab' }, pw: { value: 'ghyt9e4fu' }) } context 'when not connected' do it 'greets client upon connection' do @@ -29,7 +30,7 @@ describe 'EPP Session', epp: true do end it 'prohibits further actions unless logged in' do - response = epp_plain_request(EppXml::Domain.create, :xml) + response = epp_plain_request(epp_xml.domain.create, :xml) expect(response[:result_code]).to eq('2002') expect(response[:msg]).to eq('You need to login first.') expect(response[:clTRID]).to eq('ABC-12345') diff --git a/spec/fabricators/role_fabricator.rb b/spec/fabricators/role_fabricator.rb new file mode 100644 index 000000000..e084a0dcc --- /dev/null +++ b/spec/fabricators/role_fabricator.rb @@ -0,0 +1,3 @@ +Fabricator(:role) do + code 'admin' +end diff --git a/spec/fabricators/user_fabricator.rb b/spec/fabricators/user_fabricator.rb index 0a0091a23..57776f677 100644 --- a/spec/fabricators/user_fabricator.rb +++ b/spec/fabricators/user_fabricator.rb @@ -3,6 +3,6 @@ Fabricator(:user) do password 'ghyt9e4fu' email 'info@gitlab.eu' identity_code '37810013108' - admin true country + role end diff --git a/spec/features/sessions_spec.rb b/spec/features/sessions_spec.rb index 86474998a..b7484cc4a 100644 --- a/spec/features/sessions_spec.rb +++ b/spec/features/sessions_spec.rb @@ -6,8 +6,7 @@ feature 'Sessions', type: :feature do background do create_settings - Fabricate(:user, identity_code: '37810013261') - Fabricate(:user, username: 'zone', admin: false, identity_code: '37810013087') + Fabricate(:user, username: 'zone', identity_code: '37810013087') Fabricate.times(2, :domain, registrar: zone) Fabricate.times(2, :domain, registrar: elkdata) end diff --git a/spec/features/setting_management_spec.rb b/spec/features/setting_management_spec.rb index 5cedbfc1a..f53185d62 100644 --- a/spec/features/setting_management_spec.rb +++ b/spec/features/setting_management_spec.rb @@ -1,14 +1,13 @@ require 'rails_helper' feature 'Setting management', type: :feature do - let(:user) { Fabricate(:user, username: 'user1', admin: true, identity_code: '37810013087') } + let(:user) { Fabricate(:user, username: 'user1', identity_code: '37810013087') } background { create_settings } scenario 'User changes a setting' do sign_in user visit admin_settings_path - val_min = find_field('_settings_ns_min_count').value val_max = find_field('_settings_ns_max_count').value diff --git a/spec/models/contact_disclosure_spec.rb b/spec/models/contact_disclosure_spec.rb index fa9ae0e31..ad5d37d49 100644 --- a/spec/models/contact_disclosure_spec.rb +++ b/spec/models/contact_disclosure_spec.rb @@ -18,7 +18,8 @@ describe '.extract_attributes' do # TODO: remodel create contact xml to support disclosure it 'should return disclosure has if disclosure' do - xml = EppXml::Contact.create( + epp_xml = EppXml::Contact.new + xml = epp_xml.create( { disclose: { value: { voice: { value: '' }, diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 2f99cf77d..e3a1dcf5a 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,5 +1,43 @@ require 'rails_helper' +require 'cancan/matchers' describe User do it { should belong_to(:role) } + + describe 'abilities' do + subject(:ability) { Ability.new(user) } + let(:user) { nil } + + context 'when user is admin' do + let(:user) { Fabricate(:user) } + + it { should be_able_to(:manage, Domain.new) } + it { should be_able_to(:manage, Contact.new) } + it { should be_able_to(:manage, Registrar.new) } + it { should be_able_to(:manage, Setting.new) } + it { should be_able_to(:manage, ZonefileSetting.new) } + it { should be_able_to(:manage, DomainVersion.new) } + it { should be_able_to(:manage, User.new) } + it { should be_able_to(:manage, EppUser.new) } + it { should be_able_to(:index, :delayed_job) } + it { should be_able_to(:create, :zonefile) } + it { should be_able_to(:access, :settings_menu) } + end + + context 'when user is customer service' do + let(:user) { Fabricate(:user, role: Role.new(code: 'customer_service')) } + + it { should be_able_to(:manage, Domain.new) } + it { should be_able_to(:manage, Contact.new) } + it { should be_able_to(:manage, Registrar.new) } + it { should_not be_able_to(:manage, Setting.new) } + it { should_not be_able_to(:manage, ZonefileSetting.new) } + it { should_not be_able_to(:manage, DomainVersion.new) } + it { should_not be_able_to(:manage, User.new) } + it { should_not be_able_to(:manage, EppUser.new) } + it { should_not be_able_to(:index, :delayed_job) } + it { should_not be_able_to(:create, :zonefile) } + it { should_not be_able_to(:access, :settings_menu) } + end + end end diff --git a/spec/support/epp.rb b/spec/support/epp.rb index ae9e166d6..a35580384 100644 --- a/spec/support/epp.rb +++ b/spec/support/epp.rb @@ -78,7 +78,9 @@ module Epp } xml_params = defaults.deep_merge(xml_params) - EppXml::Domain.info(xml_params) + + epp_xml = EppXml::Domain.new(cl_trid: 'ABC-12345') + epp_xml.info(xml_params) end # rubocop: disable Metrics/MethodLength @@ -122,7 +124,8 @@ module Epp } dnssec_params = dnssec_defaults.deep_merge(dnssec_params) if dnssec_params != false - EppXml::Domain.create(xml_params, dnssec_params) + epp_xml = EppXml::Domain.new(cl_trid: 'ABC-12345') + epp_xml.create(xml_params, dnssec_params) end def domain_create_with_invalid_ns_ip_xml @@ -154,7 +157,8 @@ module Epp } } - EppXml::Domain.create(xml_params, false) + epp_xml = EppXml::Domain.new(cl_trid: 'ABC-12345') + epp_xml.create(xml_params, false) end def domain_create_with_host_attrs @@ -186,7 +190,8 @@ module Epp } } - EppXml::Domain.create(xml_params, false) + epp_xml = EppXml::Domain.new(cl_trid: 'ABC-12345') + epp_xml.create(xml_params, false) end def domain_update_xml(xml_params = {}, dnssec_params = false) @@ -195,7 +200,8 @@ module Epp } xml_params = defaults.deep_merge(xml_params) - EppXml::Domain.update(xml_params, dnssec_params) + epp_xml = EppXml::Domain.new(cl_trid: 'ABC-12345') + epp_xml.update(xml_params, dnssec_params) end def domain_check_xml(xml_params = {}) @@ -205,7 +211,8 @@ module Epp ] } xml_params = defaults.deep_merge(xml_params) - EppXml::Domain.check(xml_params) + epp_xml = EppXml::Domain.new(cl_trid: 'ABC-12345') + epp_xml.check(xml_params) end def domain_transfer_xml(xml_params = {}, op = 'query') @@ -217,7 +224,8 @@ module Epp } xml_params = defaults.deep_merge(xml_params) - EppXml::Domain.transfer(xml_params, op) + epp_xml = EppXml::Domain.new(cl_trid: 'ABC-12345') + epp_xml.transfer(xml_params, op) end def log(req, res) diff --git a/spec/support/epp_contact_xml_helper.rb b/spec/support/epp_contact_xml_helper.rb index 47aaa1548..7fc2747fd 100644 --- a/spec/support/epp_contact_xml_helper.rb +++ b/spec/support/epp_contact_xml_helper.rb @@ -15,7 +15,8 @@ module EppContactXmlHelper } xml_params = defaults.deep_merge(xml_params) - EppXml::Contact.create(xml_params) + epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345') + epp_xml.create(xml_params) end def update_contact_xml(xml_params = {}) @@ -37,19 +38,22 @@ module EppContactXmlHelper } } xml_params = defaults.deep_merge(xml_params) - EppXml::Contact.update(xml_params) + epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345') + epp_xml.update(xml_params) end def delete_contact_xml(xml_params = {}) defaults = { id: { value: 'sh8012' } } xml_params = defaults.deep_merge(xml_params) - EppXml::Contact.delete(xml_params) + epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345') + epp_xml.delete(xml_params) end def info_contact_xml(xml_params = {}) defaults = { id: { value: 'sh8012' }, authInfo: { pw: { value: 'password' } } } xml_params = defaults.deep_merge(xml_params) - EppXml::Contact.info(xml_params) + epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345') + epp_xml.info(xml_params) end def check_contact_xml(xml_params = {}) @@ -57,7 +61,8 @@ module EppContactXmlHelper id: { value: 'ad123c3' } } xml_params = defaults.deep_merge(xml_params) - EppXml::Contact.check(xml_params) + epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345') + epp_xml.check(xml_params) end def check_multiple_contacts_xml diff --git a/spec/support/feature.rb b/spec/support/feature.rb index f529e8bcf..1505aa217 100644 --- a/spec/support/feature.rb +++ b/spec/support/feature.rb @@ -1,7 +1,7 @@ module Feature def sign_in(user) visit '/logout' - click_on 'ID card (gitlab)' if user.username == 'gitlab' + click_on 'ID card (user1)' if user.username == 'user1' end end