1
0
Fork 0

Remove roles

This commit is contained in:
Alex Kotov 2019-08-12 00:27:06 +05:00
parent 5d35a21e34
commit 94ccab8a18
Signed by: kotovalexarian
GPG Key ID: 553C0EBBEB5D5F08
36 changed files with 87 additions and 837 deletions

View File

@ -51,10 +51,6 @@ Rails:
Rails/BulkChangeTable:
Enabled: false
Rails/HasAndBelongsToMany:
Exclude:
- 'app/models/role.rb'
Rails/HasManyOrHasOneDependent:
Enabled: false

View File

@ -79,11 +79,6 @@ gem 'devise', '~> 4.6'
# Translations for the devise gem.
gem 'devise-i18n', '~> 1.8'
# Very simple Roles library without any authorization enforcement
# supporting scope on resource objects (instance or class).
# Supports ActiveRecord and Mongoid ORMs.
gem 'rolify', '~> 5.2'
# Object oriented authorization for Rails applications.
gem 'pundit', '~> 2.0'

View File

@ -314,7 +314,6 @@ GEM
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
rolify (5.2.0)
rspec-core (3.8.2)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.4)
@ -468,7 +467,6 @@ DEPENDENCIES
recaptcha (~> 4.13)
redis (~> 4.1)
rest-client (~> 2.0)
rolify (~> 5.2)
rspec-rails (~> 3.8)
rubocop (~> 0.72.0)
rubocop-performance (~> 1.4)

View File

@ -1,30 +0,0 @@
# frozen_string_literal: true
class Settings::RolesController < ApplicationController
before_action :set_role, except: :index
# GET /settings/roles
def index
authorize %i[settings role]
@roles = policy_scope(
current_account.roles,
policy_scope_class: Settings::RolePolicy::Scope,
)
end
# DELETE /settings/roles/:id
def destroy
authorize [:settings, @role]
current_account.remove_role @role.name, @role.resource
redirect_to settings_roles_url
end
private
def set_role
@role = current_account.roles.find params[:id]
end
end

View File

@ -1,17 +1,8 @@
# frozen_string_literal: true
class Account < ApplicationRecord
include Rolify::Role
extend Rolify::Dynamic if Rolify.dynamic_shortcuts
NICKNAME_RE = /\A[a-z][a-z0-9]*(_[a-z0-9]+)*\z/.freeze
self.role_cname = 'Role'
self.role_table_name = 'roles'
self.strict_rolify = false
self.adapter = Rolify::Adapter::Base.create 'role_adapter', role_cname, name
##########
# Scopes #
##########
@ -24,14 +15,6 @@ class Account < ApplicationRecord
has_one_attached :avatar
has_many :account_roles,
-> { active },
inverse_of: :account
has_many :roles,
-> { distinct },
through: :account_roles
belongs_to :person, optional: true
belongs_to :contact_list
@ -87,31 +70,8 @@ class Account < ApplicationRecord
user.nil?
end
def add_role(role_name, resource = nil)
raise 'can not add role to guest account' if guest?
role = self.class.role_class.make! role_name, resource
return role if roles.include? role
if Rolify.dynamic_shortcuts
self.class.define_dynamic_method role.name, resource
end
account_roles.where(role: role).first_or_create!
role
end
def remove_role(role_name, resource = nil)
role = self.class.role_class.find_by name: role_name, resource: resource
return if role.nil?
account_roles.where(role: role).update_all(deleted_at: Time.zone.now)
end
def can_access_sidekiq_web_interface?
is_superuser?
superuser?
end
private

View File

@ -1,40 +0,0 @@
# frozen_string_literal: true
class AccountRole < ApplicationRecord
################
# Associations #
################
belongs_to :account
belongs_to :role
##########
# Scopes #
##########
scope :active, -> { not_deleted.not_expired }
scope :not_deleted, -> { where(deleted_at: nil) }
scope :not_expired, lambda {
where(
arel_table[:expires_at].eq(nil).or(
arel_table[:expires_at].gt(Time.zone.now),
),
)
}
###############
# Validations #
###############
validate :deleted_at_is_not_in_future
private
def deleted_at_is_not_in_future
return if deleted_at.nil?
errors.add :deleted_at unless deleted_at <= Time.zone.now + 10
end
end

View File

@ -1,58 +0,0 @@
# frozen_string_literal: true
class Role < ApplicationRecord
NAMES = %w[
superuser
].map(&:freeze).freeze
scopify
################
# Associations #
################
has_many :account_roles,
-> { active },
inverse_of: :role
has_many :accounts, through: :account_roles
belongs_to :resource, polymorphic: true, optional: true
###############
# Validations #
###############
validates :name,
presence: true,
inclusion: { in: NAMES }
validates :resource_type,
allow_nil: true,
inclusion: { in: Rolify.resource_types }
###########
# Methods #
###########
def self.make!(role_name, resource = nil)
resource_type =
resource.is_a?(Class) ? resource.to_s : resource&.class&.name
resource_id = resource&.id unless resource.is_a? Class
find_or_create_by!(
name: role_name,
resource_type: resource_type,
resource_id: resource_id,
)
end
def human_name
I18n.translate name, scope: :roles
end
def human_resource
"#{resource_type} ##{resource_id}" if resource_id
end
end

View File

@ -1,19 +0,0 @@
# frozen_string_literal: true
class Settings::RolePolicy < ApplicationPolicy
def index?
account && !account.guest?
end
def destroy?
account && !account.guest? && account.roles.include?(record)
end
class Scope < Scope
def resolve
return scope.none if account.nil? || account.guest?
scope.merge(account.roles)
end
end
end

View File

@ -2,6 +2,6 @@
class Staff::HomePolicy < ApplicationPolicy
def show?
account&.is_superuser?
account&.superuser?
end
end

View File

@ -2,12 +2,12 @@
class Staff::Person::PassportPolicy < ApplicationPolicy
def index?
account&.is_superuser?
account&.superuser?
end
class Scope < Scope
def resolve
return scope.all if account&.is_superuser?
return scope.all if account&.superuser?
scope.none
end

View File

@ -2,11 +2,11 @@
class Staff::Person::PersonCommentPolicy < ApplicationPolicy
def index?
account&.is_superuser?
account&.superuser?
end
def create?
account&.is_superuser?
account&.superuser?
end
def permitted_attributes_for_create
@ -15,7 +15,7 @@ class Staff::Person::PersonCommentPolicy < ApplicationPolicy
class Scope < Scope
def resolve
return scope.all if account&.is_superuser?
return scope.all if account&.superuser?
scope.none
end

View File

@ -2,16 +2,16 @@
class Staff::PersonPolicy < ApplicationPolicy
def index?
account&.is_superuser?
account&.superuser?
end
def show?
account&.is_superuser?
account&.superuser?
end
class Scope < Scope
def resolve
return scope.all if account&.is_superuser?
return scope.all if account&.superuser?
scope.none
end

View File

@ -12,11 +12,4 @@
class: 'list-group-item list-group-item-action ' \
"#{:active if tab == :credentials}" %>
<% end %>
<% if policy(%i[settings role]).index? %>
<%= link_to translate(:roles, scope: %i[nav_tabs settings]),
settings_roles_path,
class: 'list-group-item list-group-item-action ' \
"#{:active if tab == :roles}" %>
<% end %>
</div>

View File

@ -1,47 +0,0 @@
<div class="container">
<div class="row">
<div class="col-md-3 mb-4">
<%= render partial: 'settings/nav_sidebar', locals: { tab: :roles } %>
</div>
<div class="col-md-9">
<table class="table">
<thead>
<tr>
<th scope="col">
<%= Role.human_attribute_name :id %>
</th>
<th scope="col">
<%= Role.human_attribute_name :name %>
</th>
<th scope="col">
<%= Role.human_attribute_name :resource %>
</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<% @roles.each do |role| %>
<tr>
<td scope="row"><%= role.id %></td>
<td><%= role.human_name %></td>
<td><%= role.human_resource %></td>
<td>
<% if policy([:settings, role]).destroy? %>
<%= link_to [:settings, role],
method: :delete,
role: :button,
class: 'btn btn-danger btn-sm' do %>
<i class="fas fa-trash"></i>
<%= translate '.revoke' %>
<% end %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>

View File

@ -1,11 +0,0 @@
# frozen_string_literal: true
Rolify.configure do |config|
# Dynamic shortcuts for User class (user.is_admin? like methods).
# Default is: false.
config.use_dynamic_shortcuts
# Configuration to remove roles from database
# once the last resource is removed. Default is: true.
config.remove_role_if_empty = false
end

View File

@ -19,9 +19,6 @@ en:
regional_office:
one: Regional office
many: Regional offices
roles:
one: Role
many: Roles
user:
one: User
many: Users
@ -71,10 +68,6 @@ en:
id: ID
current_supporters_count: Number of supporters
current_members_count: Number of members
role:
id: ID
name: Name
resource: Resource
user:
id: ID
confirmation_sent_at: Confirmation sent at

View File

@ -19,9 +19,6 @@ ru:
regional_office:
one: Региональное отделение
many: Региональные отделения
roles:
one: Роль
many: Роли
user:
one: Пользователь
many: Пользователи
@ -71,10 +68,6 @@ ru:
id: ID
current_supporters_count: Количество сторонников
current_members_count: Количество членов
role:
id: ID
name: Название
resource: Ресурс
user:
id: ID
confirmation_sent_at: Дата отправки подтверждения

View File

@ -7,4 +7,3 @@ en:
settings:
credentials: Credentials
profile: Public profile
roles: Roles

View File

@ -7,4 +7,3 @@ ru:
settings:
credentials: Данные для входа
profile: Публичный профиль
roles: Роли

View File

@ -1,3 +0,0 @@
en:
roles:
superuser: Superuser

View File

@ -1,3 +0,0 @@
ru:
roles:
superuser: Суперпользователь

View File

@ -7,7 +7,3 @@ en:
We stand for a free market and freedom of government intervention
in the economy, for the principle of self-ownership and self-value
of the human person.
settings:
roles:
index:
revoke: Revoke

View File

@ -7,7 +7,3 @@ ru:
Мы выступаем за свободный рынок и государственное невмешательство
в экономику, за принцип самопринадлежности и самоценности человеческой
личности.
settings:
roles:
index:
revoke: Отозвать

View File

@ -32,7 +32,6 @@ Rails.application.routes.draw do
namespace :settings do
resource :profile, only: %i[edit update]
resources :roles, only: %i[index destroy]
end
#########################

View File

@ -96,6 +96,27 @@ private
$$;
SQL
func :ensure_superuser_has_related_user, <<~SQL
() RETURNS trigger LANGUAGE plpgsql AS
$$
DECLARE
user record;
BEGIN
IF NOT NEW.superuser THEN
RETURN NEW;
END IF;
SELECT * FROM users INTO user WHERE users.account_id = NEW.id;
IF user IS NULL THEN
RAISE EXCEPTION 'does not have related user';
END IF;
RETURN NEW;
END;
$$
SQL
func :ensure_contact_list_id_remains_unchanged, <<~SQL
() RETURNS trigger LANGUAGE plpgsql AS
$$
@ -234,6 +255,8 @@ private
t.string :public_name
t.text :biography
t.boolean :superuser, null: false, default: false
t.references :person, index: { unique: true }, foreign_key: true
t.references :contact_list,
@ -291,26 +314,6 @@ private
t.index :unlock_token, unique: true
end
create_table :roles do |t|
t.timestamps null: false
t.string :name, null: false
t.references :resource, polymorphic: true
t.index %i[name resource_type resource_id], unique: true
end
create_table :account_roles do |t|
t.timestamps null: false
t.references :account, null: false, index: true, foreign_key: true
t.references :role, null: false, index: true, foreign_key: true
t.datetime :deleted_at
t.datetime :expires_at
end
create_table :user_omniauths do |t|
t.timestamps null: false
@ -494,6 +497,22 @@ private
end
def change_triggers
reversible do |dir|
dir.down do
execute 'DROP TRIGGER ensure_superuser_has_related_user ON accounts;'
end
dir.up do
execute <<~SQL
CREATE TRIGGER ensure_superuser_has_related_user
BEFORE INSERT OR UPDATE
ON accounts
FOR EACH ROW
EXECUTE PROCEDURE ensure_superuser_has_related_user();
SQL
end
end
reversible do |dir|
dir.down do
execute <<~SQL

View File

@ -40,7 +40,7 @@ CSV.foreach(
end
Rails.application.settings(:superuser).tap do |config|
User.where(email: config[:email]).first_or_create! do |new_user|
user = User.where(email: config[:email]).first_or_create! do |new_user|
new_user.password = config[:password]
new_user.confirmed_at = Time.zone.now
new_user.account = Account.create!(
@ -48,5 +48,7 @@ Rails.application.settings(:superuser).tap do |config|
public_name: config[:public_name],
biography: config[:biography],
)
end.account.add_role :superuser
end
user.account.update! superuser: true
end

View File

@ -136,6 +136,31 @@ END;
$$;
--
-- Name: ensure_superuser_has_related_user(); Type: FUNCTION; Schema: public; Owner: -
--
CREATE FUNCTION public.ensure_superuser_has_related_user() RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
user record;
BEGIN
IF NOT NEW.superuser THEN
RETURN NEW;
END IF;
SELECT * FROM users INTO user WHERE users.account_id = NEW.id;
IF user IS NULL THEN
RAISE EXCEPTION 'does not have related user';
END IF;
RETURN NEW;
END;
$$;
--
-- Name: is_good_big_text(text); Type: FUNCTION; Schema: public; Owner: -
--
@ -219,40 +244,6 @@ SET default_tablespace = '';
SET default_with_oids = false;
--
-- Name: account_roles; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.account_roles (
id bigint NOT NULL,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL,
account_id bigint NOT NULL,
role_id bigint NOT NULL,
deleted_at timestamp without time zone,
expires_at timestamp without time zone
);
--
-- Name: account_roles_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE public.account_roles_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: account_roles_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE public.account_roles_id_seq OWNED BY public.account_roles.id;
--
-- Name: accounts; Type: TABLE; Schema: public; Owner: -
--
@ -265,6 +256,7 @@ CREATE TABLE public.accounts (
nickname character varying NOT NULL,
public_name character varying,
biography text,
superuser boolean DEFAULT false NOT NULL,
person_id bigint,
contact_list_id bigint NOT NULL,
CONSTRAINT biography CHECK (((biography IS NULL) OR public.is_good_big_text(biography))),
@ -727,39 +719,6 @@ CREATE SEQUENCE public.relationships_id_seq
ALTER SEQUENCE public.relationships_id_seq OWNED BY public.relationships.id;
--
-- Name: roles; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.roles (
id bigint NOT NULL,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL,
name character varying NOT NULL,
resource_type character varying,
resource_id bigint
);
--
-- Name: roles_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE public.roles_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: roles_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE public.roles_id_seq OWNED BY public.roles.id;
--
-- Name: schema_migrations; Type: TABLE; Schema: public; Owner: -
--
@ -851,13 +810,6 @@ CREATE SEQUENCE public.users_id_seq
ALTER SEQUENCE public.users_id_seq OWNED BY public.users.id;
--
-- Name: account_roles id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.account_roles ALTER COLUMN id SET DEFAULT nextval('public.account_roles_id_seq'::regclass);
--
-- Name: accounts id; Type: DEFAULT; Schema: public; Owner: -
--
@ -942,13 +894,6 @@ ALTER TABLE ONLY public.regional_offices ALTER COLUMN id SET DEFAULT nextval('pu
ALTER TABLE ONLY public.relationships ALTER COLUMN id SET DEFAULT nextval('public.relationships_id_seq'::regclass);
--
-- Name: roles id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.roles ALTER COLUMN id SET DEFAULT nextval('public.roles_id_seq'::regclass);
--
-- Name: user_omniauths id; Type: DEFAULT; Schema: public; Owner: -
--
@ -963,14 +908,6 @@ ALTER TABLE ONLY public.user_omniauths ALTER COLUMN id SET DEFAULT nextval('publ
ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass);
--
-- Name: account_roles account_roles_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.account_roles
ADD CONSTRAINT account_roles_pkey PRIMARY KEY (id);
--
-- Name: accounts accounts_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@ -1075,14 +1012,6 @@ ALTER TABLE ONLY public.relationships
ADD CONSTRAINT relationships_pkey PRIMARY KEY (id);
--
-- Name: roles roles_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.roles
ADD CONSTRAINT roles_pkey PRIMARY KEY (id);
--
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@ -1107,20 +1036,6 @@ ALTER TABLE ONLY public.users
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
--
-- Name: index_account_roles_on_account_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_account_roles_on_account_id ON public.account_roles USING btree (account_id);
--
-- Name: index_account_roles_on_role_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_account_roles_on_role_id ON public.account_roles USING btree (role_id);
--
-- Name: index_accounts_on_contact_list_id; Type: INDEX; Schema: public; Owner: -
--
@ -1317,20 +1232,6 @@ CREATE INDEX index_relationships_on_role ON public.relationships USING btree (ro
CREATE INDEX index_relationships_on_status ON public.relationships USING btree (status);
--
-- Name: index_roles_on_name_and_resource_type_and_resource_id; Type: INDEX; Schema: public; Owner: -
--
CREATE UNIQUE INDEX index_roles_on_name_and_resource_type_and_resource_id ON public.roles USING btree (name, resource_type, resource_id);
--
-- Name: index_roles_on_resource_type_and_resource_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_roles_on_resource_type_and_resource_id ON public.roles USING btree (resource_type, resource_id);
--
-- Name: index_user_omniauths_on_remote_id_and_provider; Type: INDEX; Schema: public; Owner: -
--
@ -1394,6 +1295,13 @@ CREATE TRIGGER ensure_contact_list_id_matches_related_person BEFORE INSERT OR UP
CREATE TRIGGER ensure_contact_list_id_remains_unchanged BEFORE UPDATE OF contact_list_id ON public.people FOR EACH ROW EXECUTE PROCEDURE public.ensure_contact_list_id_remains_unchanged();
--
-- Name: accounts ensure_superuser_has_related_user; Type: TRIGGER; Schema: public; Owner: -
--
CREATE TRIGGER ensure_superuser_has_related_user BEFORE INSERT OR UPDATE ON public.accounts FOR EACH ROW EXECUTE PROCEDURE public.ensure_superuser_has_related_user();
--
-- Name: relationships fk_rails_100235139c; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@ -1466,14 +1374,6 @@ ALTER TABLE ONLY public.contacts
ADD CONSTRAINT fk_rails_8dffd7a589 FOREIGN KEY (contact_network_id) REFERENCES public.contact_networks(id);
--
-- Name: account_roles fk_rails_a85be4ccfd; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.account_roles
ADD CONSTRAINT fk_rails_a85be4ccfd FOREIGN KEY (account_id) REFERENCES public.accounts(id);
--
-- Name: person_comments fk_rails_a9c7b4ae11; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@ -1514,14 +1414,6 @@ ALTER TABLE ONLY public.contacts
ADD CONSTRAINT fk_rails_dd2a5400cf FOREIGN KEY (contact_list_id) REFERENCES public.contact_lists(id);
--
-- Name: account_roles fk_rails_f48937287f; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.account_roles
ADD CONSTRAINT fk_rails_f48937287f FOREIGN KEY (role_id) REFERENCES public.roles(id);
--
-- PostgreSQL database dump complete
--

View File

@ -15,8 +15,6 @@ FactoryBot.define do
end
factory :superuser_account, parent: :personal_account do
after :create do |account, _evaluator|
account.add_role :superuser
end
superuser { true }
end
end

View File

@ -1,7 +0,0 @@
# frozen_string_literal: true
FactoryBot.define do
factory :role do
name { 'superuser' }
end
end

View File

@ -1,10 +0,0 @@
Feature: Roles
Background:
Given I am signed in as superuser
Scenario:
When I visit "/settings/roles"
Then I see text "Суперпользователь"
When I click the button "Отозвать"
Then I do not see text "Суперпользователь"

View File

@ -1,55 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe AccountRole do
pending '.active'
pending '.not_deleted'
pending '.not_expired'
describe '#account' do
it { is_expected.to belong_to :account }
end
describe '#role' do
it { is_expected.to belong_to :role }
end
describe '#deleted_at' do
def allow_value(*)
super.for :deleted_at
end
it { is_expected.to allow_value nil }
it { is_expected.to allow_value Time.zone.now }
it { is_expected.to allow_value Faker::Time.backward.utc }
it { is_expected.to allow_value 1.minute.ago }
it { is_expected.to allow_value 1.hour.ago }
it { is_expected.to allow_value 1.day.ago }
it { is_expected.not_to allow_value Faker::Time.forward.utc + 1.minute }
it { is_expected.not_to allow_value 1.minute.from_now }
it { is_expected.not_to allow_value 1.hour.from_now }
it { is_expected.not_to allow_value 1.day.from_now }
end
describe '#expires_at' do
def allow_value(*)
super.for :expires_at
end
it { is_expected.to allow_value nil }
it { is_expected.to allow_value Time.zone.now }
it { is_expected.to allow_value Faker::Time.backward.utc }
it { is_expected.to allow_value 1.second.ago }
it { is_expected.to allow_value 1.hour.ago }
it { is_expected.to allow_value 1.day.ago }
it { is_expected.to allow_value Faker::Time.forward.utc + 1.minute }
it { is_expected.to allow_value 1.minute.from_now }
it { is_expected.to allow_value 1.hour.from_now }
it { is_expected.to allow_value 1.day.from_now }
end
end

View File

@ -15,23 +15,6 @@ RSpec.describe Account do
end
end
describe '#account_roles' do
it do
is_expected.to \
have_many(:account_roles)
.inverse_of(:account)
.dependent(:restrict_with_exception)
end
end
describe '#roles' do
it do
is_expected.to \
have_many(:roles)
.through(:account_roles)
end
end
describe '#user' do
it do
is_expected.to \
@ -189,179 +172,4 @@ RSpec.describe Account do
end
end
end
describe '#roles' do
subject { create :usual_account }
let(:role) { subject.add_role :superuser }
context 'when role is added twice' do
before do
AccountRole.create! account: subject, role: role
end
specify do
expect(subject.roles).to eq [role]
end
end
end
describe '#has_role?' do
subject { create :usual_account }
let(:role) { subject.add_role :superuser }
let!(:account_role) { role.account_roles.last }
let(:result) { subject.has_role? :superuser }
specify do
expect(result).to eq true
end
context 'after role is removed' do
before do
subject.remove_role :superuser
end
specify do
expect(result).to eq false
end
end
context 'before role expires' do
before do
account_role.update! expires_at: 2.seconds.from_now
end
specify do
expect(result).to eq true
end
end
context 'before role expires' do
before do
account_role.update! expires_at: Faker::Time.forward
end
specify do
expect(result).to eq true
end
end
context 'after role expires' do
before do
account_role.update! expires_at: 1.second.ago
end
specify do
expect(result).to eq false
end
end
context 'after role expires' do
before do
account_role.update! expires_at: Faker::Time.backward
end
specify do
expect(result).to eq false
end
end
end
describe '#add_role' do
subject { create :usual_account }
let(:result) { subject.add_role :superuser }
let(:account_role) { result; AccountRole.last }
specify do
expect { result }.to change { subject.roles.reload.count }.by(1)
end
specify do
expect { result }.to change { subject.account_roles.reload.count }.by(1)
end
specify do
expect { result }.to change { Role.count }.by(1)
end
specify do
expect { result }.to change { AccountRole.count }.by(1)
end
specify do
expect(account_role.account).to eq subject
end
specify do
expect(account_role.role).to eq result
end
context 'to guest account' do
subject { create :guest_account }
specify do
expect { result }.to \
raise_error RuntimeError, 'can not add role to guest account'
end
specify do
expect { result rescue nil }.not_to(
change { subject.roles.reload.count },
)
end
end
end
describe '#remove_role' do
subject { create :usual_account }
let(:role) { subject.add_role :superuser }
let!(:account_role) { role.account_roles.last }
let(:result) { subject.remove_role :superuser }
specify do
expect { result }.to change { subject.roles.reload.count }.by(-1)
end
specify do
expect { result }.to change { subject.account_roles.reload.count }.by(-1)
end
specify do
expect { result }.to change { role.accounts.reload.count }.by(-1)
end
specify do
expect { result }.to change { role.account_roles.reload.count }.by(-1)
end
specify do
expect { result }.not_to(change { Role.count })
end
specify do
expect { result }.not_to(change { AccountRole.count })
end
specify do
expect { result }.not_to \
change { account_role.reload.account }.from(subject)
end
specify do
expect { result }.not_to change { account_role.reload.role }.from(role)
end
specify do
expect { result }.to change { account_role.reload.deleted_at }.from(nil)
expect(account_role.deleted_at).to be_within(10).of(Time.zone.now)
end
end
end

View File

@ -1,40 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Role do
subject { create :role }
pending '.make!'
pending '#human_name'
pending '#human_resource'
describe '#account_roles' do
it do
is_expected.to \
have_many(:account_roles)
.inverse_of(:role)
.dependent(:restrict_with_exception)
end
end
describe '#accounts' do
it do
is_expected.to \
have_many(:accounts)
.through(:account_roles)
end
end
describe '#name' do
def allow_value(*)
super.for :name
end
it { is_expected.to validate_presence_of :name }
it { is_expected.not_to allow_value 'foobar' }
it { is_expected.to allow_value 'superuser' }
end
end

View File

@ -1,7 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Settings::RolePolicy do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,34 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'DELETE /settings/roles/:id' do
let!(:role) { current_account.add_role :superuser }
before do
sign_in current_account.user if current_account&.user
end
def make_request
delete "/settings/roles/#{role.id}"
end
for_account_types :usual, :superuser do
specify do
expect { make_request }.to \
change { current_account.roles.reload.count }.by(-1)
end
specify do
expect { make_request }.not_to(change { AccountRole.count })
end
context 'after request' do
before { make_request }
specify do
expect(response).to redirect_to settings_roles_url
end
end
end
end

View File

@ -1,22 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'GET /settings/roles' do
before do
sign_in current_account.user if current_account&.user
get '/settings/roles'
end
for_account_types nil, :guest do
specify do
expect(response).to have_http_status :forbidden
end
end
for_account_types :usual, :superuser do
specify do
expect(response).to have_http_status :ok
end
end
end