我在多租户模型中使用RLS。我启用的前几个表没有问题。然后我将RLS添加到新表中,然后我突然无法在该表中插入记录。
这是一个有效的表格:
CREATE TABLE wtr.adjustment (
id uuid UNIQUE NOT NULL DEFAULT uuid_generate_v1(),
created_at timestamp NOT NULL DEFAULT current_timestamp,
updated_at timestamp NOT NULL DEFAULT current_timestamp,
vendor_id uuid NOT NULL,
reporting_period_id uuid NOT NULL,
inventory_lot_id uuid NOT NULL,
adjustment_date date NOT NULL,
quantity_delta NUMERIC(50,2) NOT NULL,
adjustment_type wtr.adjustment_type NOT NULL,
comments text,
CONSTRAINT pk_adjustment PRIMARY KEY (id)
);
--||--
GRANT select, insert, update, delete ON TABLE wtr.adjustment TO wtr_user;
--||--
ALTER TABLE wtr.adjustment ADD CONSTRAINT fk_adjustment_vendor FOREIGN KEY ( vendor_id ) REFERENCES wtr.vendor( id );
--||--
ALTER TABLE wtr.adjustment ADD CONSTRAINT fk_adjustment_reporting_period FOREIGN KEY ( reporting_period_id ) REFERENCES wtr.reporting_period( id );
--||--
ALTER TABLE wtr.adjustment ADD CONSTRAINT fk_adjustment_inventory_lot FOREIGN KEY ( inventory_lot_id ) REFERENCES wtr.inventory_lot( id );
--||--
ALTER TABLE wtr.adjustment ENABLE ROW LEVEL SECURITY;
--||--
CREATE POLICY select_adjustment ON wtr.adjustment FOR SELECT
USING (vendor_id = wtr.current_vendor_id());
--||--
CREATE FUNCTION wtr.fn_timestamp_update_adjustment() RETURNS trigger AS $$
BEGIN
NEW.updated_at = current_timestamp;
RETURN NEW;
END; $$ LANGUAGE plpgsql;
--||--
CREATE TRIGGER tg_timestamp_update_adjustment
BEFORE UPDATE ON wtr.adjustment
FOR EACH ROW
EXECUTE PROCEDURE wtr.fn_timestamp_update_adjustment();
--||--
以及有效的相关功能:
CREATE OR REPLACE FUNCTION wtr.build_adjustment(
_reporting_period_id uuid,
_inventory_lot_gov_id text,
_strain_name text,
_room_name text,
_inventory_type_name text,
_adjustment_date text,
_quantity_delta NUMERIC(50,2),
_adjustment_type wtr.adjustment_type,
_comments text
)
RETURNS wtr.adjustment as $$
DECLARE
_vendor_id uuid;
_inventory_lot wtr.inventory_lot;
_adjustment wtr.adjustment;
_inventory_type_id uuid;
BEGIN
_vendor_id := wtr.current_vendor_id();
_inventory_lot := wtr.find_or_build_existing_inventory_lot(
_strain_name,
_room_name,
_inventory_lot_gov_id,
_inventory_type_name
);
INSERT INTO wtr.adjustment(
vendor_id,
reporting_period_id,
inventory_lot_id,
adjustment_date,
quantity_delta,
adjustment_type,
comments
)
SELECT
_vendor_id,
_reporting_period_id,
_inventory_lot.id,
_adjustment_date::DATE,
_quantity_delta,
_adjustment_type,
_comments
RETURNING *
INTO _adjustment;
RETURN _adjustment;
END;
$$ language plpgsql strict security definer;
--||--
GRANT execute ON FUNCTION wtr.build_adjustment(
uuid,
text,
text,
text,
text,
text,
numeric,
wtr.adjustment_type,
text
) TO wtr_user;
这是失败的表:
CREATE TABLE wtr.received_inventory_transfer (
id uuid UNIQUE NOT NULL DEFAULT uuid_generate_v1(),
created_at timestamp NOT NULL DEFAULT current_timestamp,
updated_at timestamp NOT NULL DEFAULT current_timestamp,
vendor_id uuid NOT NULL,
reporting_period_id uuid NOT NULL,
inventory_lot_id uuid NOT NULL,
transfer_date DATE NOT NULL,
quantity_received NUMERIC(50,2) NOT NULL,
CONSTRAINT pk_received_inventory_transfer PRIMARY KEY (id)
);
--||--
GRANT select, insert, update, delete ON TABLE wtr.received_inventory_transfer TO wtr_user;
--||--
ALTER TABLE wtr.received_inventory_transfer ADD CONSTRAINT fk_received_inventory_transfer_vendor FOREIGN KEY ( vendor_id ) REFERENCES wtr.vendor( id );
--||--
ALTER TABLE wtr.received_inventory_transfer ADD CONSTRAINT fk_received_inventory_transfer_reporting_period FOREIGN KEY ( reporting_period_id ) REFERENCES wtr.reporting_period( id );
--||--
ALTER TABLE wtr.received_inventory_transfer ADD CONSTRAINT fk_received_inventory_transfer_inventory_lot FOREIGN KEY ( inventory_lot_id ) REFERENCES wtr.inventory_lot( id );
--||--
ALTER TABLE wtr.received_inventory_transfer ENABLE ROW LEVEL SECURITY;
--||--
CREATE POLICY select_received_inventory_transfer ON wtr.received_inventory_transfer FOR SELECT USING (vendor_id = wtr.current_vendor_id());
--||--
CREATE FUNCTION wtr.fn_timestamp_update_received_inventory_transfer() RETURNS trigger AS $$
BEGIN
NEW.updated_at = current_timestamp;
RETURN NEW;
END; $$ LANGUAGE plpgsql;
--||--
CREATE TRIGGER tg_timestamp_update_received_inventory_transfer
BEFORE UPDATE ON wtr.received_inventory_transfer
FOR EACH ROW
EXECUTE PROCEDURE wtr.fn_timestamp_update_received_inventory_transfer();
--||--
以及相关的失败功能:
CREATE OR REPLACE FUNCTION wtr.build_received_inventory_transfers(
_reporting_period_id uuid,
_transfer_date text
-- _received_inventory_transfers jsonb
)
RETURNS wtr.received_inventory_transfer as $$
DECLARE
_vendor_id uuid;
_inventory_lot wtr.inventory_lot;
_received_inventory_transfer_info jsonb;
_received_inventory_transfer wtr.received_inventory_transfer;
_quantity numeric(50,2);
BEGIN
_vendor_id := wtr.current_vendor_id();
-- this call is currently hard coded for debug purposes
_inventory_lot := wtr.find_or_build_existing_inventory_lot(
'tacos',
'N/A',
'1234123412341234',
'Hash'
);
-- again, this is hard-coded for debug purposes
RAISE EXCEPTION 'v: %, rp: %, il: %, td: %, q: %',
_vendor_id,
_reporting_period_id,
_inventory_lot.id,
_transfer_date::DATE,
20
;
-- this is the call that fails
INSERT INTO wtr.received_inventory_transfer(
vendor_id,
reporting_period_id,
inventory_lot_id,
transfer_date,
quantity_received
)
SELECT
_vendor_id,
_reporting_period_id,
_inventory_lot.id,
_transfer_date::DATE,
20
RETURNING *
INTO _received_inventory_transfer;
RETURN _received_inventory_transfer;
END;
$$ language plpgsql;
--||--
GRANT execute ON FUNCTION wtr.build_received_inventory_transfers(
uuid,
text
-- jsonb
) TO wtr_user;
current_vendor_id
函数使用服务器传入的jwt令牌声明,即postgraphile。
在insert语句中,调用失败:
new row violates row-level security policy for table
\"received_inventory_transfer\"",
此信息就是日志将显示给我的全部信息。
我认为我的真正问题是 - 如何进一步调试RLS策略?如果我只启用RLS,但没有创建选择策略,我会遇到同样的失败。
答案 0 :(得分:0)
当然,接下来我想通了:
CREATE POLICY insert_received_inventory_transfer
ON wtr.received_inventory_transfer
FOR INSERT
WITH CHECK (vendor_id = wtr.current_vendor_id());