Skip to content

Commit 267bb79

Browse files
committedAug 11, 2023
Add support for sqlite3_set_authorizer
1 parent b6fe02d commit 267bb79

File tree

2 files changed

+198
-1
lines changed

2 files changed

+198
-1
lines changed
 

‎src/easy_sqlite3.nim

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ export raw, len, toOpenArray, SQLiteError, SQLiteBlob, Statement, Database,
55
SqliteDataType, OpenFlag, enableSharedCache, initDatabase, exec, execM,
66
changes, lastInsertRowid, `[]=`, reset, step, withColumnBlob,
77
getParameterIndex, getColumnType, getColumn, ColumnDef, columns, `[]`,
8-
unpack, `=destroy`, newStatement, rows
8+
unpack, `=destroy`, newStatement, rows, setAuthorizer,
9+
AuthorizerActionCode, AuthorizerRequest, AuthorizerResult, RawAuthorizer,
10+
Authorizer

‎src/easy_sqlite3/bindings.nim

+195
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,102 @@ func compileTimeHash[T](original: static[T]): CachedHash[T] =
6060
type Statement* = object
6161
raw*: ptr RawStatement
6262

63+
type
64+
AuthorizerResult* {.pure, size: sizeof(cint).} = enum
65+
ok = 0,
66+
deny = 1,
67+
ignore = 2
68+
AuthorizerActionCode* {.pure, size: sizeof(cint).} = enum
69+
# action code # arg3 arg4
70+
copy = 0, # No longer used
71+
create_index = 1, # Index Name Table Name
72+
create_table = 2, # Table Name NULL
73+
create_temp_index = 3, # Index Name Table Name
74+
create_temp_table = 4, # Table Name NULL
75+
create_temp_trigger = 5, # Trigger Name Table Name
76+
create_temp_view = 6, # View Name NULL
77+
create_trigger = 7, # Trigger Name Table Name
78+
create_view = 8, # View Name NULL
79+
delete = 9, # Table Name NULL
80+
drop_index = 10, # Index Name Table Name
81+
drop_table = 11, # Table Name NULL
82+
drop_temp_index = 12, # Index Name Table Name
83+
drop_temp_table = 13, # Table Name NULL
84+
drop_temp_trigger = 14, # Trigger Name Table Name
85+
drop_temp_view = 15, # View Name NULL
86+
drop_trigger = 16, # Trigger Name Table Name
87+
drop_view = 17, # View Name NULL
88+
insert = 18, # Table Name NULL
89+
pragma = 19, # Pragma Name 1st arg or NULL
90+
read = 20, # Table Name Column Name
91+
select = 21, # NULL NULL
92+
transaction = 22, # Operation NULL
93+
update = 23, # Table Name Column Name
94+
attach = 24, # Filename NULL
95+
detach = 25, # Database Name NULL
96+
alter_table = 26, # Database Name Table Name
97+
reindex = 27, # Index Name NULL
98+
analyze = 28, # Table Name NULL
99+
create_vtable = 29, # Table Name Module Name
100+
drop_vtable = 30, # Table Name Module Name
101+
function = 31, # NULL Function Name
102+
savepoint = 32, # Operation Savepoint Name
103+
recursive = 33, # NULL NULL
104+
AuthorizerRequest* = ref object
105+
case action_code*: AuthorizerActionCode
106+
of create_index, create_temp_index, drop_index, drop_temp_index:
107+
index_name*: string
108+
index_table_name*: string
109+
of create_table, create_temp_table, delete, drop_table, drop_temp_table, insert, analyze:
110+
table_name*: string
111+
of create_temp_trigger, create_trigger, drop_temp_trigger, drop_trigger:
112+
trigger_name*: string
113+
trigger_table_name*: string
114+
of create_temp_view, create_view, drop_temp_view, drop_view:
115+
view_name*: string
116+
of pragma:
117+
pragma_name*: string
118+
pragma_arg*: Option[string]
119+
of read, update:
120+
target_table_name*: string
121+
column_name*: string
122+
of select, recursive, copy:
123+
discard
124+
of transaction:
125+
transaction_operation*: string
126+
of attach:
127+
filename*: string
128+
of detach:
129+
database_name*: string
130+
of alter_table:
131+
alter_database_name*: string
132+
alter_table_name*: string
133+
of reindex:
134+
reindex_index_name*: string
135+
of create_vtable, drop_vtable:
136+
vtable_name*: string
137+
module_name*: string
138+
of function:
139+
# no arg3
140+
function_name*: string
141+
of savepoint:
142+
savepoint_operation*: string
143+
savepoint_name*: string
144+
SqliteRawAuthorizer* = proc(
145+
userdata: pointer,
146+
action_code: AuthorizerActionCode,
147+
arg3, arg4, arg5, arg6: cstring): AuthorizerResult {.cdecl.}
148+
RawAuthorizer* = proc(
149+
action_code: AuthorizerActionCode,
150+
arg3, arg4, arg5, arg6: Option[string]): AuthorizerResult
151+
Authorizer* = proc(request: AuthorizerRequest): AuthorizerResult
152+
WrapAuthorizer = object
153+
authorizer: RawAuthorizer
154+
63155
type Database* = object
64156
raw*: ptr RawDatabase
65157
stmtcache: Table[CachedHash[string], ref Statement]
158+
authorizer: ref WrapAuthorizer
66159

67160
type ResultCode* {.pure.} = enum
68161
sr_ok = 0,
@@ -374,6 +467,7 @@ proc sqlite3_prepare_v3*(db: ptr RawDatabase, sql: cstring, nbyte: int, flags: P
374467
proc sqlite3_finalize*(st: ptr RawStatement): ResultCode {.sqlite3linkage.}
375468
proc sqlite3_reset*(st: ptr RawStatement): ResultCode {.sqlite3linkage.}
376469
proc sqlite3_step*(st: ptr RawStatement): ResultCode {.sqlite3linkage.}
470+
proc sqlite3_set_authorizer*(db: ptr RawDatabase, auth: SqliteRawAuthorizer, userdata: pointer): ResultCode {.sqlite3linkage.}
377471
proc sqlite3_bind_parameter_index*(st: ptr RawStatement, name: cstring): int {.sqlite3linkage.}
378472
proc sqlite3_bind_blob64*(st: ptr RawStatement, idx: int, buffer: pointer, len: int, free: SqliteDestroctor): ResultCode {.sqlite3linkage.}
379473
proc sqlite3_bind_double*(st: ptr RawStatement, idx: int, value: float64): ResultCode {.sqlite3linkage.}
@@ -444,6 +538,107 @@ proc initDatabase*(
444538
sqliteCheck sqlite3_open_v2(filename, addr result.raw, flags, vfs)
445539
result.stmtcache = initTable[CachedHash[string], ref Statement]()
446540

541+
proc toS(s: cstring): Option[string] =
542+
if s == nil:
543+
result = none(string)
544+
else:
545+
result = some($s)
546+
547+
proc setAuthorizer*(db: var Database, callback: RawAuthorizer = nil) =
548+
let userdata: ref WrapAuthorizer = new(WrapAuthorizer)
549+
userdata.authorizer = callback
550+
551+
proc raw_callback(
552+
userdata: pointer,
553+
action_code: AuthorizerActionCode,
554+
arg3, arg4, arg5, arg6: cstring): AuthorizerResult {.cdecl.} =
555+
let callback = cast[ref WrapAuthorizer](userdata).authorizer
556+
callback(action_code, arg3.toS(), arg4.toS(), arg5.toS(), arg6.toS())
557+
558+
var res: ResultCode
559+
if callback == nil:
560+
res = db.raw.sqlite3_set_authorizer(nil, nil)
561+
else:
562+
res = db.raw.sqlite3_set_authorizer(raw_callback, cast[pointer](userdata))
563+
db.authorizer = userdata
564+
if res != ResultCode.sr_ok:
565+
raise newSQLiteError res
566+
567+
proc setAuthorizer*(db: var Database, callback: Authorizer = nil) =
568+
var raw_callback: RawAuthorizer = nil
569+
if callback != nil:
570+
raw_callback = proc(code: AuthorizerActionCode, arg3, arg4, arg5, arg6: Option[string]): AuthorizerResult =
571+
var req: AuthorizerRequest
572+
case code
573+
of create_index, create_temp_index, drop_index, drop_temp_index:
574+
req = AuthorizerRequest(
575+
action_code: code,
576+
index_name: arg3.get,
577+
index_table_name: arg4.get)
578+
of create_table, create_temp_table, delete, drop_table, drop_temp_table, insert, analyze:
579+
req = AuthorizerRequest(
580+
action_code: code,
581+
table_name: arg3.get)
582+
of create_temp_trigger, create_trigger, drop_temp_trigger, drop_trigger:
583+
req = AuthorizerRequest(
584+
action_code: code,
585+
trigger_name: arg3.get,
586+
trigger_table_name: arg4.get)
587+
of create_temp_view, create_view, drop_temp_view, drop_view:
588+
req = AuthorizerRequest(
589+
action_code: code,
590+
view_name: arg3.get)
591+
of pragma:
592+
req = AuthorizerRequest(
593+
action_code: code,
594+
pragma_name: arg3.get,
595+
pragma_arg: arg4)
596+
of read, update:
597+
req = AuthorizerRequest(
598+
action_code: code,
599+
target_table_name: arg3.get,
600+
column_name: arg4.get)
601+
of select, recursive, copy:
602+
req = AuthorizerRequest(action_code: code)
603+
of transaction:
604+
req = AuthorizerRequest(
605+
action_code: code,
606+
transaction_operation: arg3.get)
607+
of attach:
608+
req = AuthorizerRequest(
609+
action_code: code,
610+
filename: arg3.get)
611+
of detach:
612+
req = AuthorizerRequest(
613+
action_code: code,
614+
database_name: arg3.get)
615+
of alter_table:
616+
req = AuthorizerRequest(
617+
action_code: code,
618+
alter_database_name: arg3.get,
619+
alter_table_name: arg4.get)
620+
of reindex:
621+
req = AuthorizerRequest(
622+
action_code: code,
623+
reindex_index_name: arg3.get)
624+
of create_vtable, drop_vtable:
625+
req = AuthorizerRequest(
626+
action_code: code,
627+
vtable_name: arg3.get,
628+
module_name: arg4.get)
629+
of function:
630+
req = AuthorizerRequest(
631+
action_code: code,
632+
# no arg3
633+
function_name: arg4.get)
634+
of savepoint:
635+
req = AuthorizerRequest(
636+
action_code: code,
637+
savepoint_operation: arg3.get,
638+
savepoint_name: arg4.get)
639+
return callback(req)
640+
db.setAuthorizer(raw_callback)
641+
447642
proc changes*(st: var Database): int =
448643
sqlite3_changes st.raw
449644

0 commit comments

Comments
 (0)
Please sign in to comment.