USE [Elyse_DB] GO /****** Object: StoredProcedure [internal].[usp_AUTHENTICATE_file_ed_free] Script Date: Fri 02-10-2026 8:29:40 PM ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Silkwood Software -- Create date: 27-12-2023 /* Description: Check if a file is free from edit restrictions for the connected user This is not the same as checking if the user has edit permission for the file. By default a user does not have edit permission for a file unless it is explicitly granted This check establishes if either the file is free from any edit permission restrictions or the user already has edit permission. The procedure is used to check if it is ok for a user to grant theselves edit permission for the given file. Otherwise permission must be granted by a controler If the connected user SID exists in any pathway then the check passes If there are no SIDs for any user linked in any pathway the the check passes In all other cases the check fails. Input is the file ID to check. Output is a user authentication status indicating 'Pass' or 'Fail'. */ /* COPYRIGHT NOTICE This database schema and stored procedures are protected by copyright. Copyright. Silkwood Software Pty. Ltd. 2023 */ -- ============================================= CREATE PROCEDURE [internal].[usp_AUTHENTICATE_file_ed_free] @fileid_tocheck bigint, @user_authentication_reslt_fgef nvarchar(10) OUTPUT AS BEGIN SET NOCOUNT ON; -- Declare variables DECLARE @usersid varbinary(100) = NULL, -- The SID of the connected user @fileiscontrollergroup nvarchar(5) = NULL, @sid_id bigint = NULL, @failure_type nvarchar(1000) = NULL, @now datetime2(7) = SYSDATETIME(), @privilege_name nvarchar(50) = ''; SET @usersid = SUSER_SID(ORIGINAL_LOGIN()); -- Read the SID of the connected user SELECT @sid_id = sid_id FROM user_restr.sid_list WHERE sid = @usersid; -- Default user authentication result to Fail SET @user_authentication_reslt_fgef = 'Fail'; -- Fail if the file is linked to any controller edit group. -- Otherwise: -- Pass if the file is linked to a SID that includes the connected user. -- Pass if the file is not linked to any SIDs -- Fail otherwise IF EXISTS -- Is the file id linked to a controller group? (SELECT cfgl.file_id FROM xref.controller_file_group_links AS cfgl WHERE cfgl.file_id = @fileid_tocheck) BEGIN SET @fileiscontrollergroup = 'Yes'; SET @user_authentication_reslt_fgef = 'Fail'; END ELSE SET @fileiscontrollergroup = 'No'; IF @fileiscontrollergroup = 'No' -- File listed in a controller group overrides other permissions BEGIN -- Check if the connected user SID is linked through either pathway IF EXISTS ( SELECT fgl.file_group_id -- Check through duty function lists FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_funct_lst AS fgepfl ON fgl.file_group_id = fgepfl.file_group_id INNER JOIN people.function_lists AS fl ON fgepfl.function_list_id = fl.function_list_id INNER JOIN people.duty_functions AS df ON fl.function_id = df.function_id INNER JOIN people.duty_function_sid_links AS dfsl ON df.function_id = dfsl.function_id INNER JOIN user_restr.sid_list AS sl ON dfsl.sid_id = sl.sid_id WHERE fgl.file_id = @fileid_tocheck AND sl.sid = @usersid -- Check time-bound restrictions AND (fgepfl.valid_from IS NULL OR fgepfl.valid_from <= @now) AND (fgepfl.valid_until IS NULL OR fgepfl.valid_until >= @now) AND (fl.valid_from IS NULL OR fl.valid_from <= @now) AND (fl.valid_until IS NULL OR fl.valid_until >= @now) AND (dfsl.valid_from IS NULL OR dfsl.valid_from <= @now) AND (dfsl.valid_until IS NULL OR dfsl.valid_until >= @now) UNION SELECT fgl.file_group_id -- Check through people lists FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_ppl_lst AS fgeppl ON fgl.file_group_id = fgeppl.file_group_id INNER JOIN people.people_lists AS pl ON fgeppl.people_list_id = pl.people_list_id INNER JOIN user_restr.sid_list AS sl ON pl.sid_id = sl.sid_id WHERE fgl.file_id = @fileid_tocheck AND sl.sid = @usersid -- Check time-bound restrictions AND (fgeppl.valid_from IS NULL OR fgeppl.valid_from <= @now) AND (fgeppl.valid_until IS NULL OR fgeppl.valid_until >= @now) AND (pl.valid_from IS NULL OR pl.valid_from <= @now) AND (pl.valid_until IS NULL OR pl.valid_until >= @now) ) BEGIN -- If the file is linked to SIDs that include the connected user, set result to Pass SET @user_authentication_reslt_fgef = 'Pass'; END -- Check if the file is not linked to any SID IF @user_authentication_reslt_fgef = 'Fail' -- The connected user SID has not been already found to be linked AND NOT EXISTS ( SELECT fgl.file_group_id -- Check through duty function lists FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_funct_lst AS fgepfl ON fgl.file_group_id = fgepfl.file_group_id INNER JOIN people.function_lists AS fl ON fgepfl.function_list_id = fl.function_list_id INNER JOIN people.duty_functions AS df ON fl.function_id = df.function_id INNER JOIN people.duty_function_sid_links AS dfsl ON df.function_id = dfsl.function_id INNER JOIN user_restr.sid_list AS sl ON dfsl.sid_id = sl.sid_id WHERE fgl.file_id = @fileid_tocheck UNION SELECT fgl.file_group_id -- Check through people lists FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_ppl_lst AS fgeppl ON fgl.file_group_id = fgeppl.file_group_id INNER JOIN people.people_lists AS pl ON fgeppl.people_list_id = pl.people_list_id INNER JOIN user_restr.sid_list AS sl ON pl.sid_id = sl.sid_id WHERE fgl.file_id = @fileid_tocheck ) BEGIN -- If the file is not linked to any users, set result to Pass SET @user_authentication_reslt_fgef = 'Pass'; END END -- END IF @fileiscontrollergroup = 'No' -- File listed in a controller group overrides other permissions -- The result is returned via the OUTPUT parameter IF @user_authentication_reslt_fgef = 'Fail' BEGIN -- ============================================================================================ -- Authorisation failure diagnostics -- ============================================================================================ -- -- This procedure checks whether a file is free from edit restrictions. -- Failure occurs when: -- 1. The file is in a controller group (overrides all other permissions), OR -- 2. The file has edit restrictions (users ARE linked) but the connected -- user is not among them, or their permissions have expired. -- -- The "no users linked" case is a Pass, so it never reaches diagnostics. -- ============================================================================================ DECLARE @controller_failure nvarchar(1000) = NULL, @function_failure nvarchar(1000) = NULL, @people_failure nvarchar(1000) = NULL; -- ============================================================================================ -- CONTROLLER GROUP CHECK -- ============================================================================================ IF @fileiscontrollergroup = 'Yes' BEGIN SET @controller_failure = 'File is linked to a Controller File Group'; END; -- ============================================================================================ -- FUNCTION LIST PATH -- -- File -- -> File Group -- -> Function List Edit Authorisation (fgepfl) -- -> Function List (fl) -- -> Duty Function (df) -- -> User SID (dfsl -> sl) -- -- Time-bound restrictions: -- fgepfl.valid_from / valid_until -- fl.valid_from / valid_until -- dfsl.valid_from / valid_until -- ============================================================================================ IF @fileiscontrollergroup = 'No' BEGIN -- Check that the file is linked to a file group IF NOT EXISTS ( SELECT 1 FROM xref.file_group_links AS fgl WHERE fgl.file_id = @fileid_tocheck ) BEGIN SET @function_failure = CONCAT_WS('; ', @function_failure, 'Function Path: File Group Link Not Found' ); END ELSE BEGIN -- Check for a Function List edit authorisation IF NOT EXISTS ( SELECT 1 FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_funct_lst AS fgepfl ON fgl.file_group_id = fgepfl.file_group_id WHERE fgl.file_id = @fileid_tocheck ) BEGIN SET @function_failure = CONCAT_WS('; ', @function_failure, 'Function Path: Edit Authorisation Not Found' ); END ELSE BEGIN -- Check validity of the file-group / function-list authorisation IF NOT EXISTS ( SELECT 1 FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_funct_lst AS fgepfl ON fgl.file_group_id = fgepfl.file_group_id WHERE fgl.file_id = @fileid_tocheck AND (fgepfl.valid_from IS NULL OR fgepfl.valid_from <= @now) AND (fgepfl.valid_until IS NULL OR fgepfl.valid_until >= @now) ) BEGIN SET @function_failure = CONCAT_WS('; ', @function_failure, 'Function Path: Edit Authorisation Not Currently Valid' ); END; -- Check that the Function List exists IF NOT EXISTS ( SELECT 1 FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_funct_lst AS fgepfl ON fgl.file_group_id = fgepfl.file_group_id INNER JOIN people.function_lists AS fl ON fgepfl.function_list_id = fl.function_list_id WHERE fgl.file_id = @fileid_tocheck ) BEGIN SET @function_failure = CONCAT_WS('; ', @function_failure, 'Function Path: Function List Not Found' ); END ELSE BEGIN -- Check Function List validity IF NOT EXISTS ( SELECT 1 FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_funct_lst AS fgepfl ON fgl.file_group_id = fgepfl.file_group_id INNER JOIN people.function_lists AS fl ON fgepfl.function_list_id = fl.function_list_id WHERE fgl.file_id = @fileid_tocheck AND (fl.valid_from IS NULL OR fl.valid_from <= @now) AND (fl.valid_until IS NULL OR fl.valid_until >= @now) ) BEGIN SET @function_failure = CONCAT_WS('; ', @function_failure, 'Function Path: Function List Not Currently Valid' ); END; -- Check whether the Function List ultimately provides -- a SID link for this user IF NOT EXISTS ( SELECT 1 FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_funct_lst AS fgepfl ON fgl.file_group_id = fgepfl.file_group_id INNER JOIN people.function_lists AS fl ON fgepfl.function_list_id = fl.function_list_id INNER JOIN people.duty_functions AS df ON fl.function_id = df.function_id INNER JOIN people.duty_function_sid_links AS dfsl ON df.function_id = dfsl.function_id INNER JOIN user_restr.sid_list AS sl ON dfsl.sid_id = sl.sid_id WHERE fgl.file_id = @fileid_tocheck AND sl.sid = @usersid ) BEGIN SET @function_failure = CONCAT_WS('; ', @function_failure, 'Function Path: User Not Linked Through Duty Function' ); END ELSE BEGIN -- Check validity of the complete function-to-user path IF NOT EXISTS ( SELECT 1 FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_funct_lst AS fgepfl ON fgl.file_group_id = fgepfl.file_group_id INNER JOIN people.function_lists AS fl ON fgepfl.function_list_id = fl.function_list_id INNER JOIN people.duty_functions AS df ON fl.function_id = df.function_id INNER JOIN people.duty_function_sid_links AS dfsl ON df.function_id = dfsl.function_id INNER JOIN user_restr.sid_list AS sl ON dfsl.sid_id = sl.sid_id WHERE fgl.file_id = @fileid_tocheck AND sl.sid = @usersid -- File Group / Function List authorisation AND (fgepfl.valid_from IS NULL OR fgepfl.valid_from <= @now) AND (fgepfl.valid_until IS NULL OR fgepfl.valid_until >= @now) -- Function List AND (fl.valid_from IS NULL OR fl.valid_from <= @now) AND (fl.valid_until IS NULL OR fl.valid_until >= @now) -- Duty Function / User link AND (dfsl.valid_from IS NULL OR dfsl.valid_from <= @now) AND (dfsl.valid_until IS NULL OR dfsl.valid_until >= @now) ) BEGIN SET @function_failure = CONCAT_WS('; ', @function_failure, 'Function Path: One or More Authorisation Links Not Currently Valid' ); END; END; END; END; END; -- ============================================================================================ -- PEOPLE LIST PATH -- -- File -- -> File Group -- -> People List Edit Authorisation (fgeppl) -- -> People List (pl) -- -> User SID (sl) -- -- Time-bound restrictions: -- fgeppl.valid_from / valid_until -- pl.valid_from / valid_until -- ============================================================================================ -- Check that the file is linked to a file group IF NOT EXISTS ( SELECT 1 FROM xref.file_group_links AS fgl WHERE fgl.file_id = @fileid_tocheck ) BEGIN SET @people_failure = CONCAT_WS('; ', @people_failure, 'People Path: File Group Link Not Found' ); END ELSE BEGIN -- Check for a People List edit authorisation IF NOT EXISTS ( SELECT 1 FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_ppl_lst AS fgeppl ON fgl.file_group_id = fgeppl.file_group_id WHERE fgl.file_id = @fileid_tocheck ) BEGIN SET @people_failure = CONCAT_WS('; ', @people_failure, 'People Path: Edit Authorisation Not Found' ); END ELSE BEGIN -- Check validity of the file-group / people-list authorisation IF NOT EXISTS ( SELECT 1 FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_ppl_lst AS fgeppl ON fgl.file_group_id = fgeppl.file_group_id WHERE fgl.file_id = @fileid_tocheck AND (fgeppl.valid_from IS NULL OR fgeppl.valid_from <= @now) AND (fgeppl.valid_until IS NULL OR fgeppl.valid_until >= @now) ) BEGIN SET @people_failure = CONCAT_WS('; ', @people_failure, 'People Path: Edit Authorisation Not Currently Valid' ); END; -- Check that the People List exists and contains the user's SID IF NOT EXISTS ( SELECT 1 FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_ppl_lst AS fgeppl ON fgl.file_group_id = fgeppl.file_group_id INNER JOIN people.people_lists AS pl ON fgeppl.people_list_id = pl.people_list_id INNER JOIN user_restr.sid_list AS sl ON pl.sid_id = sl.sid_id WHERE fgl.file_id = @fileid_tocheck AND sl.sid = @usersid ) BEGIN -- Distinguish a missing People List from a People List -- which exists but does not contain the user IF NOT EXISTS ( SELECT 1 FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_ppl_lst AS fgeppl ON fgl.file_group_id = fgeppl.file_group_id INNER JOIN people.people_lists AS pl ON fgeppl.people_list_id = pl.people_list_id WHERE fgl.file_id = @fileid_tocheck ) BEGIN SET @people_failure = CONCAT_WS('; ', @people_failure, 'People Path: People List Not Found' ); END ELSE BEGIN SET @people_failure = CONCAT_WS('; ', @people_failure, 'People Path: User Not a Member of People List' ); END; END ELSE BEGIN -- Check validity of the complete people-list-to-user path IF NOT EXISTS ( SELECT 1 FROM xref.file_group_links AS fgl INNER JOIN user_restr.file_group_edit_perm_ppl_lst AS fgeppl ON fgl.file_group_id = fgeppl.file_group_id INNER JOIN people.people_lists AS pl ON fgeppl.people_list_id = pl.people_list_id INNER JOIN user_restr.sid_list AS sl ON pl.sid_id = sl.sid_id WHERE fgl.file_id = @fileid_tocheck AND sl.sid = @usersid -- File Group / People List authorisation AND (fgeppl.valid_from IS NULL OR fgeppl.valid_from <= @now) AND (fgeppl.valid_until IS NULL OR fgeppl.valid_until >= @now) -- People List AND (pl.valid_from IS NULL OR pl.valid_from <= @now) AND (pl.valid_until IS NULL OR pl.valid_until >= @now) ) BEGIN SET @people_failure = CONCAT_WS('; ', @people_failure, 'People Path: One or More Authorisation Links Not Currently Valid' ); END; END; END; END; END; -- END IF @fileiscontrollergroup = 'No' diagnostics -- ============================================================================================ -- COMBINE ALL FAILURE DIAGNOSTICS -- ============================================================================================ SET @failure_type = CONCAT_WS('; ', @controller_failure, @function_failure, @people_failure ); -- End authorisation failure diagnostics -- ============================================================================================ -- Write to authorisation fail log INSERT INTO user_restr.authorisation_fail_log (sid_id, privilege_type, privilege_id, privilege_name, stored_procedure, failure_type) VALUES ( @sid_id, 'File Edit Free Check', @fileid_tocheck, @privilege_name, '[internal].[usp_AUTHENTICATE_file_ed_free]', @failure_type ) END -- END IF @user_authentication_reslt_fgef = 'Fail' END GO