Skip to content

Commit

Permalink
add tests for permissions rake task
Browse files Browse the repository at this point in the history
  • Loading branch information
ezekg committed Jul 24, 2023
1 parent 7f1bc88 commit f01daaf
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 13 deletions.
3 changes: 2 additions & 1 deletion app/models/concerns/permissible.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ def can?(*actions)
actual.size == expected.size
end
end
alias_method :permissions?, :can?
alias_method :permissions?, :can?
alias_method :has_permissions?, :can?

##
# cannot? returns true if the user does not have all provided permissions.
Expand Down
26 changes: 14 additions & 12 deletions lib/tasks/keygen/permissions.rake
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,33 @@ namespace :keygen do

model = args[:type].to_s.classify.safe_constantize

# Split args up into ID and permission buckets
ids,
permissions,
* = args.extras.chunk { Permission::ALL_PERMISSIONS.include?(_1) }
.collect { _2 }
# Split args up into ID and permission buckets.
new_permissions,
record_ids = args.extras.flatten.partition {
Permission::ALL_PERMISSIONS.include?(_1)
}

records = model.includes(:account, role: { role_permissions: :permission })
.where(id: ids)
.where(id: record_ids)

records.find_each(batch_size:) do |record, i|
# NOTE(ezekg) Use preloaded permissions to save on superfluous queries.
records.find_each(batch_size:) do |record|
# Use preloaded permissions to save on superfluous queries.
prev_permissions = record.role_permissions.map { _1.permission.action }

unless record.default_permissions?(except: permissions, with: prev_permissions)
# We only want to add new permissions to records that have the default
# permission set, i.e. not to records with a custom permission set.
unless record.default_permissions?(except: new_permissions, with: prev_permissions)
Keygen.logger.info { "Skipping #{record.id}..." }

next
end

next_permissions = prev_permissions + (permissions & record.allowed_permissions)
next_permissions = prev_permissions + (new_permissions & record.allowed_permissions)

if next_permissions.any?
new_permissions = next_permissions - prev_permissions
diff_permissions = next_permissions - prev_permissions

Keygen.logger.info { "Adding #{new_permissions.join(',')} permissions to #{record.id}..." }
Keygen.logger.info { "Adding #{diff_permissions.join(',')} permissions to #{record.id}..." }

record.update!(
permissions: next_permissions,
Expand Down
8 changes: 8 additions & 0 deletions spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
config.include TimeHelper
config.include EnvHelper
config.include KeygenHelper
config.include TaskHelper

# # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
# config.fixture_path = "#{::Rails.root}/spec/fixtures"
Expand Down Expand Up @@ -112,4 +113,11 @@
Keygen::EE::LicenseFile.reset!
Keygen::EE::License.reset!
end

# Load rake tasks
config.before type: :task do
require 'rake'

Rails.application.load_tasks
end
end
46 changes: 46 additions & 0 deletions spec/support/helpers/task_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

require 'rake'

module TaskHelper
module WorldMethods
def described_task = self.class.metadata[:description_args].first
def run_task(name, *args, &)
task = Rake::Task[name]

# Ensure task is re-enabled, as Rake tasks are disabled by default
# after running once within a process.
task.reenable

task.invoke(*args)

if block_given?
instance_exec(&)
end
end
end

module ScenarioMethods
def described_task = metadata[:description_args].first
def with_task(name, *args, &)
context "with #{name} Rake task" do
let(:task) {
task = Rake::Task[name]

# Ensure task is re-enabled, as Rake tasks are disabled by default
# after running once within a process.
task.reenable

task
}

instance_exec(&)
end
end
end

def self.included(klass)
klass.include WorldMethods
klass.extend ScenarioMethods
end
end
72 changes: 72 additions & 0 deletions spec/tasks/keygen/permissions_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# frozen_string_literal: true

require 'rails_helper'
require 'spec_helper'

describe 'keygen:permissions:add', type: :task do
let(:account) { create(:account) }

it 'should add permissions to licenses' do
licenses = create_list(:license, 5,
permissions: License.default_permissions - %w[package.read],
account:,
)

run_task described_task, :license, licenses.first.id, licenses.third.id, 'package.read' do
expect(licenses.first).to have_permissions 'package.read'
expect(licenses.second).to_not have_permissions 'package.read'
expect(licenses.third).to have_permissions 'package.read'
expect(licenses.fourth).to_not have_permissions 'package.read'
expect(licenses.fifth).to_not have_permissions 'package.read'
end
end

it 'should add permissions to licenses with default permissions' do
licenses = create_list(:license, 5,
permissions: License.default_permissions - %w[package.read],
account:,
)

run_task described_task, :license, *licenses.collect(&:id), 'package.read' do
licenses.each do |license|
expect(license).to have_permissions 'package.read'
end
end
end

it 'should not add permissions to licenses with custom permissions' do
licenses = create_list(:license, 5,
permissions: %w[license.validate license.read],
account:,
)

run_task described_task, :license, *licenses.collect(&:id), 'machine.create' do
licenses.each do |license|
expect(license).to_not have_permissions 'machine.create'
end
end
end

it 'should not add permissions to licenses that are not allowed' do
licenses = create_list(:license, 5,
permissions: License.default_permissions,
account:,
)

run_task described_task, :license, *licenses.collect(&:id), 'license.create' do
licenses.each do |license|
expect(license).to_not have_permissions 'license.create'
end
end
end

it 'should raise for model without role permissions' do
tokens = create_list(:token, 5,
permissions: License.default_permissions,
account:,
)

expect { run_task described_task, :token, *tokens.collect(&:id), 'product.create' }
.to raise_error ActiveRecord::AssociationNotFoundError
end
end

0 comments on commit f01daaf

Please sign in to comment.