Remove roles
This commit is contained in:
parent
5d35a21e34
commit
94ccab8a18
|
@ -51,10 +51,6 @@ Rails:
|
|||
Rails/BulkChangeTable:
|
||||
Enabled: false
|
||||
|
||||
Rails/HasAndBelongsToMany:
|
||||
Exclude:
|
||||
- 'app/models/role.rb'
|
||||
|
||||
Rails/HasManyOrHasOneDependent:
|
||||
Enabled: false
|
||||
|
||||
|
|
5
Gemfile
5
Gemfile
|
@ -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'
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
class Staff::HomePolicy < ApplicationPolicy
|
||||
def show?
|
||||
account&.is_superuser?
|
||||
account&.superuser?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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: Дата отправки подтверждения
|
||||
|
|
|
@ -7,4 +7,3 @@ en:
|
|||
settings:
|
||||
credentials: Credentials
|
||||
profile: Public profile
|
||||
roles: Roles
|
||||
|
|
|
@ -7,4 +7,3 @@ ru:
|
|||
settings:
|
||||
credentials: Данные для входа
|
||||
profile: Публичный профиль
|
||||
roles: Роли
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
en:
|
||||
roles:
|
||||
superuser: Superuser
|
|
@ -1,3 +0,0 @@
|
|||
ru:
|
||||
roles:
|
||||
superuser: Суперпользователь
|
|
@ -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
|
||||
|
|
|
@ -7,7 +7,3 @@ ru:
|
|||
Мы выступаем за свободный рынок и государственное невмешательство
|
||||
в экономику, за принцип самопринадлежности и самоценности человеческой
|
||||
личности.
|
||||
settings:
|
||||
roles:
|
||||
index:
|
||||
revoke: Отозвать
|
||||
|
|
|
@ -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
|
||||
|
||||
#########################
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
174
db/structure.sql
174
db/structure.sql
|
@ -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
|
||||
--
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :role do
|
||||
name { 'superuser' }
|
||||
end
|
||||
end
|
|
@ -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 "Суперпользователь"
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
Reference in New Issue