2013-10-15 31 views
1

考慮以下模式:授權邀請用戶通過數據庫觸發器

Table "public.users" 
     Column  |   Type   |       Modifiers 
----------------------+--------------------------+------------------------------------------------------------ 
uuid     | uuid      | not null default uuid_generate_v4() 
email    | character varying(254) | not null 
name     | text      | not null 
created_at   | timestamp with time zone | not null default now() 

Table "public.users_projects" 
    Column  |   Type   |     Modifiers 
-----------------+--------------------------+-------------------------------------------- 
project_uuid | uuid      | not null 
user_uuid  | uuid      | not null 
invitation_uuid | uuid      | 
membership_type | membership_type   | not null default 'member'::membership_type 
created_at  | timestamp with time zone | not null default now() 

Table "public.projects" 
    Column |   Type   |    Modifiers 
------------+--------------------------+------------------------------------- 
uuid  | uuid      | not null default uuid_generate_v4() 
name  | character varying(100) | not null 
created_at | timestamp with time zone | not null default now() 

Table "public.invitations" 
    Column  |   Type   |     Modifiers 
-----------------+--------------------------+-------------------------------------------- 
uuid   | uuid      | not null default uuid_generate_v4() 
email   | character varying(254) | not null 
target_type  | character varying(50) | not null 
target_uuid  | uuid      | not null 
membership_type | membership_type   | not null default 'member'::membership_type 
token   | character varying(32) | not null default md5((random())::text) 
creator_uuid | uuid      | not null 

也有一個枚舉類型CREATE TYPE membership_type AS ENUM ('guest', 'member', 'manager', 'owner');

我想知道如果我可以使用觸發器來驗證用戶不能創建一個資源的邀請,至少沒有連接表上的成員類型manager

我的主要問題是:

  • 我可以將該行插入「之前」使用觸發器,CREATE TRIGGER check_authorisation BEFORE INSERT OR UPDATE ON invitations FOR EACH ROW EXECUTE PROCEDURE check_authorisation();
  • 我多少信息可以給回一條錯誤消息,因爲對剛剛失敗,因爲數據庫連接斷開等
  • 這是一個理智的方法嗎?作爲一個Web應用程序開發人員,我習慣於在應用程序代碼中檢查這個環境,但是我正在處理將由兩個應用程序共享的數據庫(Golang和Ruby)
  • 我可以實現REFERENCES在多態字段(target_type,target_uuid)以某種方式?

回答

0

我可以用一個觸發行插入 「之前」,CREATE TRIGGER check_authorisation BEFORE插入或更新爲每個ROW EXECUTE PROCEDURE check_authorisation邀請();

使其成爲(之後)約束觸發器,並在適當時引發異常。

更一般地說,在觸發器傳播副作用和約束觸發器以驗證完整性之後,在需要時使用觸發器之前修改傳入數據。

我多少信息可以給回一條錯誤消息,因爲對剛剛失敗,因爲數據庫連接下來,等

只要你想提高你的異常時發送太多。

這是一種理智的方法嗎?作爲一個Web應用程序開發人員,我習慣於在應用程序代碼中檢查這個環境,但我正在處理將由兩個應用程序(Golang和Ruby)共享的數據庫。

它可以如果做得對,那麼理智就沒有問題,但是,在授權方面,正確管理所有的怪異案例基本上是不可能的,所以這種類型的邏輯通常更好地位於數據庫之外。

案例:經理的祕書更換(原來的產假)會發生什麼?

能否以某種方式在多態字段(target_type,target_uuid)上實現REFERENCES?

你可以用後觸發。但是,根據你在做什麼,考慮用單獨的字段,外鍵和檢查約束對它進行規範化,以確保它們是互斥的。管理起來往往比管理更簡單/清潔,而最終還是等於手動重寫外鍵邏輯。