Class: CurrentScope::RolesController

Inherits:
ApplicationController show all
Defined in:
app/controllers/current_scope/roles_controller.rb

Constant Summary collapse

ADD_LIMIT =

Who holds this role — the role-side complement to the subjects page. Org-wide holders (this role IS their one org-wide role) and per-record scoped holders, plus a capped list of subjects to add from here.

100

Instance Method Summary collapse

Instance Method Details

#createObject



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'app/controllers/current_scope/roles_controller.rb', line 11

def create
  @role = Role.new(role_params)
  saved = false
  Role.transaction do
    saved = @role.save
    # Fold the initial permission set into the create event — no separate
    # grid-diff event for a brand-new role.
    if saved
      Event.record!(event: "role.created", target: @role,
                    details: { name: @role.name, full_access: @role.full_access?,
                               permission_keys: @role.permission_keys })
    end
  end

  if saved
    redirect_to edit_role_path(@role), notice: "Role created."
  else
    render :new, status: :unprocessable_entity
  end
end

#destroyObject



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'app/controllers/current_scope/roles_controller.rb', line 73

def destroy
  role = Role.find(params[:id])

  if last_full_access?(role)
    redirect_to roles_path,
                alert: "Refusing to delete the last full-access role — it would lock everyone out of this UI."
    return
  end

  # Snapshot the cascade BEFORE destroy! — dependent: :destroy takes the
  # assignments with the role, so they can't be read afterwards.
  org_removed = role.role_assignments.includes(:subject).to_a
  scoped_revoked = role.scoped_role_assignments.includes(:subject, :resource).to_a

  Role.transaction do
    role.destroy!
    Event.record!(event: "role.deleted", target: role, details: { name: role.name })
    org_removed.each do |a|
      Event.record!(event: "org_role.removed", target: a.subject, details: { role: role.name })
    end
    scoped_revoked.each do |a|
      Event.record!(event: "scoped_role.revoked", target: a.subject,
                    details: { role: role.name, resource: helpers.current_scope_label(a.resource) })
    end
  end
  redirect_to roles_path, notice: "Role deleted."
end

#editObject



32
33
34
# File 'app/controllers/current_scope/roles_controller.rb', line 32

def edit
  @role = Role.find(params[:id])
end

#indexObject



3
4
5
# File 'app/controllers/current_scope/roles_controller.rb', line 3

def index
  @roles = Role.order(:name)
end

#membersObject



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'app/controllers/current_scope/roles_controller.rb', line 41

def members
  @role = Role.find(params[:id])
  # No polymorphic includes: eager-loading a stale/renamed subject_type or
  # resource_type raises NameError. Lazy-load per row and label defensively
  # in the view (current_scope_holder_* helpers), like the audit ledger does.
  @org_holders = RoleAssignment.where(role: @role).to_a
  @scoped_holders = ScopedRoleAssignment.where(role: @role).to_a

  # Exclude via a subquery, not a plucked Ruby array, so a role with many
  # holders doesn't build a huge NOT IN bind list.
  held = RoleAssignment.where(role: @role, subject_type: subject_class.name).select(:subject_id)
  remaining = subject_class.where.not(id: held).order(:id)
  @candidates = remaining.limit(ADD_LIMIT).to_a
  @more_candidates = remaining.offset(ADD_LIMIT).exists?
end

#newObject



7
8
9
# File 'app/controllers/current_scope/roles_controller.rb', line 7

def new
  @role = Role.new
end

#updateObject



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'app/controllers/current_scope/roles_controller.rb', line 57

def update
  @role = Role.find(params[:id])
  previous_name = @role.name
  saved = false
  Role.transaction do
    saved = @role.update(role_params)
    record_role_update(@role, previous_name) if saved
  end

  if saved
    redirect_to roles_path, notice: "Role updated."
  else
    render :edit, status: :unprocessable_entity
  end
end