Skip to content

Commit 0eec847

Browse files
authored
Merge pull request #623 from graf0/feature/#619
implementation of set_authorizer interface
2 parents 3198c77 + df0c034 commit 0eec847

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

callback.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ func updateHookTrampoline(handle uintptr, op int, db *C.char, table *C.char, row
7777
callback(op, C.GoString(db), C.GoString(table), rowid)
7878
}
7979

80+
//export authorizerTrampoline
81+
func authorizerTrampoline(handle uintptr, op int, arg1 *C.char, arg2 *C.char, arg3 *C.char) int {
82+
callback := lookupHandle(handle).(func(int, string, string, string) int)
83+
return callback(op, C.GoString(arg1), C.GoString(arg2), C.GoString(arg3))
84+
}
85+
8086
// Use handles to avoid passing Go pointers to C.
8187

8288
type handleVal struct {

sqlite3.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ int commitHookTrampoline(void*);
119119
void rollbackHookTrampoline(void*);
120120
void updateHookTrampoline(void*, int, char*, char*, sqlite3_int64);
121121
122+
int authorizerTrampoline(void*, int, char*, char*, char*, char*);
123+
122124
#ifdef SQLITE_LIMIT_WORKER_THREADS
123125
# define _SQLITE_HAS_LIMIT
124126
# define SQLITE_LIMIT_LENGTH 0
@@ -200,9 +202,48 @@ func Version() (libVersion string, libVersionNumber int, sourceID string) {
200202
}
201203

202204
const (
205+
// used by authorizer and pre_update_hook
203206
SQLITE_DELETE = C.SQLITE_DELETE
204207
SQLITE_INSERT = C.SQLITE_INSERT
205208
SQLITE_UPDATE = C.SQLITE_UPDATE
209+
210+
// used by authorzier - as return value
211+
SQLITE_OK = C.SQLITE_OK
212+
SQLITE_IGNORE = C.SQLITE_IGNORE
213+
SQLITE_DENY = C.SQLITE_DENY
214+
215+
// different actions query tries to do - passed as argument to authorizer
216+
SQLITE_CREATE_INDEX = C.SQLITE_CREATE_INDEX
217+
SQLITE_CREATE_TABLE = C.SQLITE_CREATE_TABLE
218+
SQLITE_CREATE_TEMP_INDEX = C.SQLITE_CREATE_TEMP_INDEX
219+
SQLITE_CREATE_TEMP_TABLE = C.SQLITE_CREATE_TEMP_TABLE
220+
SQLITE_CREATE_TEMP_TRIGGER = C.SQLITE_CREATE_TEMP_TRIGGER
221+
SQLITE_CREATE_TEMP_VIEW = C.SQLITE_CREATE_TEMP_VIEW
222+
SQLITE_CREATE_TRIGGER = C.SQLITE_CREATE_TRIGGER
223+
SQLITE_CREATE_VIEW = C.SQLITE_CREATE_VIEW
224+
SQLITE_CREATE_VTABLE = C.SQLITE_CREATE_VTABLE
225+
SQLITE_DROP_INDEX = C.SQLITE_DROP_INDEX
226+
SQLITE_DROP_TABLE = C.SQLITE_DROP_TABLE
227+
SQLITE_DROP_TEMP_INDEX = C.SQLITE_DROP_TEMP_INDEX
228+
SQLITE_DROP_TEMP_TABLE = C.SQLITE_DROP_TEMP_TABLE
229+
SQLITE_DROP_TEMP_TRIGGER = C.SQLITE_DROP_TEMP_TRIGGER
230+
SQLITE_DROP_TEMP_VIEW = C.SQLITE_DROP_TEMP_VIEW
231+
SQLITE_DROP_TRIGGER = C.SQLITE_DROP_TRIGGER
232+
SQLITE_DROP_VIEW = C.SQLITE_DROP_VIEW
233+
SQLITE_DROP_VTABLE = C.SQLITE_DROP_VTABLE
234+
SQLITE_PRAGMA = C.SQLITE_PRAGMA
235+
SQLITE_READ = C.SQLITE_READ
236+
SQLITE_SELECT = C.SQLITE_SELECT
237+
SQLITE_TRANSACTION = C.SQLITE_TRANSACTION
238+
SQLITE_ATTACH = C.SQLITE_ATTACH
239+
SQLITE_DETACH = C.SQLITE_DETACH
240+
SQLITE_ALTER_TABLE = C.SQLITE_ALTER_TABLE
241+
SQLITE_REINDEX = C.SQLITE_REINDEX
242+
SQLITE_ANALYZE = C.SQLITE_ANALYZE
243+
SQLITE_FUNCTION = C.SQLITE_FUNCTION
244+
SQLITE_SAVEPOINT = C.SQLITE_SAVEPOINT
245+
SQLITE_COPY = C.SQLITE_COPY
246+
SQLITE_RECURSIVE = C.SQLITE_RECURSIVE
206247
)
207248

208249
// SQLiteDriver implements driver.Driver.
@@ -440,6 +481,20 @@ func (c *SQLiteConn) RegisterUpdateHook(callback func(int, string, string, int64
440481
}
441482
}
442483

484+
// RegisterAuthorizer sets the authorizer for connection.
485+
//
486+
// The parameters to the callback are the operation (one of the constants
487+
// SQLITE_INSERT, SQLITE_DELETE, or SQLITE_UPDATE), and 1 to 3 arguments,
488+
// depending on operation. More details see:
489+
// https://www.sqlite.org/c3ref/c_alter_table.html
490+
func (c *SQLiteConn) RegisterAuthorizer(callback func(int, string, string, string) int) {
491+
if callback == nil {
492+
C.sqlite3_set_authorizer(c.db, nil, nil)
493+
} else {
494+
C.sqlite3_set_authorizer(c.db, (*[0]byte)(C.authorizerTrampoline), unsafe.Pointer(newHandle(c, callback)))
495+
}
496+
}
497+
443498
// RegisterFunc makes a Go function available as a SQLite function.
444499
//
445500
// The Go function can have arguments of the following types: any

sqlite3_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,47 @@ func TestUpdateAndTransactionHooks(t *testing.T) {
15741574
}
15751575
}
15761576

1577+
func TestAuthorizer(t *testing.T) {
1578+
var authorizerReturn = 0
1579+
1580+
sql.Register("sqlite3_Authorizer", &SQLiteDriver{
1581+
ConnectHook: func(conn *SQLiteConn) error {
1582+
conn.RegisterAuthorizer(func(op int, arg1, arg2, arg3 string) int {
1583+
return authorizerReturn
1584+
})
1585+
return nil
1586+
},
1587+
})
1588+
db, err := sql.Open("sqlite3_Authorizer", ":memory:")
1589+
if err != nil {
1590+
t.Fatal("Failed to open database:", err)
1591+
}
1592+
defer db.Close()
1593+
1594+
statements := []string{
1595+
"create table foo (id integer primary key, name varchar)",
1596+
"insert into foo values (9, 'test9')",
1597+
"update foo set name = 'test99' where id = 9",
1598+
"select * from foo",
1599+
}
1600+
1601+
authorizerReturn = SQLITE_OK
1602+
for _, statement := range statements {
1603+
_, err = db.Exec(statement)
1604+
if err != nil {
1605+
t.Fatalf("No error expected [%v]: %v", statement, err)
1606+
}
1607+
}
1608+
1609+
authorizerReturn = SQLITE_DENY
1610+
for _, statement := range statements {
1611+
_, err = db.Exec(statement)
1612+
if err == nil {
1613+
t.Fatalf("Authorizer didn't worked - nil received, but error expected: [%v]", statement)
1614+
}
1615+
}
1616+
}
1617+
15771618
func TestNilAndEmptyBytes(t *testing.T) {
15781619
db, err := sql.Open("sqlite3", ":memory:")
15791620
if err != nil {

0 commit comments

Comments
 (0)