diff --git a/lauth/Gemfile b/lauth/Gemfile index df585c72..8b3a2b8a 100644 --- a/lauth/Gemfile +++ b/lauth/Gemfile @@ -20,6 +20,8 @@ gem "rom-factory", "~> 0.11.0" gem "rom-sql", "~> 3.6" gem "mysql2" +gem "ipaddress", "~> 0.8" + group :development do gem "hanami-webconsole", "~> #{HANAMI_VERSION}" gem "guard-puma" diff --git a/lauth/Gemfile.lock b/lauth/Gemfile.lock index 7e3e96df..76eeae0f 100644 --- a/lauth/Gemfile.lock +++ b/lauth/Gemfile.lock @@ -154,6 +154,7 @@ GEM i18n (1.14.1) concurrent-ruby (~> 1.0) ice_nine (0.11.2) + ipaddress (0.8.3) json (2.6.3) language_server-protocol (3.17.0.3) lint_roller (1.1.0) @@ -298,6 +299,7 @@ DEPENDENCIES hanami-validations (~> 2.1.0.rc2) hanami-view (~> 2.1.0.rc2) hanami-webconsole (~> 2.1.0.rc2) + ipaddress (~> 0.8) mysql2 puma rack-test diff --git a/lauth/app/repositories/collection_repo.rb b/lauth/app/repositories/collection_repo.rb new file mode 100644 index 00000000..dc208aed --- /dev/null +++ b/lauth/app/repositories/collection_repo.rb @@ -0,0 +1,81 @@ +module Lauth + module Repositories + class CollectionRepo < ROM::Repository[:collections] + include Deps[container: "persistence.rom"] + struct_namespace Lauth + # auto_struct true + # commands :create, update: :by_pk, delete: :by_pk + + def index + undeleted_collections.to_a + end + + def create(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + id = document[:data][:id] + collection = undeleted_collections.where(uniqueIdentifier: id).one + return nil if collection + + if deleted_collections.where(uniqueIdentifier: id).one + deleted_collections.where(uniqueIdentifier: id).changeset(Lauth::Persistence::Changesets::CollectionUpdate, document).commit + else + undeleted_collections.changeset(Lauth::Persistence::Changesets::CollectionCreate, document).commit + end + + undeleted_collections.where(uniqueIdentifier: id).one + end + + def find(id) + undeleted_collections.where(uniqueIdentifier: id).one + end + + def find_with_locations(id) + undeleted_collections.where(uniqueIdentifier: id).combine(:locations).node(:locations) do |locations_relation| + locations_relation.where(locations[:dlpsDeleted] => "f") + end + .one + end + + def update(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + id = document[:data][:id] + collection = deleted_collections.where(uniqueIdentifier: id).one + return nil if collection + + if undeleted_collections.where(uniqueIdentifier: id).one + undeleted_collections.where(uniqueIdentifier: id).changeset(Lauth::Persistence::Changesets::CollectionUpdate, document).commit + end + + undeleted_collections.where(uniqueIdentifier: id).one + end + + def delete(id) + collection = find(id) + undeleted_collections.where(uniqueIdentifier: id).update(dlpsDeleted: "t") if collection + collection + end + + def by_request_uri(host, uri) + collections.join(locations) + .where(collections[:dlpsDeleted].is("f")) + .where(locations[:dlpsDeleted].is("f")) + .where(locations[:dlpsServer].is(host)) + .where(Sequel.ilike(uri, locations[:dlpsPath])) + .order(Sequel.function(:length, locations[:dlpsPath])) + .rename(commonName: :name) + .reverse + .to_a + end + + protected + + def undeleted_collections + collections.where(dlpsDeleted: "f") + end + + def deleted_collections + collections.where(dlpsDeleted: "t") + end + end + end +end diff --git a/lauth/app/repositories/grant_repo.rb b/lauth/app/repositories/grant_repo.rb index 8a6c18b7..01d07108 100644 --- a/lauth/app/repositories/grant_repo.rb +++ b/lauth/app/repositories/grant_repo.rb @@ -4,10 +4,6 @@ class GrantRepo < ROM::Repository[:grants] include Deps[container: "persistence.rom"] struct_namespace Lauth - def find(id) - grants.where(uniqueIdentifier: id).one - end - def for(username:, uri:, client_ip: nil) ip = client_ip ? IPAddr.new(client_ip).to_i : nil smallest_network = networks @@ -19,11 +15,16 @@ def for(username:, uri:, client_ip: nil) 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]) + .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(institution_memberships.name.dataset, inst: grants[:inst], dlpsDeleted: "f") + .left_join(institutions.name.dataset, uniqueIdentifier: institution_memberships[:inst], dlpsDeleted: "f") + .left_join(Sequel.as(users.name.dataset, :inst_users), userid: institution_memberships[:userid], dlpsDeleted: "f") + .left_join(group_memberships.name.dataset, user_grp: grants[:user_grp], dlpsDeleted: "f") + .left_join(groups.name.dataset, uniqueIdentifier: group_memberships[:user_grp], dlpsDeleted: "f") + .left_join(Sequel.as(users.name.dataset, :group_users), userid: group_memberships[:userid], dlpsDeleted: "f") .left_join(Sequel.as(smallest_network, :smallest), inst: grants[:inst]) .where(Sequel.ilike(uri, locations[:dlpsPath])) .where( @@ -33,11 +34,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.&( @@ -50,6 +53,58 @@ def for(username:, uri:, client_ip: nil) rel = grants.class.new(ds) rel.combine(:user, collections: :locations, institutions: {institution_memberships: :users}).to_a end + + def index + undeleted_grants.rename(uniqueIdentifier: :id).to_a + end + + def create(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + id = document[:data][:id] + grant = undeleted_grants.where(uniqueIdentifier: id).one + return nil if grant + + if deleted_grants.where(uniqueIdentifier: id).one + deleted_grants.where(uniqueIdentifier: id).changeset(Lauth::Persistence::Changesets::GrantUpdate, document).commit + else + undeleted_grants.changeset(Lauth::Persistence::Changesets::GrantCreate, document).commit + end + + undeleted_grants.where(uniqueIdentifier: id).rename(uniqueIdentifier: :id).one + end + + def find(id) + undeleted_grants.where(uniqueIdentifier: id).rename(uniqueIdentifier: :id).one + end + + def update(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + id = document[:data][:id] + grant = deleted_grants.where(uniqueIdentifier: id).one + return nil if grant + + if undeleted_grants.where(uniqueIdentifier: id).one + undeleted_grants.where(uniqueIdentifier: id).changeset(Lauth::Persistence::Changesets::GrantUpdate, document).commit + end + + undeleted_grants.where(uniqueIdentifier: id).rename(uniqueIdentifier: :id).one + end + + def delete(id) + grant = find(id) + undeleted_grants.where(uniqueIdentifier: id).update(dlpsDeleted: "t") if grant + grant + end + + protected + + def undeleted_grants + grants.where(dlpsDeleted: "f") + end + + def deleted_grants + grants.where(dlpsDeleted: "t") + end end end end diff --git a/lauth/app/repositories/group_membership_repo.rb b/lauth/app/repositories/group_membership_repo.rb new file mode 100644 index 00000000..e59f4e79 --- /dev/null +++ b/lauth/app/repositories/group_membership_repo.rb @@ -0,0 +1,64 @@ +module Lauth + module Repositories + class GroupMembershipRepo < ROM::Repository[:group_memberships] + include Deps[container: "persistence.rom"] + struct_namespace Lauth + # auto_struct true + # commands :create, update: :by_pk, delete: :by_pk + + def index + undeleted_group_memberships.to_a + end + + def create(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + user_id = document[:data][:attributes][:user_id] + group_id = document[:data][:attributes][:group_id] + group_membership = undeleted_group_memberships.where(userid: user_id, user_grp: group_id).one + return nil if group_membership + + if deleted_group_memberships.where(userid: user_id, user_grp: group_id).one + deleted_group_memberships.where(userid: user_id, user_grp: group_id).changeset(Lauth::Persistence::Changesets::GroupMembershipUpdate, document).commit + else + undeleted_group_memberships.changeset(Lauth::Persistence::Changesets::GroupMembershipCreate, document).commit + end + + undeleted_group_memberships.where(userid: user_id, user_grp: group_id).one + end + + def find(user_id, group_id) + undeleted_group_memberships.where(userid: user_id, user_grp: group_id).one + end + + def update(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + user_id = document[:data][:attributes][:user_id] + group_id = document[:data][:attributes][:group_id] + group_membership = deleted_group_memberships.where(userid: user_id, user_grp: group_id).one + return nil if group_membership + + if undeleted_group_memberships.where(userid: user_id, user_grp: group_id).one + undeleted_group_memberships.where(userid: user_id, user_grp: group_id).changeset(Lauth::Persistence::Changesets::GroupMembershipUpdate, document).commit + end + + undeleted_group_memberships.where(userid: user_id, user_grp: group_id).one + end + + def delete(user_id, group_id) + group_membership = find(user_id, group_id) + undeleted_group_memberships.where(userid: user_id, user_grp: group_id).update(dlpsDeleted: "t") if group_membership + group_membership + end + + protected + + def undeleted_group_memberships + group_memberships.where(dlpsDeleted: "f") + end + + def deleted_group_memberships + group_memberships.where(dlpsDeleted: "t") + end + end + end +end diff --git a/lauth/app/repositories/group_repo.rb b/lauth/app/repositories/group_repo.rb new file mode 100644 index 00000000..e7f234bc --- /dev/null +++ b/lauth/app/repositories/group_repo.rb @@ -0,0 +1,62 @@ +module Lauth + module Repositories + class GroupRepo < ROM::Repository[:groups] + include Deps[container: "persistence.rom"] + struct_namespace Lauth + # auto_struct true + # commands :create, update: :by_pk, delete: :by_pk + + def index + undeleted_groups.rename(uniqueIdentifier: :id, commonName: :name).to_a + end + + def create(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + id = document[:data][:id] + group = undeleted_groups.where(uniqueIdentifier: id).one + return nil if group + + if deleted_groups.where(uniqueIdentifier: id).one + deleted_groups.where(uniqueIdentifier: id).changeset(Lauth::Persistence::Changesets::GroupUpdate, document).commit + else + undeleted_groups.changeset(Lauth::Persistence::Changesets::GroupCreate, document).commit + end + + undeleted_groups.where(uniqueIdentifier: id).rename(uniqueIdentifier: :id, commonName: :name).one + end + + def find(id) + undeleted_groups.where(uniqueIdentifier: id).rename(uniqueIdentifier: :id, commonName: :name).one + end + + def update(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + id = document[:data][:id] + group = deleted_groups.where(uniqueIdentifier: id).one + return nil if group + + if undeleted_groups.where(uniqueIdentifier: id).one + undeleted_groups.where(uniqueIdentifier: id).changeset(Lauth::Persistence::Changesets::GroupUpdate, document).commit + end + + undeleted_groups.where(uniqueIdentifier: id).rename(uniqueIdentifier: :id, commonName: :name).one + end + + def delete(id) + group = find(id) + undeleted_groups.where(uniqueIdentifier: id).update(dlpsDeleted: "t") if group + group + end + + protected + + def undeleted_groups + groups.where(dlpsDeleted: "f") + end + + def deleted_groups + groups.where(dlpsDeleted: "t") + end + end + end +end diff --git a/lauth/app/repositories/institution_membership_repo.rb b/lauth/app/repositories/institution_membership_repo.rb new file mode 100644 index 00000000..e3bbf90d --- /dev/null +++ b/lauth/app/repositories/institution_membership_repo.rb @@ -0,0 +1,64 @@ +module Lauth + module Repositories + class InstitutionMembershipRepo < ROM::Repository[:institution_memberships] + include Deps[container: "persistence.rom"] + struct_namespace Lauth + # auto_struct true + # commands :create, update: :by_pk, delete: :by_pk + + def index + undeleted_institution_memberships.to_a + end + + def create(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + user_id = document[:data][:attributes][:user_id] + institution_id = document[:data][:attributes][:institution_id] + institution_membership = undeleted_institution_memberships.where(userid: user_id, inst: institution_id).one + return nil if institution_membership + + if deleted_institution_memberships.where(userid: user_id, inst: institution_id).one + deleted_institution_memberships.where(userid: user_id, inst: institution_id).changeset(Lauth::Persistence::Changesets::InstitutionMembershipUpdate, document).commit + else + undeleted_institution_memberships.changeset(Lauth::Persistence::Changesets::InstitutionMembershipCreate, document).commit + end + + undeleted_institution_memberships.where(userid: user_id, inst: institution_id).one + end + + def find(user_id, institution_id) + undeleted_institution_memberships.where(userid: user_id, inst: institution_id).one + end + + def update(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + user_id = document[:data][:attributes][:user_id] + institution_id = document[:data][:attributes][:institution_id] + institution_membership = deleted_institution_memberships.where(userid: user_id, inst: institution_id).one + return nil if institution_membership + + if undeleted_institution_memberships.where(userid: user_id, inst: institution_id).one + undeleted_institution_memberships.where(userid: user_id, inst: institution_id).changeset(Lauth::Persistence::Changesets::InstitutionMembershipUpdate, document).commit + end + + undeleted_institution_memberships.where(userid: user_id, inst: institution_id).one + end + + def delete(user_id, institution_id) + institution_membership = find(user_id, institution_id) + undeleted_institution_memberships.where(userid: user_id, inst: institution_id).update(dlpsDeleted: "t") if institution_membership + institution_membership + end + + protected + + def undeleted_institution_memberships + institution_memberships.where(dlpsDeleted: "f") + end + + def deleted_institution_memberships + institution_memberships.where(dlpsDeleted: "t") + end + end + end +end diff --git a/lauth/app/repositories/institution_repo.rb b/lauth/app/repositories/institution_repo.rb new file mode 100644 index 00000000..56066658 --- /dev/null +++ b/lauth/app/repositories/institution_repo.rb @@ -0,0 +1,62 @@ +module Lauth + module Repositories + class InstitutionRepo < ROM::Repository[:institutions] + include Deps[container: "persistence.rom"] + struct_namespace Lauth + # auto_struct true + # commands :create, update: :by_pk, delete: :by_pk + + def index + undeleted_institutions.rename(uniqueIdentifier: :id, organizationName: :name).to_a + end + + def create(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + id = document[:data][:id] + institution = undeleted_institutions.where(uniqueIdentifier: id).one + return nil if institution + + if deleted_institutions.where(uniqueIdentifier: id).one + deleted_institutions.where(uniqueIdentifier: id).changeset(Lauth::Persistence::Changesets::InstitutionUpdate, document).commit + else + undeleted_institutions.changeset(Lauth::Persistence::Changesets::InstitutionCreate, document).commit + end + + undeleted_institutions.where(uniqueIdentifier: id).rename(uniqueIdentifier: :id, organizationName: :name).one + end + + def find(id) + undeleted_institutions.where(uniqueIdentifier: id).rename(uniqueIdentifier: :id, organizationName: :name).one + end + + def update(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + id = document[:data][:id] + institution = deleted_institutions.where(uniqueIdentifier: id).one + return nil if institution + + if undeleted_institutions.where(uniqueIdentifier: id).one + undeleted_institutions.where(uniqueIdentifier: id).changeset(Lauth::Persistence::Changesets::InstitutionUpdate, document).commit + end + + undeleted_institutions.where(uniqueIdentifier: id).rename(uniqueIdentifier: :id, organizationName: :name).one + end + + def delete(id) + institution = find(id) + undeleted_institutions.where(uniqueIdentifier: id).update(dlpsDeleted: "t") if institution + institution + end + + protected + + def undeleted_institutions + institutions.where(dlpsDeleted: "f") + end + + def deleted_institutions + institutions.where(dlpsDeleted: "t") + end + end + end +end diff --git a/lauth/app/repositories/location_repo.rb b/lauth/app/repositories/location_repo.rb new file mode 100644 index 00000000..29ac3891 --- /dev/null +++ b/lauth/app/repositories/location_repo.rb @@ -0,0 +1,65 @@ +module Lauth + module Repositories + class LocationRepo < ROM::Repository[:locations] + include Deps[container: "persistence.rom"] + struct_namespace Lauth + # auto_struct true + # commands :create, update: :by_pk, delete: :by_pk + def index + undeleted_locations.to_a + end + + def create(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + host = document[:data][:attributes][:host] + path = document[:data][:attributes][:path] + collection = document[:data][:attributes][:collection] + location = undeleted_locations.where(dlpsServer: host, dlpsPath: path, coll: collection).one + return nil if location + + if deleted_locations.where(dlpsServer: host, dlpsPath: path, coll: collection).one + deleted_locations.where(dlpsServer: host, dlpsPath: path, coll: collection).changeset(Lauth::Persistence::Changesets::LocationUpdate, document).commit + else + undeleted_locations.changeset(Lauth::Persistence::Changesets::LocationCreate, document).commit + end + + undeleted_locations.where(dlpsServer: host, dlpsPath: path, coll: collection).one + end + + def find(host, path, collection) + undeleted_locations.where(dlpsServer: host, dlpsPath: path, coll: collection).one + end + + def update(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + host = document[:data][:attributes][:host] + path = document[:data][:attributes][:path] + collection = document[:data][:attributes][:collection] + location = deleted_locations.where(dlpsServer: host, dlpsPath: path, coll: collection).one + return nil if location + + if undeleted_locations.where(dlpsServer: host, dlpsPath: path, coll: collection).one + undeleted_locations.where(dlpsServer: host, dlpsPath: path, coll: collection).changeset(Lauth::Persistence::Changesets::LocationUpdate, document).commit + end + + undeleted_locations.where(dlpsServer: host, dlpsPath: path, coll: collection).one + end + + def delete(host, path, collection) + location = find(host, path, collection) + undeleted_locations.where(dlpsServer: host, dlpsPath: path, coll: collection).update(dlpsDeleted: "t") if location + location + end + + protected + + def undeleted_locations + locations.where(dlpsDeleted: "f") + end + + def deleted_locations + locations.where(dlpsDeleted: "t") + end + end + end +end diff --git a/lauth/app/repositories/network_repo.rb b/lauth/app/repositories/network_repo.rb new file mode 100644 index 00000000..dd052893 --- /dev/null +++ b/lauth/app/repositories/network_repo.rb @@ -0,0 +1,118 @@ +module Lauth + module Repositories + class NetworkRepo < ROM::Repository[:networks] + include Deps[container: "persistence.rom"] + struct_namespace Lauth + # auto_struct true + # commands :create, update: :by_pk, delete: :by_pk + + def include?(ip) + undeleted_networks.where { (dlpsAddressStart <= ip.to_u32) & (dlpsAddressEnd >= ip.to_u32) }.rename(uniqueIdentifier: :id, dlpsCIDRAddress: :cidr, dlpsAccessSwitch: :access, dlpsAddressStart: :minimum, dlpsAddressEnd: :maximum).to_a + end + + def index + undeleted_networks.rename(uniqueIdentifier: :id, dlpsCIDRAddress: :cidr, dlpsAccessSwitch: :access, dlpsAddressStart: :minimum, dlpsAddressEnd: :maximum).to_a + end + + def create(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + id = document[:data][:id] + network = undeleted_networks.where(uniqueIdentifier: id).one + return nil if network + + ip_address = IPAddress.parse document[:data][:attributes][:cidr] + return nil unless ip_address + + cidr = "0.0.0.0/0" + minimum = 0 + maximum = 0xFFFFFFFF + case ip_address.prefix + when 32 + cidr = ip_address.to_string + minimum = maximum = ip_address.to_u32 + when 31 + cidr = ip_address.first.to_string + minimum = ip_address.first.to_u32 + maximum = ip_address.last.to_u32 + else + cidr = ip_address.network.to_string + minimum = ip_address.network.to_u32 + maximum = ip_address.broadcast.to_u32 + end + + document[:data][:attributes][:minimum] = minimum + document[:data][:attributes][:maximum] = maximum + document[:data][:attributes][:cidr] = cidr + + if deleted_networks.where(uniqueIdentifier: id).one + deleted_networks.where(uniqueIdentifier: id).changeset(Lauth::Persistence::Changesets::NetworkUpdate, document).commit + else + undeleted_networks.changeset(Lauth::Persistence::Changesets::NetworkCreate, document).commit + end + + undeleted_networks.where(uniqueIdentifier: id).rename(uniqueIdentifier: :id, dlpsCIDRAddress: :cidr, dlpsAccessSwitch: :access, dlpsAddressStart: :minimum, dlpsAddressEnd: :maximum).one + rescue => _e + nil + end + + def find(id) + undeleted_networks.where(uniqueIdentifier: id).rename(uniqueIdentifier: :id, dlpsCIDRAddress: :cidr, dlpsAccessSwitch: :access, dlpsAddressStart: :minimum, dlpsAddressEnd: :maximum).one + end + + def update(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + id = document[:data][:id] + network = deleted_networks.where(uniqueIdentifier: id).one + return nil if network + + ip_address = IPAddress.parse document[:data][:attributes][:cidr] + return nil unless ip_address + + cidr = "0.0.0.0/0" + minimum = 0 + maximum = 0xFFFFFFFF + case ip_address.prefix + when 32 + cidr = ip_address.to_string + minimum = maximum = ip_address.to_u32 + when 31 + cidr = ip_address.first.to_string + minimum = ip_address.first.to_u32 + maximum = ip_address.last.to_u32 + else + cidr = ip_address.network.to_string + minimum = ip_address.network.to_u32 + maximum = ip_address.broadcast.to_u32 + end + + document[:data][:attributes][:minimum] = minimum + document[:data][:attributes][:maximum] = maximum + document[:data][:attributes][:cidr] = cidr + + if undeleted_networks.where(uniqueIdentifier: id).one + undeleted_networks.where(uniqueIdentifier: id).changeset(Lauth::Persistence::Changesets::NetworkUpdate, document).commit + end + + undeleted_networks.where(uniqueIdentifier: id).rename(uniqueIdentifier: :id, dlpsCIDRAddress: :cidr, dlpsAccessSwitch: :access, dlpsAddressStart: :minimum, dlpsAddressEnd: :maximum).one + rescue => _e + nil + end + + def delete(id) + network = find(id) + undeleted_networks.where(uniqueIdentifier: id).update(dlpsDeleted: "t") if network + network + end + + protected + + def undeleted_networks + networks.where(dlpsDeleted: "f") + end + + def deleted_networks + networks.where(dlpsDeleted: "t") + end + end + end +end diff --git a/lauth/app/repositories/user_repo.rb b/lauth/app/repositories/user_repo.rb new file mode 100644 index 00000000..9af6c053 --- /dev/null +++ b/lauth/app/repositories/user_repo.rb @@ -0,0 +1,62 @@ +module Lauth + module Repositories + class UserRepo < ROM::Repository[:users] + include Deps[container: "persistence.rom"] + struct_namespace Lauth + # auto_struct true + # commands :create, update: :by_pk, delete: :by_pk + + def index + undeleted_users.rename(userid: :id, userPassword: :password, surname: :name).to_a + end + + def create(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + id = document[:data][:id] + user = undeleted_users.where(userid: id).one + return nil if user + + if deleted_users.where(userid: id).one + deleted_users.where(userid: id).changeset(Lauth::Persistence::Changesets::UserUpdate, document).commit + else + undeleted_users.changeset(Lauth::Persistence::Changesets::UserCreate, document).commit + end + + undeleted_users.where(userid: id).rename(userid: :id, userPassword: :password, surname: :name).one + end + + def find(id) + undeleted_users.where(userid: id).rename(userid: :id, userPassword: :password, surname: :name).one + end + + def update(document) + document = Hanami::Utils::Hash.deep_symbolize(document) + id = document[:data][:id] + user = deleted_users.where(userid: id).one + return nil if user + + if undeleted_users.where(userid: id).one + undeleted_users.where(userid: id).changeset(Lauth::Persistence::Changesets::UserUpdate, document).commit + end + + undeleted_users.where(userid: id).rename(userid: :id, userPassword: :password, surname: :name).one + end + + def delete(id) + user = find(id) + undeleted_users.where(userid: id).update(dlpsDeleted: "t") if user + user + end + + protected + + def undeleted_users + users.where(dlpsDeleted: "f") + end + + def deleted_users + users.where(dlpsDeleted: "t") + end + end + end +end diff --git a/lauth/lib/lauth/collection.rb b/lauth/lib/lauth/collection.rb index 640a5e89..04bb2db3 100644 --- a/lauth/lib/lauth/collection.rb +++ b/lauth/lib/lauth/collection.rb @@ -1,4 +1,7 @@ module Lauth class Collection < ROM::Struct + def id + uniqueIdentifier + end end end diff --git a/lauth/lib/lauth/grant.rb b/lauth/lib/lauth/grant.rb index a149a0ad..e3c27c7e 100644 --- a/lauth/lib/lauth/grant.rb +++ b/lauth/lib/lauth/grant.rb @@ -1,4 +1,7 @@ module Lauth class Grant < ROM::Struct + def id + uniqueIdentifier + end end end diff --git a/lauth/lib/lauth/location.rb b/lauth/lib/lauth/location.rb index 5c5fec07..5946faf1 100644 --- a/lauth/lib/lauth/location.rb +++ b/lauth/lib/lauth/location.rb @@ -1,4 +1,19 @@ module Lauth class Location < ROM::Struct + def collection + coll + end + + def host + dlpsServer + end + + def path + dlpsPath + end + + def ==(other) + dlpsServer == other.host && dlpsPath == other.path + end end end diff --git a/lauth/lib/lauth/persistence/changesets/collection_create.rb b/lauth/lib/lauth/persistence/changesets/collection_create.rb new file mode 100644 index 00000000..01cbee95 --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/collection_create.rb @@ -0,0 +1,16 @@ +module Lauth + module Persistence + module Changesets + class CollectionCreate < ROM::Changeset::Create + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys id: :uniqueIdentifier, name: :commonName + deep_merge lastModifiedTime: Time.now + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/collection_update.rb b/lauth/lib/lauth/persistence/changesets/collection_update.rb new file mode 100644 index 00000000..e298aa2e --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/collection_update.rb @@ -0,0 +1,24 @@ +module Lauth + module Persistence + module Changesets + class CollectionUpdate < ROM::Changeset::Update + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys id: :uniqueIdentifier, name: :commonName + deep_merge lastModifiedTime: Time.now + end + + def clean? + false + end + + def diff? + true + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/grant_create.rb b/lauth/lib/lauth/persistence/changesets/grant_create.rb new file mode 100644 index 00000000..0f408db3 --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/grant_create.rb @@ -0,0 +1,16 @@ +module Lauth + module Persistence + module Changesets + class GrantCreate < ROM::Changeset::Create + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys id: :uniqueIdentifier + deep_merge lastModifiedTime: Time.now + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/grant_update.rb b/lauth/lib/lauth/persistence/changesets/grant_update.rb new file mode 100644 index 00000000..41221fae --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/grant_update.rb @@ -0,0 +1,24 @@ +module Lauth + module Persistence + module Changesets + class GrantUpdate < ROM::Changeset::Update + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys id: :uniqueIdentifier + deep_merge lastModifiedTime: Time.now + end + + def clean? + false + end + + def diff? + true + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/group_create.rb b/lauth/lib/lauth/persistence/changesets/group_create.rb new file mode 100644 index 00000000..2a9b01f8 --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/group_create.rb @@ -0,0 +1,16 @@ +module Lauth + module Persistence + module Changesets + class GroupCreate < ROM::Changeset::Create + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys id: :uniqueIdentifier, name: :commonName + deep_merge lastModifiedTime: Time.now + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/group_membership_create.rb b/lauth/lib/lauth/persistence/changesets/group_membership_create.rb new file mode 100644 index 00000000..8301320c --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/group_membership_create.rb @@ -0,0 +1,16 @@ +module Lauth + module Persistence + module Changesets + class GroupMembershipCreate < ROM::Changeset::Create + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys user_id: :userid, group_id: :user_grp + deep_merge lastModifiedTime: Time.now + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/group_membership_update.rb b/lauth/lib/lauth/persistence/changesets/group_membership_update.rb new file mode 100644 index 00000000..638c0025 --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/group_membership_update.rb @@ -0,0 +1,24 @@ +module Lauth + module Persistence + module Changesets + class GroupMembershipUpdate < ROM::Changeset::Update + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys user_id: :userid, group_id: :user_grp + deep_merge lastModifiedTime: Time.now + end + + def clean? + false + end + + def diff? + true + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/group_update.rb b/lauth/lib/lauth/persistence/changesets/group_update.rb new file mode 100644 index 00000000..ac8b806a --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/group_update.rb @@ -0,0 +1,24 @@ +module Lauth + module Persistence + module Changesets + class GroupUpdate < ROM::Changeset::Update + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys id: :uniqueIdentifier, name: :commonName + deep_merge lastModifiedTime: Time.now + end + + def clean? + false + end + + def diff? + true + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/institution_create.rb b/lauth/lib/lauth/persistence/changesets/institution_create.rb new file mode 100644 index 00000000..7357fe3f --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/institution_create.rb @@ -0,0 +1,16 @@ +module Lauth + module Persistence + module Changesets + class InstitutionCreate < ROM::Changeset::Create + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys id: :uniqueIdentifier, name: :organizationName + deep_merge lastModifiedTime: Time.now + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/institution_membership_create.rb b/lauth/lib/lauth/persistence/changesets/institution_membership_create.rb new file mode 100644 index 00000000..383b87b5 --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/institution_membership_create.rb @@ -0,0 +1,16 @@ +module Lauth + module Persistence + module Changesets + class InstitutionMembershipCreate < ROM::Changeset::Create + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys user_id: :userid, institution_id: :inst + deep_merge lastModifiedTime: Time.now + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/institution_membership_update.rb b/lauth/lib/lauth/persistence/changesets/institution_membership_update.rb new file mode 100644 index 00000000..bc9d9e52 --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/institution_membership_update.rb @@ -0,0 +1,24 @@ +module Lauth + module Persistence + module Changesets + class InstitutionMembershipUpdate < ROM::Changeset::Update + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys user_id: :userid, institution_id: :inst + deep_merge lastModifiedTime: Time.now + end + + def clean? + false + end + + def diff? + true + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/institution_update.rb b/lauth/lib/lauth/persistence/changesets/institution_update.rb new file mode 100644 index 00000000..30271a9a --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/institution_update.rb @@ -0,0 +1,24 @@ +module Lauth + module Persistence + module Changesets + class InstitutionUpdate < ROM::Changeset::Update + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys id: :uniqueIdentifier, name: :organizationName + deep_merge lastModifiedTime: Time.now + end + + def clean? + false + end + + def diff? + true + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/location_create.rb b/lauth/lib/lauth/persistence/changesets/location_create.rb new file mode 100644 index 00000000..1c1a8933 --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/location_create.rb @@ -0,0 +1,16 @@ +module Lauth + module Persistence + module Changesets + class LocationCreate < ROM::Changeset::Create + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys host: :dlpsServer, path: :dlpsPath, collection: :coll + deep_merge lastModifiedTime: Time.now + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/location_update.rb b/lauth/lib/lauth/persistence/changesets/location_update.rb new file mode 100644 index 00000000..46ec3c11 --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/location_update.rb @@ -0,0 +1,24 @@ +module Lauth + module Persistence + module Changesets + class LocationUpdate < ROM::Changeset::Update + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys host: :dlpsServer, path: :dlpsPath, collection: :coll + deep_merge lastModifiedTime: Time.now + end + + def clean? + false + end + + def diff? + true + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/network_create.rb b/lauth/lib/lauth/persistence/changesets/network_create.rb new file mode 100644 index 00000000..b623d950 --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/network_create.rb @@ -0,0 +1,17 @@ +module Lauth + module Persistence + module Changesets + class NetworkCreate < ROM::Changeset::Create + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys id: :uniqueIdentifier, cidr: :dlpsCIDRAddress, access: :dlpsAccessSwitch + rename_keys minimum: :dlpsAddressStart, maximum: :dlpsAddressEnd + deep_merge lastModifiedTime: Time.now + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/network_update.rb b/lauth/lib/lauth/persistence/changesets/network_update.rb new file mode 100644 index 00000000..df77decf --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/network_update.rb @@ -0,0 +1,25 @@ +module Lauth + module Persistence + module Changesets + class NetworkUpdate < ROM::Changeset::Update + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys id: :uniqueIdentifier, cidr: :dlpsCIDRAddress, access: :dlpsAccessSwitch + rename_keys minimum: :dlpsAddressStart, maximum: :dlpsAddressEnd + deep_merge lastModifiedTime: Time.now + end + + def clean? + false + end + + def diff? + true + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/user_create.rb b/lauth/lib/lauth/persistence/changesets/user_create.rb new file mode 100644 index 00000000..0f16cb8d --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/user_create.rb @@ -0,0 +1,17 @@ +module Lauth + module Persistence + module Changesets + class UserCreate < ROM::Changeset::Create + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys id: :userid, name: :surname + copy_keys surname: :givenName + deep_merge lastModifiedTime: Time.now + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/changesets/user_update.rb b/lauth/lib/lauth/persistence/changesets/user_update.rb new file mode 100644 index 00000000..2074841e --- /dev/null +++ b/lauth/lib/lauth/persistence/changesets/user_update.rb @@ -0,0 +1,25 @@ +module Lauth + module Persistence + module Changesets + class UserUpdate < ROM::Changeset::Update + map do + deep_symbolize_keys + unwrap :data + unwrap :attributes + reject_keys [:type] + rename_keys id: :userid, name: :surname + copy_keys surname: :givenName + deep_merge lastModifiedTime: Time.now + end + + def clean? + false + end + + def diff? + true + end + end + end + end +end diff --git a/lauth/lib/lauth/persistence/relations/locations.rb b/lauth/lib/lauth/persistence/relations/locations.rb index 149add9b..94315e46 100644 --- a/lauth/lib/lauth/persistence/relations/locations.rb +++ b/lauth/lib/lauth/persistence/relations/locations.rb @@ -3,6 +3,9 @@ module Persistence module Relations class Locations < ROM::Relation[:sql] schema(:aa_coll_obj, infer: true, as: :locations) do + attribute :lastModifiedBy, Types::String.default("root".freeze) + attribute :dlpsDeleted, Types::String.default("f".freeze) + associations do belongs_to :collection, foreign_key: :coll end diff --git a/lauth/spec/repositories/collection_repo_spec.rb b/lauth/spec/repositories/collection_repo_spec.rb new file mode 100644 index 00000000..8bd470fc --- /dev/null +++ b/lauth/spec/repositories/collection_repo_spec.rb @@ -0,0 +1,91 @@ +RSpec.describe Lauth::Repositories::CollectionRepo, type: :database do + subject(:repo) { Lauth::Repositories::CollectionRepo.new } + + describe "#collection and #collections" do + let(:active_collection) { {data: {id: "active_collection", type: "collections", attributes: {name: "Active"}}} } + let(:deleted_collection) { {data: {id: "deleted_collection", type: "collections", attributes: {name: "Deleted", dlpsDeleted: "t"}}} } + + before do + repo.create(active_collection) + repo.create(deleted_collection) + end + + it "has only one active collection" do + expect(repo.index.count).to eq 1 + end + + it "finds the active collection" do + expect(repo.find(active_collection[:data][:id]).id).to eq active_collection[:data][:id] + end + + it "does NOT find the deleted collection" do + expect(repo.find(deleted_collection[:data][:id])).to be nil + end + + it "does NOT find an undefined collection" do + expect(repo.find("undefined_collection")).to be nil + end + end + + describe "searching for collection based on request URI" do + context "with a collection 'some_collection' located at '/s/some/location'" do + let(:some_collection) { {data: {id: "some_collection", type: "collections", attributes: {name: "Some Collection"}}} } + let(:some_location) { {data: {id: "", type: "locations", attributes: {host: "some.host", path: "/s/some/location%", collection: some_collection[:data][:id]}}} } + let(:location_some) { {data: {id: "", type: "locations", attributes: {host: "some.host", path: "/s/location/some%", collection: some_collection[:data][:id], dlpsDeleted: "t"}}} } + + before do + location_repo = Lauth::Repositories::LocationRepo.new + repo.create(some_collection) + location_repo.create(some_location) + location_repo.create(location_some) + end + + it "finds the collection with a location" do + collection = repo.find_with_locations(some_collection[:data][:id]) + expect(collection.id).to eq some_collection[:data][:id] + expect(collection.locations.first.host).to eq some_location[:data][:attributes][:host] + expect(collection.locations.count).to eq 1 + end + + it "finds the collection for a request to '/s/some/location'" do + collections = repo.by_request_uri("some.host", "/s/some/location") + expect(collections.first.id).to eq some_collection[:data][:id] + end + + it "finds the collection for a request to '/s/some/location/resource'" do + collections = repo.by_request_uri("some.host", "/s/some/location/resource") + expect(collections.first.id).to eq some_collection[:data][:id] + end + + it "does not find the collection for a request to '/s/some'" do + collections = repo.by_request_uri("some.host", "/s/some") + expect(collections).to be_empty + end + end + + context "with two collections, 'some_collection' and 'other_collection', located at '/s/some/location' and '/o/other/location'" do + let(:some_collection) { {data: {id: "some_collection", type: "collections", attributes: {name: "Some Collection"}}} } + let(:some_location) { {data: {id: "", type: "locations", attributes: {host: "some.host", path: "/s/some/location%", collection: some_collection[:data][:id]}}} } + let(:other_collection) { {data: {id: "other_collection", type: "collections", attributes: {name: "Other Collection"}}} } + let(:other_location) { {data: {id: "", type: "locations", attributes: {host: "some.host", path: "/o/other/location%", collection: other_collection[:data][:id]}}} } + + before do + location_repo = Lauth::Repositories::LocationRepo.new + repo.create(some_collection) + location_repo.create(some_location) + repo.create(other_collection) + location_repo.create(other_location) + end + + it "finds 'some_collection' for a request to '/s/some/location'" do + collections = repo.by_request_uri("some.host", "/s/some/location") + expect(collections.first.id).to eq some_collection[:data][:id] + end + + it "finds 'other_collection' for a request to '/o/other/location'" do + collections = repo.by_request_uri("some.host", "/o/other/location") + expect(collections.first.id).to eq other_collection[:data][:id] + end + end + end +end diff --git a/lauth/spec/repositories/group_membership_repo_spec.rb b/lauth/spec/repositories/group_membership_repo_spec.rb new file mode 100644 index 00000000..ba17f665 --- /dev/null +++ b/lauth/spec/repositories/group_membership_repo_spec.rb @@ -0,0 +1,31 @@ +RSpec.describe Lauth::Repositories::GroupMembershipRepo, type: :database do + subject(:repo) { Lauth::Repositories::GroupMembershipRepo.new } + + describe "#group_membership and #group_memberships" do + let(:active_group_membership) { {data: {id: "", type: "group_memberships", attributes: {user_id: "Active", group_id: 2}}} } + let(:deleted_group_membership) { {data: {id: "", type: "group_memberships", attributes: {user_id: "Deleted", group_id: 1, dlpsDeleted: "t"}}} } + + before do + repo.create(active_group_membership) + repo.create(deleted_group_membership) + end + + it "has only one active group_membership" do + expect(repo.index.count).to eq 1 + end + + it "finds the active group_membership" do + group_membership = repo.find(active_group_membership[:data][:attributes][:user_id], active_group_membership[:data][:attributes][:group_id]) + expect(group_membership.userid).to eq active_group_membership[:data][:attributes][:user_id] + expect(group_membership.user_grp).to eq active_group_membership[:data][:attributes][:group_id] + end + + it "does NOT find the deleted group_membership" do + expect(repo.find(deleted_group_membership[:data][:attributes][:user_id], deleted_group_membership[:data][:attributes][:group_id])).to be nil + end + + it "does NOT find an undefined group_membership" do + expect(repo.find("undefined", 3)).to be nil + end + end +end diff --git a/lauth/spec/repositories/group_repo_spec.rb b/lauth/spec/repositories/group_repo_spec.rb new file mode 100644 index 00000000..0bbba0e6 --- /dev/null +++ b/lauth/spec/repositories/group_repo_spec.rb @@ -0,0 +1,29 @@ +RSpec.describe Lauth::Repositories::GroupRepo, type: :database do + subject(:repo) { Lauth::Repositories::GroupRepo.new } + + describe "#group and #groups" do + let(:active_group) { {data: {id: 2, type: "groups", attributes: {name: "Active"}}} } + let(:deleted_group) { {data: {id: 1, type: "groups", attributes: {name: "Deleted", dlpsDeleted: "t"}}} } + + before do + repo.create(active_group) + repo.create(deleted_group) + end + + it "has only one active group" do + expect(repo.index.count).to eq 1 + end + + it "finds the active group" do + expect(repo.find(active_group[:data][:id]).id).to eq active_group[:data][:id] + end + + it "does NOT find the deleted group" do + expect(repo.find(deleted_group[:data][:id])).to be nil + end + + it "does NOT find an undefined group" do + expect(repo.find(3)).to be nil + end + end +end diff --git a/lauth/spec/repositories/institution_repo_spec.rb b/lauth/spec/repositories/institution_repo_spec.rb new file mode 100644 index 00000000..813c833b --- /dev/null +++ b/lauth/spec/repositories/institution_repo_spec.rb @@ -0,0 +1,29 @@ +RSpec.describe Lauth::Repositories::InstitutionRepo, type: :database do + subject(:repo) { Lauth::Repositories::InstitutionRepo.new } + + describe "#institution and #institutions" do + let(:active_institution) { {data: {id: 2, type: "institutions", attributes: {name: "Active"}}} } + let(:deleted_institution) { {data: {id: 1, type: "institutions", attributes: {name: "Deleted", dlpsDeleted: "t"}}} } + + before do + repo.create(active_institution) + repo.create(deleted_institution) + end + + it "has only one active institution" do + expect(repo.index.count).to eq 1 + end + + it "finds the active institution" do + expect(repo.find(active_institution[:data][:id]).id).to eq active_institution[:data][:id] + end + + it "does NOT find the deleted institution" do + expect(repo.find(deleted_institution[:data][:id])).to be nil + end + + it "does NOT find an undefined institution" do + expect(repo.find(3)).to be nil + end + end +end diff --git a/lauth/spec/repositories/location_repo_spec.rb b/lauth/spec/repositories/location_repo_spec.rb new file mode 100644 index 00000000..69c93112 --- /dev/null +++ b/lauth/spec/repositories/location_repo_spec.rb @@ -0,0 +1,35 @@ +RSpec.describe Lauth::Repositories::LocationRepo, type: :database do + subject(:repo) { Lauth::Repositories::LocationRepo.new } + + describe "#location and #locations" do + let(:active_location) { {data: {id: "", type: "locations", attributes: {host: "Active", path: "/active%", collection: "active_collection"}}} } + let(:deleted_location) { {data: {id: "", type: "locations", attributes: {host: "Deleted", path: "/deleted%", collection: "deleted_collection", dlpsDeleted: "t"}}} } + + before do + repo.create(active_location) + repo.create(deleted_location) + end + + it "has only one active location" do + expect(repo.index.count).to eq 1 + end + + it "finds the active location" do + host = active_location[:data][:attributes][:host] + path = active_location[:data][:attributes][:path] + collection = active_location[:data][:attributes][:collection] + expect(repo.find(host, path, collection).host).to eq active_location[:data][:attributes][:host] + end + + it "does NOT find the deleted location" do + host = deleted_location[:data][:attributes][:host] + path = deleted_location[:data][:attributes][:path] + collection = deleted_location[:data][:attributes][:collection] + expect(repo.find(host, path, collection)).to be nil + end + + it "does NOT find an undefined location" do + expect(repo.find("Undefined", "/undefined%", "undefined_location")).to be nil + end + end +end diff --git a/lauth/spec/repositories/network_repo_spec.rb b/lauth/spec/repositories/network_repo_spec.rb new file mode 100644 index 00000000..73e88402 --- /dev/null +++ b/lauth/spec/repositories/network_repo_spec.rb @@ -0,0 +1,213 @@ +require "ipaddress" + +RSpec.describe Lauth::Repositories::NetworkRepo, type: :database do + subject(:repo) { Lauth::Repositories::NetworkRepo.new } + + describe "#network and #networks" do + let(:active_network) { {data: {id: 2, type: "networks", attributes: {"access" => "allow", "cidr" => "192.0.0.3/24"}}} } + let(:deleted_network) { {data: {id: 1, type: "networks", attributes: {"access" => "allow", "cidr" => "192.0.1.3/24", :dlpsDeleted => "t"}}} } + + before do + repo.create(active_network) + repo.create(deleted_network) + end + + it "has only one network" do + expect(repo.index.count).to eq 1 + end + + it "finds the active network" do + expect(repo.find(active_network[:data][:id]).id).to eq active_network[:data][:id] + end + + it "does NOT find the deleted network" do + expect(repo.find(deleted_network[:data][:id])).to be nil + end + + it "does NOT find an undefined network" do + expect(repo.find(3)).to be nil + end + end + + context "create, update, and delete" do + let(:created_document) do + { + data: { + id: 1, + type: "networks", + attributes: { + "access" => "allow", + "cidr" => created_ip_address.to_string + } + } + } + end + let(:created_ip_address) { IPAddress.parse "192.0.0.3/24" } + let(:created_network) { repo.create(created_document) } + let(:updated_document) do + { + data: { + id: 1, + type: "networks", + attributes: { + "cidr" => updated_ip_address.to_string + } + } + } + end + let(:updated_ip_address) { IPAddress.parse "192.0.1.3/24" } + let(:updated_network) { repo.update(updated_document) } + let(:invalid_document) do + { + data: { + id: 1, + type: "networks", + attributes: {} + } + } + end + + describe "create, update and delete" do + it "creates a network" do + created_network + expect(repo.find(created_network.id)).to eq(created_network) + end + + it "updates a network" do + created_network + updated_network + expect(repo.find(created_network.id)).to eq(updated_network) + end + + it "deletes a network" do + created_network + deleted_network = repo.delete(created_network.id) + expect(deleted_network).to eq(created_network) + expect(repo.find(created_network.id)).to be nil + end + end + + describe "ip network" do + context "singularity (one node)" do + let(:created_ip_address) { IPAddress.parse "192.0.0.3/32" } + let(:updated_ip_address) { IPAddress.parse "192.0.1.3/32" } + + it "cidr is start node address" do + expect(created_network.cidr).to eq("192.0.0.3/32") + expect(updated_network.cidr).to eq("192.0.1.3/32") + end + + it "minimum starts at node address" do + expect(created_network.minimum).to eq(created_ip_address.to_u32) + expect(updated_network.minimum).to eq(updated_ip_address.to_u32) + end + + it "maximum ends at node address" do + expect(created_network.maximum).to eq(created_ip_address.to_u32) + expect(updated_network.maximum).to eq(updated_ip_address.to_u32) + end + + context "include?" do + before { created_network } + + it "not found" do + created_network + expect(repo.include?(updated_ip_address)).to be_empty + end + + it "found" do + created_network + expect(repo.include?(created_ip_address)).to contain_exactly(created_network) + end + end + end + + context "degenerate (two nodes)" do + let(:created_ip_address) { IPAddress.parse "192.0.0.3/31" } + let(:updated_ip_address) { IPAddress.parse "192.0.1.3/31" } + + it "cidr is start node address" do + expect(created_network.cidr).to eq("192.0.0.2/31") + expect(updated_network.cidr).to eq("192.0.1.2/31") + end + + it "minimum starts at first node address" do + expect(created_network.minimum).to eq(created_ip_address.first.to_u32) + expect(updated_network.minimum).to eq(updated_ip_address.first.to_u32) + end + + it "maximum ends at last node address" do + expect(created_network.maximum).to eq(created_ip_address.last.to_u32) + expect(updated_network.maximum).to eq(updated_ip_address.last.to_u32) + end + + context "include?" do + before { created_network } + + it "not found" do + created_network + expect(repo.include?(updated_ip_address)).to be_empty + end + + it "found" do + created_network + expect(repo.include?(created_ip_address)).to contain_exactly(created_network) + end + end + end + + context "valid network (network, two or more nodes, broadcast" do + let(:created_ip_address) { IPAddress.parse "192.0.0.3/30" } + let(:updated_ip_address) { IPAddress.parse "192.0.1.3/30" } + + it "cidr is network address" do + expect(created_network.cidr).to eq("192.0.0.0/30") + expect(updated_network.cidr).to eq("192.0.1.0/30") + end + + it "minimum starts at network address" do + expect(created_network.minimum).to eq(created_ip_address.network.to_u32) + expect(updated_network.minimum).to eq(updated_ip_address.network.to_u32) + end + + it "maximum ends at broadcast address" do + expect(created_network.maximum).to eq(created_ip_address.broadcast.to_u32) + expect(updated_network.maximum).to eq(updated_ip_address.broadcast.to_u32) + end + + context "include?" do + before { created_network } + + it "not found" do + created_network + expect(repo.include?(updated_ip_address)).to be_empty + end + + it "found" do + created_network + expect(repo.include?(created_ip_address)).to contain_exactly(created_network) + end + end + end + end + + describe "change failures" do + it "fails to create on missing cidr attribute" do + expect(repo.create(invalid_document)).to be nil + end + + it "fails to update on missing cidr attribute" do + created_network + expect(repo.update(invalid_document)).to be nil + end + + it "fails to update a non-existing network" do + expect(repo.update(updated_document)).to be nil + end + + it "fails to delete a non-existing network" do + expect(repo.delete(1)).to be nil + end + end + end +end diff --git a/lauth/spec/repositories/repo_grant_spec.rb b/lauth/spec/repositories/repo_grant_spec.rb new file mode 100644 index 00000000..b50b79d6 --- /dev/null +++ b/lauth/spec/repositories/repo_grant_spec.rb @@ -0,0 +1,29 @@ +RSpec.describe Lauth::Repositories::GrantRepo, type: :database do + subject(:repo) { Lauth::Repositories::GrantRepo.new } + + describe "#grant and #grants" do + let(:active_grant) { {data: {id: 2, type: "grants", attributes: {coll: "collection"}}} } + let(:deleted_grant) { {data: {id: 1, type: "grants", attributes: {coll: "collection", dlpsDeleted: "t"}}} } + + before do + repo.create(active_grant) + repo.create(deleted_grant) + end + + it "has only one active grant" do + expect(repo.index.count).to eq 1 + end + + it "finds the active grant" do + expect(repo.find(active_grant[:data][:id]).id).to eq active_grant[:data][:id] + end + + it "does NOT find the deleted grant" do + expect(repo.find(deleted_grant[:data][:id])).to be nil + end + + it "does NOT find an undefined grant" do + expect(repo.find(3)).to be nil + end + end +end diff --git a/lauth/spec/repositories/soft_delete_spec.rb b/lauth/spec/repositories/soft_delete_spec.rb new file mode 100644 index 00000000..335d5b1a --- /dev/null +++ b/lauth/spec/repositories/soft_delete_spec.rb @@ -0,0 +1,265 @@ +require "ipaddress" + +RSpec.describe "Soft Delete Spec", type: :database do + describe "Grant Repo" do + subject(:grant_repo) { Lauth::Repositories::GrantRepo.new } + + describe "user grant" do + subject(:grant_for) { grant_repo.for(username: user_id, uri: path) } + + let(:user_repo) { Lauth::Repositories::UserRepo.new } + let(:user_id) { "user_id" } + let(:user_doc) { {data: {id: user_id, type: "users", attributes: {name: "User"}}} } + let(:collection_repo) { Lauth::Repositories::CollectionRepo.new } + let(:collection_id) { "collection_id" } + let(:collection_doc) { {data: {id: collection_id, type: "collections", attributes: {name: "Collection"}}} } + let(:location_repo) { Lauth::Repositories::LocationRepo.new } + let(:host) { "host" } + let(:path) { "/location%" } + let(:location_doc) { {data: {type: "locations", attributes: {host: host, path: path, collection: collection_id}}} } + let(:grant_id) { 4 } + let(:grant_doc) { {data: {id: grant_id, type: "grants", attributes: {userid: user_id, coll: collection_id}}} } + + before do + user_repo.create(user_doc) + collection_repo.create(collection_doc) + location_repo.create(location_doc) + grant_repo.create(grant_doc) + end + + it "returns the grant" do + expect(grant_for.first.uniqueIdentifier).to eq grant_id + end + + context "when the grant is deleted" do + before do + grant_repo.delete(grant_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + + context "when the location is deleted" do + before do + location_repo.delete(host, path, collection_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + + context "when the collection is deleted" do + before do + collection_repo.delete(collection_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + + context "when the user is deleted" do + before do + user_repo.delete(user_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + end + + describe "group grant" do + subject(:grant_for) { grant_repo.for(username: user_id, uri: path) } + + let(:user_repo) { Lauth::Repositories::UserRepo.new } + let(:user_id) { "user_id" } + let(:user_doc) { {data: {id: user_id, type: "users", attributes: {name: "User"}}} } + let(:group_repo) { Lauth::Repositories::GroupRepo.new } + let(:group_id) { 6 } + let(:group_doc) { {data: {id: group_id, type: "groups", attributes: {name: "Group"}}} } + let(:group_memberships_repo) { Lauth::Repositories::GroupMembershipRepo.new } + let(:group_membership_doc) { {data: {type: "group_memberships", attributes: {user_id: user_id, group_id: group_id}}} } + let(:collection_repo) { Lauth::Repositories::CollectionRepo.new } + let(:collection_id) { "collection_id" } + let(:collection_doc) { {data: {id: collection_id, type: "collections", attributes: {name: "Collection"}}} } + let(:location_repo) { Lauth::Repositories::LocationRepo.new } + let(:host) { "host" } + let(:path) { "/location%" } + let(:location_doc) { {data: {type: "locations", attributes: {host: host, path: path, collection: collection_id}}} } + let(:grant_id) { 4 } + let(:grant_doc) { {data: {id: grant_id, type: "grants", attributes: {user_grp: group_id, coll: collection_id}}} } + + before do + user_repo.create(user_doc) + group_repo.create(group_doc) + group_memberships_repo.create(group_membership_doc) + collection_repo.create(collection_doc) + location_repo.create(location_doc) + grant_repo.create(grant_doc) + end + + it "returns the grant" do + expect(grant_for.first.uniqueIdentifier).to eq grant_id + end + + context "when the grant is deleted" do + before do + grant_repo.delete(grant_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + + context "when the location is deleted" do + before do + location_repo.delete(host, path, collection_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + + context "when the collection is deleted" do + before do + collection_repo.delete(collection_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + + context "when the user is deleted" do + before do + user_repo.delete(user_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + + context "when the group is deleted" do + before do + group_repo.delete(group_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + + context "when the group membership is deleted" do + before do + group_memberships_repo.delete(user_id, group_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + end + + describe "institution grant" do + subject(:grant_for) { grant_repo.for(username: user_id, uri: path) } + + let(:user_repo) { Lauth::Repositories::UserRepo.new } + let(:user_id) { "user_id" } + let(:user_doc) { {data: {id: user_id, type: "users", attributes: {name: "User"}}} } + let(:institution_repo) { Lauth::Repositories::InstitutionRepo.new } + let(:institution_id) { 8 } + let(:institution_doc) { {data: {id: institution_id, type: "institutions", attributes: {name: "Group"}}} } + let(:institution_memberships_repo) { Lauth::Repositories::InstitutionMembershipRepo.new } + let(:institution_membership_doc) { {data: {type: "institution_memberships", attributes: {user_id: user_id, institution_id: institution_id}}} } + let(:collection_repo) { Lauth::Repositories::CollectionRepo.new } + let(:collection_id) { "collection_id" } + let(:collection_doc) { {data: {id: collection_id, type: "collections", attributes: {name: "Collection"}}} } + let(:location_repo) { Lauth::Repositories::LocationRepo.new } + let(:host) { "host" } + let(:path) { "/location%" } + let(:location_doc) { {data: {type: "locations", attributes: {host: host, path: path, collection: collection_id}}} } + let(:grant_id) { 4 } + let(:grant_doc) { {data: {id: grant_id, type: "grants", attributes: {inst: institution_id, coll: collection_id}}} } + + before do + user_repo.create(user_doc) + institution_repo.create(institution_doc) + institution_memberships_repo.create(institution_membership_doc) + collection_repo.create(collection_doc) + location_repo.create(location_doc) + grant_repo.create(grant_doc) + end + + it "returns the grant" do + expect(grant_for.first.uniqueIdentifier).to eq grant_id + end + + context "when the grant is deleted" do + before do + grant_repo.delete(grant_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + + context "when the location is deleted" do + before do + location_repo.delete(host, path, collection_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + + context "when the collection is deleted" do + before do + collection_repo.delete(collection_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + + context "when the user is deleted" do + before do + user_repo.delete(user_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + + context "when the institution is deleted" do + before do + institution_repo.delete(institution_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + + context "when the institution membership is deleted" do + before do + institution_memberships_repo.delete(user_id, institution_id) + end + + it "returns and empty array" do + expect(grant_for).to be_empty + end + end + end + end +end diff --git a/lauth/spec/repositories/user_repo_spec.rb b/lauth/spec/repositories/user_repo_spec.rb new file mode 100644 index 00000000..9b1e41d9 --- /dev/null +++ b/lauth/spec/repositories/user_repo_spec.rb @@ -0,0 +1,29 @@ +RSpec.describe Lauth::Repositories::UserRepo, type: :database do + subject(:repo) { Lauth::Repositories::UserRepo.new } + + describe "#user and #users" do + let(:active_user) { {data: {id: "active_user", type: "users", attributes: {name: "Active"}}} } + let(:deleted_user) { {data: {id: "deleted_user", type: "users", attributes: {name: "Deleted", dlpsDeleted: "t"}}} } + + before do + repo.create(active_user) + repo.create(deleted_user) + end + + it "has only one active user" do + expect(repo.index.count).to eq 1 + end + + it "finds the active user" do + expect(repo.find(active_user[:data][:id]).id).to eq active_user[:data][:id] + end + + it "does NOT find the deleted user" do + expect(repo.find(deleted_user[:data][:id])).to be nil + end + + it "does NOT find an undefined user" do + expect(repo.find("undefined_user")).to be nil + end + end +end