Module: Consent::PermissionMigration

Defined in:
lib/consent/permission_migration.rb

Overview

Permission migration helper module

Instance Method Summary collapse

Instance Method Details

#copy_permissions(from:, override:) ⇒ Object

Copy permissions from one existing permission into a new permission selecting with attrs would be overrided.

I.e.:

copy_permissions(
  from: { subject: :sale, action: :view },
  override: { subject: :project }
)

Parameters:

  • from (Hash)

    a hash with ‘:subject` and `:action` to select which permissions to copy

  • override (Hash)

    hash to specify which fields/values to override

Raises:

  • (ArgumentError)


19
20
21
22
23
24
25
26
27
# File 'lib/consent/permission_migration.rb', line 19

def copy_permissions(from:, override:)
  raise ArgumentError, "Subject and Action are always required" if from[:subject].blank? || from[:action].blank?

  ::Consent::Permission.to(**from).each do |permission|
    ::Consent::Permission.create!(
      permission.slice(:subject, :action, :view, :role_id).merge(override)
    )
  end
end

#grant_permission(subject:, action:, role_ids:, view: "1") ⇒ Object

Grant a permission to a collection of roles.

I.e.:

grant_permission(
  subject: :view_installer_pay_report,
  action: ProjectTask,
  role_ids: [2, 7, 140]
)

Parameters:

  • subject (symbol)

    the permission’s subject

  • action (Class, symbol)

    the permission’s action

  • role_ids (Array<Integer>)

    the collection of role_ids to grant the permission to

  • view (String, nil) (defaults to: "1")

    the view level, or access level, that the permission will be assigned at. If not specified, this will default to true (“1”)



45
46
47
48
49
50
51
52
# File 'lib/consent/permission_migration.rb', line 45

def grant_permission(subject:, action:, role_ids:, view: "1")
  role_ids.each do |role_id|
    ::Consent::Permission.create!(subject: subject,
                                  action: action,
                                  role_id: role_id,
                                  view: view)
  end
end

#remove_permission(subject:, action:, role_ids:) ⇒ Object

Removes a permission from a collection of roles.

I.e.:

remove_permission(
  subject: :view,
  action: User,
  role_ids: [78, 12]
)

Parameters:

  • subject (symbol)

    the permission’s subject

  • action (Class, symbol)

    the permission’s action

  • role_ids (Array<Integer>)

    the collection of role_ids to grant the permission to



68
69
70
71
72
73
74
75
# File 'lib/consent/permission_migration.rb', line 68

def remove_permission(subject:, action:, role_ids:)
  role_ids.each do |role_id|
    permission = ::Consent::Permission.find_by(subject: subject,
                                               action: action,
                                               role_id: role_id)
    permission.destroy!
  end
end

#update_permissions(from:, to:) ⇒ Object

Batch updates permission data

  • CAUTION *

    Updating a permission in a migration means that for some time the old permission
    
will be broken in production. So, you might lock out people between the permission
running and your code getting deployed/restarted in the webservers.

Example:
- Page A is only displayed to users that `can? :view, Candidate`
- If you're willing to rename the `view` action to be `view_candidates`
- Then you could go with a permission like this
   update_permissions(
    from: { subject: :candidate, action: :view },
    to: { action: :view_candidates }
   )
- And you'll have to change the permission check to be `can? :view_candidates, Candidate`
- When you merge your PR, then the migration will run first, and later on your code will
  reach production.
- Between that time, the page that uses that permission will be unreachable since
`can? :view, Candidate` doesn't exists anymore in the DB.

I.e.:

Renames a subject affecting all grantted permissions keeping everything else

update_permissions(
  from: { subject: :sale },
  to: { subject: :project }
)

Moves an action from a subject to another keeping the view

update_permissions(
  from: { subject: :sale, action: :perform },
  to: { subject: :project }
)

Rename an action within a subject keeping the view

update_permissions(
  from: { subject: :sale, action: :read },
  to: { action: :inspect }
)

Rename a view within a subject and action context

update_permissions(
  from: { subject: :sale, action: :read, view: :territory },
  to: { view: :department_territory }
)

Parameters:

  • from (Hash)

    a hash with ‘:subject`, `:action`, and `:view` to match the affected permissions

  • to (Hash)

    a hash with ‘:subject`, `:action`, and/or `:view` with the desired change

Raises:

  • (ArgumentError)


131
132
133
134
135
136
137
# File 'lib/consent/permission_migration.rb', line 131

def update_permissions(from:, to:)
  raise ArgumentError, "Subject is always required" if from[:subject].blank?

  ::Consent::Permission.to(**from).find_each do |permission|
    permission.update(to)
  end
end