Skip to content

Commit

Permalink
Merge pull request #191 from mdsol/feature/distinct-accessible-objects
Browse files Browse the repository at this point in the history
[MCC-833873] Add distinct to pg function for accessible_objects
  • Loading branch information
cmcinnes-mdsol authored Nov 11, 2021
2 parents 0446706 + 2d275e2 commit 6ff77d1
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 71 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 4.0.1
* Updated PostgreSQL function `pm_accessible_objects_for_operations` to ensure uniqueness of results

## 4.0.0
* Added a PostgreSQL function for `#accessible_objects` and `#accessible_objects_for_operations` which are performance
optimized. Only supported for a single `field`, `direct_only`, and `ignore_prohibitions`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def up
RETURN QUERY EXECUTE
format(
'SELECT os.unique_identifier, array_agg(pe.%I) AS objects ' ||
'SELECT os.unique_identifier, array_agg(DISTINCT pe.%I) AS objects ' ||
'FROM ' ||
' t_operation_set_ids os_id ' ||
' JOIN t_operation_sets os ON os.operation_set_id = os_id.operation_set_id ' ||
Expand Down
2 changes: 1 addition & 1 deletion lib/policy_machine/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
class PolicyMachine
VERSION = "4.0.0"
VERSION = "4.0.1"
end
150 changes: 81 additions & 69 deletions spec/policy_machine_storage_adapters/active_record_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,11 @@
end

describe 'accessible_objects_for_operations_function' do
before do
priv_pm.add_association(color_1, creator, object_6)
priv_pm.add_association(color_2, creator, object_7)
end

it 'uses a PostgreSQL function' do
expect_any_instance_of(PolicyMachineStorageAdapter::ActiveRecord)
.to receive(:accessible_objects_for_operations_function)
Expand All @@ -755,94 +760,101 @@
)
end

context 'when there are directly accessible objects' do
before do
priv_pm.add_association(color_1, creator, object_6)
priv_pm.add_association(color_2, creator, object_7)
end
it 'returns objects accessible via each of multiple given operations' do
result = priv_pm.accessible_objects_for_operations(
user_1,
[create, paint],
direct_only: true,
ignore_prohibitions: true,
fields: [:unique_identifier]
)

it 'returns objects accessible via each of multiple given operations' do
result = priv_pm.accessible_objects_for_operations(
user_1,
[create, paint],
direct_only: true,
ignore_prohibitions: true,
fields: [:unique_identifier]
)
expect(result.keys).to contain_exactly(create.to_s, paint.to_s)
expect(result[create.to_s]).to contain_exactly('object_7', 'object_6')
expect(result[paint.to_s]).to contain_exactly('object_7', 'object_6')
end

expect(result.keys).to contain_exactly(create.to_s, paint.to_s)
expect(result[create.to_s]).to contain_exactly('object_7', 'object_6')
expect(result[paint.to_s]).to contain_exactly('object_7', 'object_6')
end
it 'can handle string operations' do
result = priv_pm.accessible_objects_for_operations(
user_1,
['create', 'paint'],
direct_only: true,
ignore_prohibitions: true,
fields: [:unique_identifier]
)

it 'can handle string operations' do
expect(result.keys).to contain_exactly('create', 'paint')
expect(result[create.to_s]).to contain_exactly('object_7', 'object_6')
expect(result[paint.to_s]).to contain_exactly('object_7', 'object_6')
end

it 'returns an empty list of objects for non-existent operations' do
result = priv_pm.accessible_objects_for_operations(
user_1,
[create, 'zagnut'],
direct_only: true,
ignore_prohibitions: true,
fields: [:unique_identifier]
)

expect(result.keys).to contain_exactly(create.to_s, 'zagnut')
expect(result[create.to_s]).to contain_exactly('object_7', 'object_6')
expect(result['zagnut']).to eq([])
end

it 'returns a unique list of objects for each operation' do
result = priv_pm.accessible_objects_for_operations(
user_1,
[create, paint],
direct_only: true,
ignore_prohibitions: true,
fields: [:type]
)

expect(result.keys).to contain_exactly('create', 'paint')
expect(result[create.to_s]).to contain_exactly('PolicyMachineStorageAdapter::ActiveRecord::Object')
expect(result[paint.to_s]).to contain_exactly('PolicyMachineStorageAdapter::ActiveRecord::Object')
end

context 'filters' do
it 'works for a single filter' do
result = priv_pm.accessible_objects_for_operations(
user_1,
['create', 'paint'],
[create, paint],
filters: {
user_attributes: { color: color_1.color }
},
direct_only: true,
ignore_prohibitions: true,
fields: [:unique_identifier]
)

expect(result.keys).to contain_exactly('create', 'paint')
expect(result[create.to_s]).to contain_exactly('object_7', 'object_6')
expect(result[paint.to_s]).to contain_exactly('object_7', 'object_6')
expect(result).to eq({
create.to_s => ['object_6'],
paint.to_s => ['object_6'],
})
end

it 'returns an empty list of objects for non-existent operations' do
it 'works for multiple filters' do
result = priv_pm.accessible_objects_for_operations(
user_1,
[create, 'zagnut'],
[create, paint],
filters: {
user_attributes: {
color: color_1.color,
unique_identifier: color_1.unique_identifier,
id: color_1.id
}
},
direct_only: true,
ignore_prohibitions: true,
fields: [:unique_identifier]
)

expect(result.keys).to contain_exactly(create.to_s, 'zagnut')
expect(result[create.to_s]).to contain_exactly('object_7', 'object_6')
expect(result['zagnut']).to eq([])
end

context 'filters' do
it 'works for a single filter' do
result = priv_pm.accessible_objects_for_operations(
user_1,
[create, paint],
filters: {
user_attributes: { color: color_1.color }
},
direct_only: true,
ignore_prohibitions: true,
fields: [:unique_identifier]
)

expect(result).to eq({
create.to_s => ['object_6'],
paint.to_s => ['object_6'],
})
end

it 'works for multiple filters' do
result = priv_pm.accessible_objects_for_operations(
user_1,
[create, paint],
filters: {
user_attributes: {
color: color_1.color,
unique_identifier: color_1.unique_identifier,
id: color_1.id
}
},
direct_only: true,
ignore_prohibitions: true,
fields: [:unique_identifier]
)

expect(result).to eq({
create.to_s => ['object_6'],
paint.to_s => ['object_6'],
})
end
expect(result).to eq({
create.to_s => ['object_6'],
paint.to_s => ['object_6'],
})
end
end
end
Expand Down

0 comments on commit 6ff77d1

Please sign in to comment.