USE [Elyse_DB]
GO
/****** Object:  StoredProcedure [reading].[usp_SEL_file]    Script Date: Mon 07-09-2026 7:26:41 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		Silkwood Software
-- Create date: 09-07-2023
-- Description:	Initial creation
-- This procedure reads the contents of a file.
-- Input is the file ID.  Output is the binary file,
-- the filename, and a message. 
-- If the user does not have Reader, Reviewer, Editor or Controller privileges then
-- the file can only be accessed if it passes the default filter group filter. 
/*
COPYRIGHT NOTICE
This database schema and stored procedures are protected by copyright.
Copyright.  Silkwood Software Pty. Ltd. 2023
*/

-- =============================================
CREATE PROCEDURE [reading].[usp_SEL_file]

    @fileid bigint                   = NULL,
	@notes nvarchar(1000)            = '', -- Optional
	@app_reference nvarchar(1000)    = '', -- Optional
	@filename nvarchar(255)          = NULL OUTPUT,
	@filesize bigint                 = NULL OUTPUT,
    @message nvarchar(1000)          = NULL OUTPUT,
	@transaction_status nvarchar(50) = NULL OUTPUT	

AS
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	SET NOCOUNT ON;

  DECLARE
        @tempmessage nvarchar(300)         = '',
		@fileauthenticationstatus nchar(10)     = '', -- Communicates if the user is not authorised to access the file
		                                              -- or alternatively if the file does not exist.  The result does not distinguish either. 	
	    @userauthentication_status nchar(10)    = 'Fail', -- The outcome of the authentication check of the user 
	    @temp_userauth_status nchar(10)         = 'Fail',				
		@filtergroupid bigint                   = NULL, -- The default filter group
	    @connectedusersid varbinary(100)         = SUSER_SID(ORIGINAL_LOGIN()),   -- The SID of the connected user
		@sidid bigint                            = NULL,  
		@transaction_ready nchar(10)       = 'Ready',
        @data_validation_status nchar(10)  = 'Pass';

  -- Parameters which have been initialised at declaration but not explicitly set might be output as null to calling functions.
  SET @transaction_status = 'Transaction not attempted';  

  -- Check if the user has any of the following privileges.
  -- This is a check NOT to determine whether the user can execute this stored procedure.
  -- All users can execute this stored procedure.  
  -- This check is used later to check if the user is permitted to access the file. 

  EXEC [internal].[usp_AUTHENTICATE_user_role] 
        @role_to_check = 'Controller',
		@user_authentication_result = @temp_userauth_status OUTPUT;
  IF @temp_userauth_status = 'Pass' SET @userauthentication_status = 'Pass';

  EXEC [internal].[usp_AUTHENTICATE_user_role] 
        @role_to_check = 'Editor',
		@user_authentication_result = @temp_userauth_status OUTPUT;
  IF @temp_userauth_status = 'Pass' SET @userauthentication_status = 'Pass';

  EXEC [internal].[usp_AUTHENTICATE_user_role] 
        @role_to_check = 'Reviewer',
		@user_authentication_result = @temp_userauth_status OUTPUT;
  IF @temp_userauth_status = 'Pass' SET @userauthentication_status = 'Pass';

  EXEC [internal].[usp_AUTHENTICATE_user_role] 
        @role_to_check = 'Reader',
		@user_authentication_result = @temp_userauth_status OUTPUT;
  IF @temp_userauth_status = 'Pass' SET @userauthentication_status = 'Pass';


  	-- Retrieve the default filter group
	SET @filtergroupid = (SELECT default_filter_group_id 
			                FROM base.global_settings_groups
			               WHERE base.global_settings_groups.setting_group_name = 'Master');
			 


   -- Check that the file id exists.  Fail if it doesn't.
  IF @fileid = 0
     SET @fileid = NULL;
  IF @fileid IS NULL
     BEGIN
	   SET @data_validation_status = 'Fail';
	   SET @transaction_ready      = 'Fail';
       EXEC internal.usp_SEL_message 
            @message_id = 'NoFileID', 
	        @message_text = @tempmessage OUTPUT;
  	   IF (@tempmessage IS NOT NULL) 
		   SET @message = CONCAT_WS(' | ', @message, @tempmessage);
	   ELSE  
		   SET @message = CONCAT_WS(' | ', @message, 'A database level message error occurred on NoFileID.');
	 END
  ELSE
     BEGIN 	-- Check if the file ID exists and the user has permission to access the file
			EXEC [internal].[usp_AUTHENTICATE_user_file_id] 
 				@file_id_to_check =  @fileid,
				@user_authentication_result = @fileauthenticationstatus OUTPUT;
				IF @fileauthenticationstatus = 'Fail'
					BEGIN -- File id does not exist or the user does not have permission to access it
						SET @data_validation_status = 'Fail';
						SET @transaction_ready      = 'Fail';
						EXEC internal.usp_SEL_message 
							@message_id = 'FileIDNotExist', 
							@message_text = @tempmessage OUTPUT;
  						IF @tempmessage IS NOT NULL 
							SET @message = CONCAT(@message, ' | ', 'File ID: ', CONVERT(nvarchar(20), @fileid), '.  ', @tempmessage);
						ELSE 
		                    SET @message = CONCAT_WS(' | ', @message, 'A database level message error occurred on FileIDNotExist.');
					END
				ELSE
				    BEGIN
					-- If the user does not have Reader, Reviewer, Editor or Controller privileges then
					-- the file cannot be accessed if it does not passes the default filter group filter. 
					IF @userauthentication_status = 'Fail' AND @filtergroupid IS NOT NULL
					   BEGIN
						IF NOT EXISTS -- Check if it does not pass the default filter group filter
								(
									SELECT 1
									WHERE NOT EXISTS
									(
										-- Fail if any required radio button attribute is missing
										SELECT 1
										FROM file_attr.file_radiob_attr_fgroup_links AS fgl
										WHERE fgl.filter_group_id = @filtergroupid
										  AND NOT EXISTS
										  (
											  SELECT 1
											  FROM file_attr.file_radio_button_links AS frbl
											  WHERE frbl.file_radiob_attr_id = fgl.file_radiob_attr_id
												AND frbl.file_id = @fileid
										  )
									)
									AND NOT EXISTS
									(
										-- Fail if any required multi-select attribute is missing
										SELECT 1
										FROM file_attr.file_ms_attr_fgroup_links AS fgl
										WHERE fgl.filter_group_id = @filtergroupid
										  AND NOT EXISTS
										  (
											  SELECT 1
											  FROM file_attr.file_multi_select_links AS fmsl
											  WHERE fmsl.file_ms_attr_id = fgl.file_ms_attr_id
												AND fmsl.file_id = @fileid
										  )
									)
								)
									BEGIN -- File fails the filter group.  
										SET @data_validation_status = 'Fail';
										SET @transaction_ready      = 'Fail';
										EXEC internal.usp_SEL_message 
											@message_id = 'FileFilterFail', 
											@message_text = @tempmessage OUTPUT;
  										IF @tempmessage IS NOT NULL 
											SET @message = CONCAT(@message, ' | ', 'File ID: ', CONVERT(nvarchar(20), @fileid), '.  ', @tempmessage);
										ELSE 
											SET @message = CONCAT_WS(' | ', @message, 'A database level message error occurred on FileFilterFail.');
									END
								END
					END -- END IF @userauthentication_status = 'Fail'
				
	 END   -- End checking if file id exists

  IF @data_validation_status = 'Fail'
    BEGIN
      EXEC internal.usp_SEL_message 
           @message_id   = 'FailedDataValidation', 
           @message_text = @tempmessage OUTPUT;
      IF @tempmessage IS NOT NULL 
		   SET @message = CONCAT_WS(' | ', @message, @tempmessage);
	  ELSE  
		   SET @message = CONCAT_WS(' | ', @message, 'A database level message error occurred on FailedDataValidation.');
	END
  -- End data validation

-- Select the filename, file size and content.  Other metadata can be retrieved elsewhere.  
-- Select the filename and file size separate from the content so that they will be in a separate
-- cursor element.  This reduces the risk that an application programming error will
-- embed the metadata into the file content.  It is expected that the transaction load on
-- this database will generally be low.

  IF @transaction_ready = 'Ready'
    BEGIN
      BEGIN TRY
	  
  -- Select the SID ID for the connected user
	  SELECT @sidid = sl.sid_id
		FROM user_restr.sid_list AS sl
	   WHERE sl.sid = @connectedusersid;

		   SELECT @filename = filename,
		          @filesize = file_size
			 FROM base.file_metadata
			WHERE file_id = @fileid;

           IF @filename IS NULL OR @filename = '' -- If the file_name field was NULL or empty then substitute the file id.
			    SET @filename = CONCAT('FileID', CONVERT(nvarchar(255),@fileid), '.unknown');

	   --   Write an entry in the file read log if it is enabled.
	  IF EXISTS (SELECT gsg.file_read_log 
	               FROM base.global_settings_groups AS gsg
		          WHERE gsg.setting_group_name = 'Master'
				    AND gsg.file_read_log = 'On')
		   BEGIN
		     INSERT INTO base.file_read_log
			             (file_id,  filename,  read_by_sid_id, notes, app_reference)
				  VALUES (@fileid, @filename, @sidid, @notes, @app_reference)  -- read_by_username is populated by the table column binding to (original_login())

		   END

           SELECT file_content AS 'File Content' 
             FROM base.file_storage 
	        WHERE file_id = @fileid;

	   IF @@ROWCOUNT > 0 -- If rowcount = 0 the TRY will still not be failed
	      BEGIN
	         EXEC internal.usp_SEL_message 
                  @message_id   = 'Success',
                  @message_text = @tempmessage OUTPUT;
  	         IF @tempmessage IS NOT NULL 
			   SET @message = CONCAT_WS(' | ', @message, @tempmessage);
			 ELSE  
			   SET @message = CONCAT_WS(' | ', @message, 'A database level message error occurred on Success.');
	         SET @transaction_status = 'Good';

	      END
	   ELSE
	      BEGIN
            SET @transaction_status = 'Bad';
           EXEC internal.usp_SEL_message 
                @message_id   = 'NotExist',
				@message_text = @tempmessage OUTPUT; 
  	         IF @tempmessage IS NOT NULL 
			   SET @message = CONCAT_WS(' | ', @message, @tempmessage);
			 ELSE  
			   SET @message = CONCAT_WS(' | ', @message, 'A database level message error occurred on NotExist.');
		  END
	  END TRY
	  BEGIN CATCH
        SET @transaction_status = 'Bad';
        EXEC internal.usp_SEL_message 
             @message_id   = 'SelectError', 
             @message_text = @tempmessage OUTPUT;
	    IF @tempmessage IS NOT NULL 
			SET @message = CONCAT_WS(' | ', @message, @tempmessage,  
			CONVERT(nvarchar(10),ERROR_NUMBER()), ERROR_MESSAGE());
		ELSE
			  SET @message = CONCAT_WS(' | ', @message, 'A database level message error occurred on SelectError');
	  END CATCH

	END -- End if transaction ready = 'Ready'

END
GO
