diff --git a/Dockerfile b/Dockerfile index 0708a3a..ffeb5c6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -81,7 +81,8 @@ RUN for binary in /app/bin/* /usr/bin/pg_dump /usr/bin/pg_restore /usr/bin/psql; xargs -I % sh -c 'mkdir -p $(dirname deps%); cp % deps%;'; \ done -RUN git clone https://github.com/PlaceOS/models +# PPT-526: the tenancy migrations live on this branch until models #332 merges +RUN git clone --branch PPT-526-partner-client https://github.com/PlaceOS/models # Create tmp directory with proper permissions RUN rm -rf /tmp && mkdir -p /tmp && chmod 1777 /tmp diff --git a/shard.lock b/shard.lock index b9a0d43..33346a7 100644 --- a/shard.lock +++ b/shard.lock @@ -147,15 +147,15 @@ shards: place_calendar: git: https://github.com/placeos/calendar.git - version: 4.30.0 + version: 4.30.1 placeos-log-backend: git: https://github.com/place-labs/log-backend.git version: 0.13.0 - placeos-models: + placeos-models: # Overridden git: https://github.com/placeos/models.git - version: 9.118.1 + version: 9.118.1+git.commit.e21d7904b1d9fe12b7852e9e835a50489647e5f6 sam: git: https://github.com/imdrasil/sam.cr.git diff --git a/shard.override.yml b/shard.override.yml index 9c17593..a8bb7aa 100644 --- a/shard.override.yml +++ b/shard.override.yml @@ -1,4 +1,9 @@ dependencies: + # PPT-526: build against the multi-tenancy data layer until models #332 merges + placeos-models: + github: placeos/models + branch: PPT-526-partner-client + retriable: github: Sija/retriable.cr db: diff --git a/src/sam.cr b/src/sam.cr index 250055e..44edd68 100644 --- a/src/sam.cr +++ b/src/sam.cr @@ -261,7 +261,9 @@ namespace "create" do desc "Creates a representative set of documents in PostgreSQL DB" task "placeholders" do - PlaceOS::Tasks.create_placeholders + # placeholders belong to the staff organisation when one exists + staff = PlaceOS::Model::Organisation.where(partner_staff: true).first? + PlaceOS::Tasks.create_placeholders(staff.try(&.id)) end desc "Creates an authority" diff --git a/src/tasks/entities.cr b/src/tasks/entities.cr index 6f46dc1..b222b5f 100644 --- a/src/tasks/entities.cr +++ b/src/tasks/entities.cr @@ -35,6 +35,41 @@ module PlaceOS::Tasks::Entities raise e end + # The platform operator's partner and staff organisation. The first domain + # belongs to that organisation, so its admins have cluster reach once + # tenancy enforcement is on. + def create_management_organisation( + authority : Model::Authority, + partner_name : String = "PlaceOS", + ) : Model::Organisation + partner = upsert_document(Model::Partner.where(management: true)) do + Log.info { {message: "creating management Partner", name: partner_name} } + Model::Partner.new(name: partner_name, description: "Platform operator (management partner)").tap do |new_partner| + new_partner.management = true + end + end + + organisation = upsert_document(Model::Organisation.where(partner_id: partner.id, partner_staff: true)) do + Log.info { {message: "creating staff Organisation", name: authority.name} } + Model::Organisation.new(name: "#{partner_name} staff", description: "Staff of the management partner").tap do |new_org| + new_org.partner_id = partner.id + new_org.partner_staff = true + new_org.payer = Model::Organisation::PAYER_ORGANISATION + end + end + + if authority.organisation_id.nil? + authority.organisation_id = organisation.id + authority.save! + Log.info { {message: "attached Authority to staff Organisation", authority: authority.id, organisation: organisation.id.to_s} } + end + + organisation + rescue e + log_fail("Organisation", e) + raise e + end + def create_interface( name : String, folder_name : String, @@ -141,7 +176,7 @@ module PlaceOS::Tasks::Entities raise e end - def create_placeholders + def create_placeholders(organisation_id : UUID? = nil) version = UUID.random.to_s.split('-').first private_repository_uri = "https://github.com/placeos/private-drivers" @@ -201,6 +236,7 @@ module PlaceOS::Tasks::Entities Model::Zone.new.tap do |zone| zone.name = "Zone-#{tag}-#{version}" zone.tags = Set{tag} + zone.organisation_id = organisation_id end end end @@ -213,7 +249,9 @@ module PlaceOS::Tasks::Entities zones[2].save! control_system = upsert_document(Model::ControlSystem.all) do - Model::ControlSystem.new(name: "System-#{version}") + Model::ControlSystem.new(name: "System-#{version}").tap do |sys| + sys.organisation_id = organisation_id + end end upsert_document(Model::Settings.for_parent(control_system.id.as(String))) do @@ -227,6 +265,7 @@ module PlaceOS::Tasks::Entities mod = upsert_document(Model::Module.where(driver_id: driver.id.as(String), control_system_id: control_system.id.as(String))) do Model::Generator.module(driver: driver, control_system: control_system).tap do |new_module| new_module.custom_name = "Module-#{version}" + new_module.organisation_id = organisation_id end end @@ -241,6 +280,7 @@ module PlaceOS::Tasks::Entities trigger_description = "An automatically generated Trigger." new_trigger = Model::Trigger.new(name: trigger_name, description: trigger_description) new_trigger.control_system = control_system + new_trigger.organisation_id = organisation_id new_trigger end diff --git a/src/tasks/initialization.cr b/src/tasks/initialization.cr index ad2199e..0bbf5e8 100644 --- a/src/tasks/initialization.cr +++ b/src/tasks/initialization.cr @@ -33,6 +33,7 @@ module PlaceOS::Tasks::Initialization start_lock.synchronize do authority = Entities.create_authority(name: application_base, domain: application_base, config: metrics_config) + organisation = Entities.create_management_organisation(authority) Entities.create_user(authority: authority, name: username, email: email, password: password, sys_admin: true) Entities.create_application(authority: authority, name: application_name, base: application_base) @@ -53,7 +54,7 @@ module PlaceOS::Tasks::Initialization unless PlaceOS::Tasks.production? || PlaceOS::SKIP_PLACEHOLDERS Log.info { "creating placeholder documents" } - Entities.create_placeholders + Entities.create_placeholders(organisation.id) end end end