Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
-- +micrate Up
-- SQL in section 'Up' is executed when this migration is applied

ALTER TABLE storages
ADD COLUMN is_default BOOLEAN NOT NULL DEFAULT FALSE;

CREATE UNIQUE INDEX storages_authority_default_idx
ON storages (authority_id)
NULLS NOT DISTINCT
WHERE is_default = TRUE;

-- +micrate StatementBegin
-- Trigger function to auto-unset any other storages with is_default = TRUE
CREATE OR REPLACE FUNCTION storages_ensure_single_default()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.is_default THEN
UPDATE storages
SET is_default = FALSE
WHERE authority_id IS NOT DISTINCT FROM NEW.authority_id
AND id <> NEW.id;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- +micrate StatementEnd

-- it will automatically flip any other row for that same tenant back to FALSE
CREATE TRIGGER trg_storages_single_default
BEFORE INSERT OR UPDATE OF is_default
ON storages
FOR EACH ROW
WHEN (NEW.is_default = TRUE)
EXECUTE FUNCTION storages_ensure_single_default();

-- +micrate Down
-- SQL section 'Down' is executed when this migration is rolled back

-- 1. Drop the trigger
DROP TRIGGER IF EXISTS trg_storages_single_default
ON storages;

-- 2. Drop the trigger function
DROP FUNCTION IF EXISTS storages_ensure_single_default()
CASCADE;

-- 3. Drop the partial unique index
DROP INDEX IF EXISTS storages_authority_default_idx;

-- 4. Drop the is_default column
ALTER TABLE storages
DROP COLUMN IF EXISTS is_default;
38 changes: 38 additions & 0 deletions spec/storage_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ require "./helper"
module PlaceOS::Model
Spec.before_each do
Storage.clear
Authority.clear
end

describe Storage do
Expand Down Expand Up @@ -44,6 +45,43 @@ module PlaceOS::Model
Storage.storage_or_default("NOT-DEFINED-AUTHORITY").should_not be_nil
end

it "should return default storage when flagged" do
authority = Generator.authority.save!

def1 = Generator.storage.save!
def1.authority_id.should be_nil
def2 = Generator.storage.save!
def2.authority_id.should be_nil
def1.reload!
def2.reload!

def1.is_default.should be_false
def2.is_default.should be_true

s2 = Generator.storage
s2.authority_id = authority.id
s2.is_default = false
s2.save!
ret_store = Storage.storage_or_default(authority.id).id.should eq s2.id

s3 = Generator.storage
s3.authority_id = authority.id
s3.is_default = true
s3.save!
s3.reload!
s3.is_default.should be_true
Storage.storage_or_default(authority.id).id.should eq s3.id

s2.is_default = true
s2.save!
s2.reload!
s2.is_default.should be_true

s3.reload!
s3.is_default.should be_false
ret_store = Storage.storage_or_default(authority.id).id.should eq s2.id
end

it "should handle extension and mime whitelist" do
s1 = Generator.storage.save!
s1.check_file_ext("something")
Expand Down
3 changes: 2 additions & 1 deletion src/placeos-models/storage.cr
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ module PlaceOS::Model
attribute access_secret : String
attribute authority_id : String?
attribute endpoint : String?
attribute is_default : Bool = true

attribute ext_filter : Array(String) = [] of String
attribute mime_filter : Array(String) = [] of String
Expand Down Expand Up @@ -50,7 +51,7 @@ module PlaceOS::Model
end

def self.storage_or_default(authority_id : String?) : Storage
model = Storage.find_by?(authority_id: authority_id) || Storage.find_by?(authority_id: nil)
model = Storage.order(is_default: :desc).find_by?(authority_id: authority_id) || Storage.order(is_default: :desc).find_by?(authority_id: nil)
raise Model::Error.new("Could not find Default or authority '#{authority_id}' Storage") if model.nil?
model
end
Expand Down