Skip to content

Commit 79b3a4c

Browse files
committed
use jdbc sintax on roles query parameter
1 parent 2c413ad commit 79b3a4c

File tree

4 files changed

+45
-51
lines changed

4 files changed

+45
-51
lines changed

README.md

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -253,17 +253,16 @@ The `queryTimeout` parameter sets a timeout for the query. If the query takes lo
253253
#### `roles`
254254

255255
```
256-
Type: string
257-
Format: roles=catalog1=ROLE{role1},catalog2=ROLE{role2}
258-
Valid values: A comma-separated list of catalog-to-role assignments, where each assignment maps a catalog to a role.
256+
Type: string
257+
Format: roles=catalog1:role1;catalog2=role2
258+
Valid values: A semicolon-separated list of catalog-to-role assignments, where each assignment maps a catalog to a role.
259259
Default: empty
260260
```
261261
The roles parameter defines authorization roles to assume for one or more catalogs during the Trino session.
262262

263-
You can assign roles either as a map of catalog-to-role pairs or a string. When a string is used, it applies the role to the `system` catalog by default.
263+
You can assign roles either as a map of catalog-to-role pairs or a string direcly in the dns connection.
264264

265265
##### Example
266-
267266
``` go
268267
c := &Config{
269268
ServerURI: "https://foobar@localhost:8090",
@@ -272,23 +271,8 @@ c := &Config{
272271
}
273272

274273
dsn, err := c.FormatDSN()
275-
// Result: https://foobar@localhost:8090?roles=catalog1%3DROLE%7B%22role1%22%7D%2Ccatalog2%3DROLE%7B%22role2%22%7D&session_properties=query_priority%3A1&source=trino-go-client
276274
```
277275

278-
**Example using a string (applies to system catalog)**
279-
280-
``` go
281-
c := &Config{
282-
ServerURI: "https://foobar@localhost:8090",
283-
SessionProperties: map[string]string{"query_priority": "1"},
284-
Roles: "admin", // equivalent to map[string]string{"system": "admin"}
285-
}
286-
287-
dsn, err := c.FormatDSN()
288-
// Result: https://foobar@localhost:8090?roles=system%3DROLE%7B%22admin%22%7D&session_properties=query_priority%3A1&source=trino-go-client
289-
```
290-
291-
292276
#### Examples
293277

294278
```
@@ -299,6 +283,11 @@ http://user@localhost:8080?source=hello&catalog=default&schema=foobar
299283
https://user@localhost:8443?session_properties=query_max_run_time=10m,query_priority=2
300284
```
301285

286+
287+
```
288+
http://user@localhost:8080?source=hello&catalog=default&schema=foobar&roles=catalog1:role1;catalog2:role2
289+
```
290+
302291
## Data types
303292

304293
### Query arguments

trino/integration_test.go

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,8 +1042,13 @@ func TestRoleHeaderSupport(t *testing.T) {
10421042
expectError: false,
10431043
},
10441044
{
1045-
name: "Valid single role via DSN",
1046-
rawDSN: *integrationServerFlag + "?roles=tpch%3DROLE%7Brole1%7D",
1045+
name: "Valid roles via DSN, not encoded url",
1046+
rawDSN: *integrationServerFlag + "?roles=tpch:role1;memory:role2",
1047+
expectError: false,
1048+
},
1049+
{
1050+
name: "Valid roles via DSN, url encoded",
1051+
rawDSN: *integrationServerFlag + "?roles%3Dtpch%3Arole1%3Bmemory%3Arole2",
10471052
expectError: false,
10481053
},
10491054
{
@@ -1053,25 +1058,13 @@ func TestRoleHeaderSupport(t *testing.T) {
10531058
Roles: map[string]string{"not-exist-catalog": "role1"},
10541059
},
10551060
expectError: true,
1056-
errorSubstr: "USER_ERROR: Catalog 'not-exist-catalog' not found",
1057-
},
1058-
{
1059-
name: "Invalid role format with colon",
1060-
rawDSN: *integrationServerFlag + "?roles=not-exist-catalog%3Arole1",
1061-
expectError: true,
1062-
errorSubstr: "Invalid X-Trino-Role header",
1063-
},
1064-
{
1065-
name: "Invalid role format missing ROLE{}",
1066-
rawDSN: *integrationServerFlag + "?roles=catolog%3Drole1",
1067-
expectError: true,
1068-
errorSubstr: "Invalid X-Trino-Role header",
1061+
errorSubstr: "USER_ERROR: Catalog",
10691062
},
10701063
{
10711064
name: "Invalid role format missing ROLE{}",
10721065
rawDSN: *integrationServerFlag + "?roles=catolog%3Drole1",
10731066
expectError: true,
1074-
errorSubstr: "Invalid X-Trino-Role header",
1067+
errorSubstr: "Invalid role format: catolog=role1",
10751068
},
10761069
}
10771070

trino/trino.go

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,6 @@ const (
155155
mapKeySeparator = ":"
156156
mapEntrySeparator = ";"
157157
mapCommaSeparator = ","
158-
mapRolesSeparator = "="
159-
sistemRole = "system"
160158
)
161159

162160
var (
@@ -198,7 +196,7 @@ type Config struct {
198196
AccessToken string // An access token (JWT) for authentication (optional)
199197
ForwardAuthorizationHeader bool // Allow forwarding the `accessToken` named query parameter in the authorization header, overwriting the `AccessToken` option, if set (optional)
200198
QueryTimeout *time.Duration // Configurable timeout for query (optional)
201-
Roles interface{} // Roles (optional)
199+
Roles map[string]string // Roles (optional)
202200
}
203201

204202
// FormatDSN returns a DSN string from the configuration.
@@ -222,14 +220,8 @@ func (c *Config) FormatDSN() (string, error) {
222220

223221
var roles []string
224222
if c.Roles != nil {
225-
if v, ok := c.Roles.(string); ok {
226-
roles = append(roles, sistemRole+mapRolesSeparator+fmt.Sprintf("ROLE{%q}", v))
227-
} else if v, ok := c.Roles.(map[string]string); ok {
228-
for k, v := range v {
229-
roles = append(roles, k+mapRolesSeparator+fmt.Sprintf("ROLE{%q}", v))
230-
}
231-
} else {
232-
return "", fmt.Errorf("Invalid roles type %T", c.Roles)
223+
for k, v := range c.Roles {
224+
roles = append(roles, fmt.Sprintf("%s=ROLE{%q}", k, v))
233225
}
234226
}
235227

@@ -411,6 +403,26 @@ func newConn(dsn string) (*Conn, error) {
411403
queryTimeout = &d
412404
}
413405

406+
var formatedRoles string
407+
if rolesStr := query.Get("roles"); rolesStr != "" {
408+
if !strings.Contains(rolesStr, "=ROLE{") {
409+
roles := []string{}
410+
rolesToFormat := strings.Split(rolesStr, ";")
411+
412+
for _, role := range rolesToFormat {
413+
parts := strings.Split(role, ":")
414+
if len(parts) != 2 {
415+
return nil, fmt.Errorf("Invalid role format: %s", role)
416+
}
417+
roles = append(roles, fmt.Sprintf("%s=ROLE{%q}", parts[0], parts[1]))
418+
}
419+
420+
formatedRoles = strings.Join(roles, mapCommaSeparator)
421+
} else {
422+
formatedRoles = rolesStr
423+
}
424+
}
425+
414426
c := &Conn{
415427
baseURL: serverURL.Scheme + "://" + serverURL.Host,
416428
httpClient: *httpClient,
@@ -421,7 +433,7 @@ func newConn(dsn string) (*Conn, error) {
421433
useExplicitPrepare: useExplicitPrepare,
422434
forwardAuthorizationHeader: forwardAuthorizationHeader,
423435
queryTimeout: queryTimeout,
424-
Roles: query.Get("roles"),
436+
Roles: formatedRoles,
425437
}
426438

427439
var user string

trino/trino_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,13 +220,13 @@ func TestFormatDSNWithRoles(t *testing.T) {
220220
wantDSN: "https://foobar@localhost:8090?roles=catalog1%3DROLE%7B%22role1%22%7D%2Ccatalog2%3DROLE%7B%22role2%22%7D&session_properties=query_priority%3A1&source=trino-go-client",
221221
},
222222
{
223-
name: "Default system role as string",
223+
name: "Single catalog role",
224224
config: &Config{
225225
ServerURI: "https://foobar@localhost:8090",
226226
SessionProperties: map[string]string{"query_priority": "1"},
227-
Roles: "role1",
227+
Roles: map[string]string{"catalog1": "role1"},
228228
},
229-
wantDSN: "https://foobar@localhost:8090?roles=system%3DROLE%7B%22role1%22%7D&session_properties=query_priority%3A1&source=trino-go-client",
229+
wantDSN: "https://foobar@localhost:8090?roles=catalog1%3DROLE%7B%22role1%22%7D&session_properties=query_priority%3A1&source=trino-go-client",
230230
},
231231
}
232232

0 commit comments

Comments
 (0)