-- Reset the demo DROP SECURITY POLICY IF EXISTS Security.patientSecurityPolicy DROP FUNCTION IF EXISTS Security.patientAccessPredicate DROP SCHEMA IF EXISTS Security go -- Observe existing schema SELECT * FROM Patients go -- Mapping table, assigning application users to patients -- We'll use RLS to ensure that application users can only access patients assigned to them SELECT * FROM ApplicationUserPatients go -- Create separate schema for RLS objects -- (not required, but best practice to limit access) CREATE SCHEMA Security go -- Create predicate function for RLS -- This determines which users can access which rows CREATE FUNCTION Security.patientAccessPredicate(@PatientID int) RETURNS TABLE WITH SCHEMABINDING AS RETURN SELECT 1 AS isAccessible FROM dbo.ApplicationUserPatients WHERE ( -- application users can access only patients assigned to them Patient_PatientID = @PatientID AND ApplicationUser_Id = CAST(SESSION_CONTEXT(N'UserId') AS nvarchar(128)) ) OR ( -- DBAs can access all patients IS_MEMBER('db_owner') = 1 ) go -- Create security policy that adds this function as a security predicate on the Patients and Visits tables -- Filter predicates filter out patients who shouldn't be accessible by the current user -- Block predicates prevent the current user from inserting any patients who aren't mapped to them CREATE SECURITY POLICY Security.patientSecurityPolicy ADD FILTER PREDICATE Security.patientAccessPredicate(PatientID) ON dbo.Patients, ADD BLOCK PREDICATE Security.patientAccessPredicate(PatientID) ON dbo.Patients, ADD FILTER PREDICATE Security.patientAccessPredicate(PatientID) ON dbo.Visits, ADD BLOCK PREDICATE Security.patientAccessPredicate(PatientID) ON dbo.Visits go