Skip to content

Commit

Permalink
Merge pull request #68 from mlibrary/soft_delete_specs
Browse files Browse the repository at this point in the history
soft delete specs and changes for grant and collection repos
  • Loading branch information
botimer authored Feb 19, 2024
2 parents 081a8f7 + d867250 commit 8800cef
Show file tree
Hide file tree
Showing 17 changed files with 547 additions and 12 deletions.
5 changes: 3 additions & 2 deletions lauth/app/repositories/collection_repo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ class CollectionRepo < ROM::Repository[:collections]
def find_by_uri(uri)
dataset = collections
.dataset
.join(locations.name.dataset, coll: :uniqueIdentifier)
.where(collections[:dlpsDeleted].is("f"))
.join(locations.name.dataset, coll: :uniqueIdentifier, dlpsDeleted: "f")
.where(Sequel.ilike(uri, locations[:dlpsPath]))
collections.class.new(dataset).to_a.first
end

def public_in_class(collection_class)
collections.where(dlpsPartlyPublic: "t", dlpsClass: collection_class).to_a
collections.where(dlpsPartlyPublic: "t", dlpsClass: collection_class, dlpsDeleted: "f").to_a
end
end
end
Expand Down
37 changes: 27 additions & 10 deletions lauth/app/repositories/grant_repo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ def for_collection_class(username:, client_ip:, collection_class:)

ds = grants
.dataset
.join(collections.name.dataset, uniqueIdentifier: :coll)
.left_join(users.name.dataset, userid: grants[:userid])
.where(grants[:dlpsDeleted].is("f"))
.join(collections.name.dataset, uniqueIdentifier: :coll, dlpsDeleted: "f")
.left_join(users.name.dataset, userid: grants[:userid], dlpsDeleted: "f")
.left_join(institution_memberships.name.dataset, inst: grants[:inst])
.left_join(group_memberships.name.dataset, user_grp: grants[:user_grp])
.left_join(Sequel.as(smallest_network, :smallest), inst: grants[:inst])
Expand Down Expand Up @@ -54,19 +55,25 @@ def for(username:, uri:, client_ip: nil)
ip = client_ip ? IPAddr.new(client_ip).to_i : nil
smallest_network = networks
.dataset
.where(dlpsDeleted: "f")
.where { dlpsAddressStart <= ip }
.where { dlpsAddressEnd >= ip }
.select_append(Sequel.as(Sequel.expr { dlpsAddressEnd - dlpsAddressStart }, :block_size))
.order(Sequel.asc(:block_size)).limit(1)

ds = grants
.dataset
.join(collections.name.dataset, uniqueIdentifier: :coll)
.join(locations.name.dataset, coll: :uniqueIdentifier)
.left_join(users.name.dataset, userid: grants[:userid])
.left_join(institution_memberships.name.dataset, inst: grants[:inst])
.left_join(group_memberships.name.dataset, user_grp: grants[:user_grp])
.left_join(Sequel.as(smallest_network, :smallest), inst: grants[:inst])
.where(grants[:dlpsDeleted].is("f"))
.join(collections.name.dataset, uniqueIdentifier: :coll, dlpsDeleted: "f")
.join(locations.name.dataset, coll: :uniqueIdentifier, dlpsDeleted: "f")
.left_join(users.name.dataset, userid: grants[:userid], dlpsDeleted: "f")
.left_join(institutions.name.dataset, uniqueIdentifier: grants[:inst], dlpsDeleted: "f")
.left_join(institution_memberships.name.dataset, inst: :uniqueIdentifier, dlpsDeleted: "f")
.left_join(Sequel.as(users.name.dataset, :inst_users), userid: :userid, dlpsDeleted: "f")
.left_join(groups.name.dataset, uniqueIdentifier: grants[:user_grp], dlpsDeleted: "f")
.left_join(group_memberships.name.dataset, user_grp: :uniqueIdentifier, dlpsDeleted: "f")
.left_join(Sequel.as(users.name.dataset, :group_users), userid: :userid, dlpsDeleted: "f")
.left_join(Sequel.as(smallest_network, :smallest), inst: institutions[:uniqueIdentifier])
.where(Sequel.ilike(uri, locations[:dlpsPath]))
.where(
Sequel.|(
Expand All @@ -75,11 +82,13 @@ def for(username:, uri:, client_ip: nil)
{users[:userid] => username}
),
Sequel.&(
Sequel.~(institution_memberships[:userid] => nil),
Sequel.~(institutions[:uniqueIdentifier] => nil),
Sequel.~(Sequel[:inst_users][:userid] => nil),
{institution_memberships[:userid] => username}
),
Sequel.&(
Sequel.~(group_memberships[:userid] => nil),
Sequel.~(groups[:uniqueIdentifier] => nil),
Sequel.~(Sequel[:group_users][:userid] => nil),
{group_memberships[:userid] => username}
),
Sequel.&(
Expand All @@ -90,6 +99,14 @@ def for(username:, uri:, client_ip: nil)
)

rel = grants.class.new(ds)
# rel.combine(:user)
# .combine(group: {group_memberships: :user})
# .node(group: :group_memberships) { |group_memberships_relation| group_memberships_relation.where(group_memberships[:dlpsDeleted] => "f").join(users.name.dataset, userid: group_memberships[:userid], dlpsDeleted: "f") }
# .combine(institution: {institution_memberships: :user})
# .node(institution: :institution_memberships) { |institution_memberships_relation| institution_memberships_relation.where(institution_memberships[:dlpsDeleted] => "f").join(users.name.dataset, userid: institution_memberships[:userid], dlpsDeleted: "f") }
# .combine(collection: :locations)
# .node(collection: :locations) { |locations_relation| locations_relation.where(locations[:dlpsDeleted] => "f") }
# .to_a
rel.combine(:user, collections: :locations, institutions: {institution_memberships: :users}).to_a
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
RSpec.describe "Soft Delete Collections#find_by_uri", type: :database do
subject(:repo) { Lauth::Repositories::CollectionRepo.new }

describe "#find_by_uri" do
it "finds the collection for the given location path" do
collection = Lauth::Fab::Collection.create
Factory[:location, dlpsPath: "/cool/path%", collection: collection]

found = repo.find_by_uri("/cool/path")

expect(found.uniqueIdentifier).to eq collection.uniqueIdentifier
end

it "does NOT find the soft deleted collection for the given location path" do
collection = Lauth::Fab::Collection.create(dlpsDeleted: "t")
Factory[:location, dlpsPath: "/cool/path%", collection: collection]

found = repo.find_by_uri("/cool/path")

expect(found).to eq nil
end

it "does NOT find the collection with a soft deleted location for the given location path" do
collection = Lauth::Fab::Collection.create
Factory[:location, :soft_deleted, dlpsPath: "/cool/path%", collection: collection]

found = repo.find_by_uri("/cool/path")

expect(found).to eq nil
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
RSpec.describe "Soft Delete Collections#public_in_class", type: :database do
subject(:repo) { Lauth::Repositories::CollectionRepo.new }

describe "#public_in_class" do
it "returns public collections that match the class" do
public_match = Factory[:collection, dlpsClass: "foo", dlpsPartlyPublic: "t"]
Factory[:collection, dlpsClass: "foo", dlpsPartlyPublic: "f"] # match, private
Factory[:collection, dlpsClass: "bar", dlpsPartlyPublic: "t"] # miss, public

expect(repo.public_in_class("foo").map(&:uniqueIdentifier))
.to contain_exactly public_match.uniqueIdentifier
end

it "does NOT return public collections that match the soft deleted class" do
_public_match = Factory[:collection, :soft_deleted, dlpsClass: "foo", dlpsPartlyPublic: "t"]
Factory[:collection, dlpsClass: "foo", dlpsPartlyPublic: "f"] # match, private
Factory[:collection, dlpsClass: "bar", dlpsPartlyPublic: "t"] # miss, public

expect(repo.public_in_class("foo")).to be_empty
end
end
end
141 changes: 141 additions & 0 deletions lauth/spec/repositories/soft_delete/grants_for_client_ip_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
RSpec.describe "Soft Delete Grants#for Client IP", type: :database do
subject(:grants) { repo.for(username: "", uri: "/restricted-by-client-ip/", client_ip: client_ip) }

let(:repo) { Lauth::Repositories::GrantRepo.new }
let(:collection) { Factory[:collection, :restricted_by_client_ip] }
let(:institution) { Factory[:institution] }
let(:grant) { Factory[:grant, :for_institution, institution: institution, collection: collection] }

before do
repo
collection
institution
grant
end

describe "(allow,deny) given a denied enclave within an allowed network" do
let(:client_ip) { "10.1.6.3" }
let(:deny_deleted) { "f" }

before do
create_network("allow", "10.1.6.0/24")
create_network("deny", "10.1.6.2/31", deny_deleted)
end

it "finds no grants" do
expect(grants).to be_empty
end

context "when deny network is soft deleted" do
let(:deny_deleted) { "t" }

it "finds the grant" do
expect(grants.map(&:uniqueIdentifier)).to contain_exactly(grant.uniqueIdentifier)
end

context "when collection is soft deleted" do
let(:collection) { Factory[:collection, :restricted_by_client_ip, :soft_deleted] }

it "finds no grants" do
expect(grants).to be_empty
end
end

context "when collection location is soft deleted" do
let(:collection) { Factory[:collection, :restricted_by_client_ip_location_soft_deleted] }

it "finds no grants" do
expect(grants).to be_empty
end
end

context "when institution is soft deleted" do
let(:institution) { Factory[:institution, :soft_deleted] }

it "finds no grants" do
expect(grants).to be_empty
end
end

context "when grant is soft deleted" do
let(:grant) { Factory[:grant, :for_institution, :soft_deleted, institution: institution, collection: collection] }

it "finds no grants" do
expect(grants).to be_empty
end
end
end
end

describe "(deny,allow) given an allowed enclave within a denied network" do
let(:client_ip) { "10.1.7.14" }
let(:allowed_deleted) { "f" }

before do
create_network("deny", "10.1.7.0/24")
create_network("allow", "10.1.7.8/29", allowed_deleted)
end

it "finds the grant" do
expect(grants.map(&:uniqueIdentifier)).to contain_exactly(grant.uniqueIdentifier)
end

context "when allowed network is soft deleted" do
let(:allowed_deleted) { "t" }

it "finds no grants" do
expect(grants).to be_empty
end
end

context "when collection is soft deleted" do
let(:collection) { Factory[:collection, :restricted_by_client_ip, :soft_deleted] }

it "finds no grants" do
expect(grants).to be_empty
end
end

context "when collection location is soft deleted" do
let(:collection) { Factory[:collection, :restricted_by_client_ip_location_soft_deleted] }

it "finds no grants" do
expect(grants).to be_empty
end
end

context "when institution is soft deleted" do
let(:institution) { Factory[:institution, :soft_deleted] }

it "finds no grants" do
expect(grants).to be_empty
end
end

context "when grant is soft deleted" do
let(:grant) { Factory[:grant, :for_institution, :soft_deleted, institution: institution, collection: collection] }

it "finds no grants" do
expect(grants).to be_empty
end
end
end

private

# Convenience for building networks.
# Requires 'institution' be set in a let block.
# @param access [String] Either 'allow' or 'deny'
# @param cidr [String] A IPv4 CIDR range.
def create_network(access, cidr, deleted = "f")
ip_range = IPAddr.new(cidr)
Factory[
:network, :for_institution, institution: institution,
dlpsAccessSwitch: access,
dlpsCIDRAddress: cidr,
dlpsAddressStart: ip_range.to_range.first.to_i,
dlpsAddressEnd: ip_range.to_range.last.to_i,
dlpsDeleted: deleted
]
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
RSpec.describe "Soft Delete Grants#for_collection_class", type: :database do
subject(:grants) { repo.for_collection_class(username: "lauth-allowed", collection_class: "same-class", client_ip: "1.2.3.4") }

let(:repo) { Lauth::Repositories::GrantRepo.new }
let(:collection_a) { Factory[:collection, :restricted_by_username, dlpsClass: "same-class"] }
let(:collection_b) { Factory[:collection, dlpsClass: "same-class"] }
let(:individual) { Factory[:user, userid: "lauth-allowed"] }
let(:grant_a) { Factory[:grant, :for_user, user: individual, collection: collection_a] }
let(:grant_b) { Factory[:grant, :for_user, user: individual, collection: collection_b] }

before do
repo
collection_a
collection_b
individual
grant_a
grant_b
end

it "finds the grants" do
expect(grants.map(&:uniqueIdentifier)).to contain_exactly grant_a.uniqueIdentifier, grant_b.uniqueIdentifier
end

context "when collection_a is soft deleted" do
let(:collection_a) { Factory[:collection, :restricted_by_username, :soft_deleted, dlpsClass: "same-class"] }

it "finds only grant_b" do
expect(grants.map(&:uniqueIdentifier)).to contain_exactly grant_b.uniqueIdentifier
end
end

xcontext "when collection_a location is soft deleted" do
let(:collection_a) { Factory[:collection, :restricted_by_username_location_soft_deleted, dlpsClass: "same-class"] }

it "finds only grant_b" do
expect(grants.map(&:uniqueIdentifier)).to contain_exactly grant_b.uniqueIdentifier
end
end

context "when collection_b is soft deleted" do
let(:collection_b) { Factory[:collection, :soft_deleted, dlpsClass: "same-class"] }

it "finds only grant_a" do
expect(grants.map(&:uniqueIdentifier)).to contain_exactly grant_a.uniqueIdentifier
end
end

xcontext "when collection_b location is soft deleted" do
let(:collection_b) { Factory[:collection, :location_soft_deleted, dlpsClass: "same-class"] }

it "finds only grant_a" do
expect(grants.map(&:uniqueIdentifier)).to contain_exactly grant_a.uniqueIdentifier
end
end

context "when individual is soft deleted" do
let(:individual) { Factory[:user, :soft_deleted, userid: "lauth-allowed"] }

it "finds no grants" do
expect(grants).to be_empty
end
end

context "when grant_a is soft deleted" do
let(:grant_a) { Factory[:grant, :for_user, :soft_deleted, user: individual, collection: collection_a] }

it "only finds grant_b" do
expect(grants.map(&:uniqueIdentifier)).to contain_exactly grant_b.uniqueIdentifier
end
end

context "when grant_b is soft deleted" do
let(:grant_b) { Factory[:grant, :for_user, :soft_deleted, user: individual, collection: collection_b] }

it "only finds grant_a" do
expect(grants.map(&:uniqueIdentifier)).to contain_exactly grant_a.uniqueIdentifier
end
end
end
Loading

0 comments on commit 8800cef

Please sign in to comment.