[yunqa.de] Re: Authorizer example

  • From: Delphi Inspiration <delphi@xxxxxxxx>
  • To: yunqa@xxxxxxxxxxxxx
  • Date: Mon, 23 Jun 2008 22:38:57 +0200

Jerry Hayes wrote:

>Does anyone have an example of using the Authorizer?

The attached project implements a monitor authorizer callback which resolves 
action variables to meaningful text info. Some example SQL is provided, and you 
can add your own for more testing.

Please share your improvement suggestions. I intend to add this project to the 
DISQLite3 demos with the next release.

>Also, is the FIELDNAME ever passed to the authorizer, such as in an update or 
>select?

Yes, the column name is passed with these actions:
  
* SQLITE_READ 
* SQLITE_UPDATE 

A table with all actions and their parameters is part of the 
"sqlite3_set_authorizer" help entry.

Ralf 
{ DISQLite3 project to monitor the authorizer working.

  Visit the DISQLite3 Internet site for latest information and updates:

    http://www.yunqa.de/delphi/

  Copyright (c) 2005-2008 Ralf Junker, The Delphi Inspiration <delphi@xxxxxxxx>

------------------------------------------------------------------------------ }

program DISQLite3_Authorizer;

{$APPTYPE CONSOLE}
{$I DI.inc}
{$I DISQLite3.inc}

{$IFDEF DISQLite3_Personal}
!!! This project requires functionality not available with DISQLite3 personal 
!!!
!!! Download DISQLite3 Professional from http://www.yunqa.de !!!
{$ENDIF DISQLite3_Personal}

uses
  {$IFDEF FastMM}FastMM4, {$ENDIF}SysUtils, DISQLite3Api;

type
  TAuthorizerText = record
    a2: Integer;
    t2: PAnsiChar;
    t3: PAnsiChar;
    t4: PAnsiChar;
  end;

const
  a: array[0..30] of TAuthorizerText = (
    (a2: SQLITE_CREATE_INDEX; t2: 'SQLITE_CREATE_INDEX'; t3: 'Index Name'; t4: 
'Table Name'),
    (a2: SQLITE_CREATE_TABLE; t2: 'SQLITE_CREATE_TABLE'; t3: 'Table Name'),
    (a2: SQLITE_CREATE_TEMP_INDEX; t2: 'SQLITE_CREATE_TEMP_INDEX'; t3: 'Index 
Name'; t4: 'Table Name'),
    (a2: SQLITE_CREATE_TEMP_TABLE; t2: 'SQLITE_CREATE_TEMP_TABLE'; t3: 'Table 
Name'),
    (a2: SQLITE_CREATE_TEMP_TRIGGER; t2: 'SQLITE_CREATE_TEMP_TRIGGER'; t3: 
'Trigger Name'; t4: 'Table Name'),
    (a2: SQLITE_CREATE_TEMP_VIEW; t2: 'SQLITE_CREATE_TEMP_VIEW'; t3: 'View 
Name'),
    (a2: SQLITE_CREATE_TRIGGER; t2: 'SQLITE_CREATE_TRIGGER'; t3: 'Trigger 
Name'; t4: 'Table Name'),
    (a2: SQLITE_CREATE_VIEW; t2: 'SQLITE_CREATE_VIEW'; t3: 'View Name'),
    (a2: SQLITE_DELETE; t2: 'SQLITE_DELETE'; t3: 'Table Name'),
    (a2: SQLITE_DROP_INDEX; t2: 'SQLITE_DROP_INDEX'; t3: 'Index Name'; t4: 
'Table Name'),
    (a2: SQLITE_DROP_TABLE; t2: 'SQLITE_DROP_TABLE'; t3: 'Table Name'),
    (a2: SQLITE_DROP_TEMP_INDEX; t2: 'SQLITE_DROP_TEMP_INDEX'; t3: 'Index 
Name'; t4: 'Table Name'),
    (a2: SQLITE_DROP_TEMP_TABLE; t2: 'SQLITE_DROP_TEMP_TABLE'; t3: 'Table 
Name'),
    (a2: SQLITE_DROP_TEMP_TRIGGER; t2: 'SQLITE_DROP_TEMP_TRIGGER'; t3: 'Trigger 
Name'; t4: 'Table Name'),
    (a2: SQLITE_DROP_TEMP_VIEW; t2: 'SQLITE_DROP_TEMP_VIEW'; t3: 'View Name'),
    (a2: SQLITE_DROP_TRIGGER; t2: 'SQLITE_DROP_TRIGGER'; t3: 'Trigger Name'; 
t4: 'Table Name'),
    (a2: SQLITE_DROP_VIEW; t2: 'SQLITE_DROP_VIEW'; t3: 'View Name'),
    (a2: SQLITE_INSERT; t2: 'SQLITE_INSERT'; t3: 'Table Name'),
    (a2: SQLITE_PRAGMA; t2: 'SQLITE_PRAGMA'; t3: 'Pragma Name'; t4: '1st arg or 
NULL'),
    (a2: SQLITE_READ; t2: 'SQLITE_READ'; t3: 'Table Name'; t4: 'Column Name'),
    (a2: SQLITE_SELECT; t2: 'SQLITE_SELECT'),
    (a2: SQLITE_TRANSACTION; t2: 'SQLITE_TRANSACTION'),
    (a2: SQLITE_UPDATE; t2: 'SQLITE_UPDATE'; t3: 'Table Name'; t4: 'Column 
Name'),
    (a2: SQLITE_ATTACH; t2: 'SQLITE_ATTACH'; t3: 'Filename'),
    (a2: SQLITE_DETACH; t2: 'SQLITE_DETACH'; t3: 'Database Name'),
    (a2: SQLITE_ALTER_TABLE; t2: 'SQLITE_ALTER_TABLE'; t3: 'Database Name'; t4: 
'Table Name'),
    (a2: SQLITE_REINDEX; t2: 'SQLITE_REINDEX'; t3: 'Index Name'),
    (a2: SQLITE_ANALYZE; t2: 'SQLITE_ANALYZE'; t3: 'Table Name'),
    (a2: SQLITE_CREATE_VTABLE; t2: 'SQLITE_CREATE_VTABLE'; t3: 'Table Name'; 
t4: 'Module Name'),
    (a2: SQLITE_DROP_VTABLE; t2: 'SQLITE_DROP_VTABLE'; t3: 'Table Name'; t4: 
'Module Name'),
    (a2: SQLITE_FUNCTION; t2: 'SQLITE_FUNCTION'; t3: 'Function Name')
    );

function Authorizer_Callback(
  UserData: Pointer;
  Arg2: Integer;
  Arg3: PAnsiChar;
  Arg4: PAnsiChar;
  Arg5: PAnsiChar;
  Arg6: PAnsiChar): Integer;
var
  i: Integer;
begin
  { Arg2 contains the authorizer action. Resolve the text information. }
  i := Low(a);
  repeat
    if a[i].a2 = Arg2 then Break;
    Inc(i);
  until i > High(a);

  if i <= High(a) then
    begin
      { Arg2 always contains the authorizer action. }
      WriteLn(a[i].t2, ' (', i, ')');
      { Arg3 and Arg4 are variable strings, depending on the Arg2 action. }
      if Assigned(a[i].t3) then
        WriteLn(a[i].t3, ': ', Arg3);
      if Assigned(a[i].t4) then
        WriteLn(a[i].t4, ': ', Arg4);
      { Arg5 always contains the database name. }
      WriteLn('Database: ', Arg5);
      { Arg6 contains the innermost trigger name, if assigned. }
      if Assigned(Arg6) then
        WriteLn('Trigger: ', Arg6);
    end
  else
    begin
      { In case new actions are added which are not yet covered here. }
      WriteLn('Invalid Arg2: ', i);
    end;

  Result := SQLITE_OK; // Authorize all actions.
end;

//------------------------------------------------------------------------------

var
  DB: sqlite3;

procedure Exec(const SQL: AnsiString);
begin
  WriteLn;
  WriteLn('SQL: ', SQL);
  sqlite3_exec_fast(DB, SQL);
end;

begin
  DeleteFile('test.db3');
  sqlite3_open('test.db3', @DB);

  sqlite3_set_authorizer(DB, Authorizer_Callback, nil);

  Exec('create table t(a)');

  Exec('insert into t values(1)');
  Exec('insert into t values(2)');
  Exec('update t set a = 3');
  Exec('delete from t');

  sqlite3_check(sqlite3_close(DB), DB);

  WriteLn;
  WriteLn('Done - Press ENTER to Exit');
  ReadLn;
end.

Other related posts: