Skip to content

Commit 3424e9d

Browse files
committed
feat(token): support to access tokens auth
1 parent fdca2a7 commit 3424e9d

File tree

9 files changed

+113
-18
lines changed

9 files changed

+113
-18
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ cli/.vscode
66
pkg/
77
bin
88
.env
9+
.cache

.golangci.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
version: "2"
2+
linters:
3+
exclusions:
4+
# Disable ST1006 (receiver name style) to allow existing receiver names in server.go
5+
rules:
6+
- path: server.go
7+
linters:
8+
- staticcheck
9+
- stylecheck
10+
text: ST1006

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Run formatter and more before git commit.
44
repos:
55
- repo: https://github.com/pre-commit/pre-commit-hooks
6-
rev: v4.6.0
6+
rev: v6.0.0
77
hooks:
88
- id: trailing-whitespace
99
- id: end-of-file-fixer
@@ -28,7 +28,7 @@ repos:
2828
- -w
2929
require_serial: true
3030
- repo: https://github.com/golangci/golangci-lint
31-
rev: v1.59.1
31+
rev: v2.7.2
3232
hooks:
3333
- id: golangci-lint
3434
exclude: ^pkg/

connection.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,11 @@ type SQCloudConfig struct {
4949
TlsInsecureSkipVerify bool // Accept invalid TLS certificates (no_verify_certificate)
5050
Pem string
5151
ApiKey string
52-
NoBlob bool // flag to tell the server to not send BLOB columns
53-
MaxData int // value to tell the server to not send columns with more than max_data bytes
54-
MaxRows int // value to control rowset chunks based on the number of rows
55-
MaxRowset int // value to control the maximum allowed size for a rowset
52+
Token string // Access Token for authentication
53+
NoBlob bool // flag to tell the server to not send BLOB columns
54+
MaxData int // value to tell the server to not send columns with more than max_data bytes
55+
MaxRows int // value to control rowset chunks based on the number of rows
56+
MaxRowset int // value to control the maximum allowed size for a rowset
5657
}
5758

5859
type SQCloud struct {
@@ -131,6 +132,7 @@ func ParseConnectionString(ConnectionString string) (config *SQCloudConfig, err
131132
config.MaxRows = 0
132133
config.MaxRowset = 0
133134
config.ApiKey = ""
135+
config.Token = ""
134136

135137
sPort := strings.TrimSpace(u.Port())
136138
if len(sPort) > 0 {
@@ -195,6 +197,8 @@ func ParseConnectionString(ConnectionString string) (config *SQCloudConfig, err
195197
config.Secure, config.TlsInsecureSkipVerify, config.Pem = ParseTlsString(lastLiteral)
196198
case "apikey":
197199
config.ApiKey = lastLiteral
200+
case "token":
201+
config.Token = lastLiteral
198202
case "noblob":
199203
if b, err := parseBool(lastLiteral, config.NoBlob); err == nil {
200204
config.NoBlob = b
@@ -434,12 +438,14 @@ func connectionCommands(config SQCloudConfig) (string, []interface{}) {
434438
}
435439

436440
if config.ApiKey != "" {
437-
c, a := authWithKeyCommand(config.ApiKey)
441+
c, a := authWithApiKeyCommand(config.ApiKey)
438442
buffer += c
439443
args = append(args, a...)
440-
}
441-
442-
if config.Username != "" && config.Password != "" {
444+
} else if config.Token != "" {
445+
c, a := authWithTokenCommand(config.Token)
446+
buffer += c
447+
args = append(args, a...)
448+
} else if config.Username != "" && config.Password != "" {
443449
c, a := authCommand(config.Username, config.Password, config.PasswordHashed)
444450
buffer += c
445451
args = append(args, a...)

connection_internal_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package sqlitecloud
2+
3+
import (
4+
"reflect"
5+
"strings"
6+
"testing"
7+
)
8+
9+
func TestConnectionCommandsAuthPreference(t *testing.T) {
10+
tests := []struct {
11+
name string
12+
config SQCloudConfig
13+
wantCmd string
14+
wantArgs []interface{}
15+
}{
16+
{"api key wins", SQCloudConfig{ApiKey: "k", Token: "t", Username: "u", Password: "p"}, "AUTH APIKEY ?;", []interface{}{"k"}},
17+
{"token next", SQCloudConfig{Token: "t", Username: "u", Password: "p"}, "AUTH TOKEN ?;", []interface{}{"t"}},
18+
{"user/pass fallback", SQCloudConfig{Username: "u", Password: "p"}, "AUTH USER ? PASSWORD ?;", []interface{}{"u", "p"}},
19+
{"hashed password", SQCloudConfig{Username: "u", Password: "hash", PasswordHashed: true}, "AUTH USER ? HASH ?;", []interface{}{"u", "hash"}},
20+
{"no credentials", SQCloudConfig{}, "", []interface{}{}},
21+
}
22+
23+
for _, tt := range tests {
24+
t.Run(tt.name, func(t *testing.T) {
25+
gotBuf, gotArgs := connectionCommands(tt.config)
26+
if tt.wantCmd == "" && gotBuf != "" {
27+
t.Fatalf("expected no auth command, got %q", gotBuf)
28+
}
29+
if tt.wantCmd != "" && !strings.Contains(gotBuf, tt.wantCmd) {
30+
t.Fatalf("expected %q in buffer, got %q", tt.wantCmd, gotBuf)
31+
}
32+
if !reflect.DeepEqual(gotArgs, tt.wantArgs) {
33+
t.Fatalf("args mismatch: want %v got %v", tt.wantArgs, gotArgs)
34+
}
35+
})
36+
}
37+
}

go.mod

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/sqlitecloud/sqlitecloud-go
22

3-
go 1.18
3+
go 1.24.0
44

55
require (
66
github.com/pierrec/lz4 v2.6.1+incompatible
@@ -10,5 +10,6 @@ require (
1010

1111
require (
1212
github.com/frankban/quicktest v1.14.3 // indirect
13-
golang.org/x/sys v0.7.0 // indirect
13+
github.com/google/go-cmp v0.6.0 // indirect
14+
golang.org/x/sys v0.39.0 // indirect
1415
)

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
22
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
33
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
4-
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
54
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
5+
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
6+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
67
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
78
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
89
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
@@ -16,11 +17,10 @@ github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBO
1617
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
1718
github.com/xo/dburl v0.13.1 h1:EV+BCdo539sc/mBrny0VxaEGLM0b1U0mJA9RpP80ux0=
1819
github.com/xo/dburl v0.13.1/go.mod h1:B7/G9FGungw6ighV8xJNwWYQPMfn3gsi2sn5SE8Bzco=
19-
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
20-
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
20+
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
21+
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
2122
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
2223
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
23-
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
2424
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
2525
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
2626
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=

server.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,13 +260,21 @@ func (this *SQCloud) Auth(Username string, Password string) error {
260260
return this.ExecuteArray(authCommand(Username, Password, false))
261261
}
262262

263-
func authWithKeyCommand(Key string) (string, []interface{}) {
263+
func authWithApiKeyCommand(Key string) (string, []interface{}) {
264264
return "AUTH APIKEY ?;", []interface{}{Key}
265265
}
266266

267+
func authWithTokenCommand(Token string) (string, []interface{}) {
268+
return "AUTH TOKEN ?;", []interface{}{Token}
269+
}
270+
267271
// Auth - INTERNAL SERVER COMMAND: Authenticates User with the given API KEY.
268272
func (this *SQCloud) AuthWithKey(Key string) error {
269-
return this.ExecuteArray(authWithKeyCommand(Key))
273+
return this.ExecuteArray(authWithApiKeyCommand(Key))
274+
}
275+
276+
func (this *SQCloud) AuthWithToken(Token string) error {
277+
return this.ExecuteArray(authWithTokenCommand(Token))
270278
}
271279

272280
// Database funcitons

test/unit/connection_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,32 @@ func TestParseConnectionStringWithAPIKey(t *testing.T) {
6868
assert.Truef(t, reflect.DeepEqual(expectedConfig, config), "Expected: %+v\nGot: %+v", expectedConfig, config)
6969
}
7070

71+
func TestParseConnectionStringWithToken(t *testing.T) {
72+
connectionString := "sqlitecloud://host.com:8860/dbname?token=123|tok123&compress=true"
73+
expectedConfig := &sqlitecloud.SQCloudConfig{
74+
Host: "host.com",
75+
Port: 8860,
76+
Username: "",
77+
Password: "",
78+
Database: "dbname",
79+
Timeout: 0,
80+
Compression: true,
81+
CompressMode: sqlitecloud.CompressModeLZ4,
82+
Secure: true,
83+
TlsInsecureSkipVerify: false,
84+
Pem: "",
85+
Token: "123|tok123",
86+
NoBlob: false,
87+
MaxData: 0,
88+
MaxRows: 0,
89+
MaxRowset: 0,
90+
}
91+
92+
config, err := sqlitecloud.ParseConnectionString(connectionString)
93+
assert.NoError(t, err)
94+
assert.Truef(t, reflect.DeepEqual(expectedConfig, config), "Expected: %+v\nGot: %+v", expectedConfig, config)
95+
}
96+
7197
func TestParseConnectionStringWithCredentials(t *testing.T) {
7298
connectionString := "sqlitecloud://user:pass@host.com:8860"
7399
config, err := sqlitecloud.ParseConnectionString(connectionString)
@@ -187,6 +213,12 @@ func TestParseConnectionStringWithParameters(t *testing.T) {
187213
value: "abc123",
188214
expectedValue: "abc123",
189215
},
216+
{
217+
param: "token",
218+
configParam: "Token",
219+
value: "123|tok123",
220+
expectedValue: "123|tok123",
221+
},
190222
}
191223

192224
for _, tt := range tests {

0 commit comments

Comments
 (0)