Add target type and session user_id as searchable (#4076)

* Add target type and session user_id to search
This commit is contained in:
Todd authored and Johan Brandhorst-Satzkorn committed 2024-01-05 07:43:21 -08:00
1 parent df93313b9a
commit 9ebb69f2a4
9 files changed
+191 -69

No files matched your search

+13 -11
View File
@@ -111,8 +111,8 @@ func (r *Repository) refreshSessions(ctx context.Context, u *user, tokens map[Au
_, err = r.rw.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{}, func(_ db.Reader, w db.Writer) error {
switch {
case oldRefreshToken == nil:
if _, err := w.Exec(ctx, "delete from session where user_id = @user_id",
[]any{sql.Named("user_id", u.Id)}); err != nil {
if _, err := w.Exec(ctx, "delete from session where fk_user_id = @fk_user_id",
[]any{sql.Named("fk_user_id", u.Id)}); err != nil {
return err
}
case len(removedIds) > 0:
@@ -185,8 +185,8 @@ func (r *Repository) fullFetchSessions(ctx context.Context, u *user, tokens map[
event.WriteSysEvent(ctx, op, fmt.Sprintf("updating %d sessions for user %v", len(resp), u))
_, err = r.rw.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{}, func(_ db.Reader, w db.Writer) error {
if _, err := w.Exec(ctx, "delete from session where user_id = @user_id",
[]any{sql.Named("user_id", u.Id)}); err != nil {
if _, err := w.Exec(ctx, "delete from session where fk_user_id = @fk_user_id",
[]any{sql.Named("fk_user_id", u.Id)}); err != nil {
return err
}
@@ -222,18 +222,19 @@ func upsertSessions(ctx context.Context, w db.Writer, u *user, in []*sessions.Se
return errors.Wrap(ctx, err, op)
}
newSession := &Session{
UserId: u.Id,
FkUserId: u.Id,
Id: s.Id,
Type: s.Type,
Status: s.Status,
Endpoint: s.Endpoint,
ScopeId: s.ScopeId,
TargetId: s.TargetId,
UserId: s.UserId,
Item: string(item),
}
onConflict := db.OnConflict{
Target: db.Columns{"user_id", "id"},
Action: db.UpdateAll(true),
Target: db.Columns{"fk_user_id", "id"},
Action: db.SetColumns([]string{"type", "status", "endpoint", "scope_id", "target_id", "user_id", "item"}),
}
if err := w.Create(ctx, newSession, db.WithOnConflict(&onConflict)); err != nil {
return errors.Wrap(ctx, err, op)
@@ -264,7 +265,7 @@ func (r *Repository) QuerySessions(ctx context.Context, authTokenId, query strin
return nil, errors.New(ctx, errors.InvalidParameter, op, "query is missing")
}
w, err := mql.Parse(query, Session{}, mql.WithIgnoredFields("UserId", "Item"))
w, err := mql.Parse(query, Session{}, mql.WithIgnoredFields("FkUserId", "Item"))
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithCode(errors.InvalidParameter))
}
@@ -292,10 +293,10 @@ func (r *Repository) searchSessions(ctx context.Context, condition string, searc
case opts.withAuthTokenId == "" && opts.withUserId == "":
return nil, errors.New(ctx, errors.InvalidParameter, op, "neither user id nor auth token id were provided")
case opts.withAuthTokenId != "":
condition = fmt.Sprintf("%s and user_id in (select user_id from auth_token where id = ?)", condition)
condition = fmt.Sprintf("%s and fk_user_id in (select user_id from auth_token where id = ?)", condition)
searchArgs = append(searchArgs, opts.withAuthTokenId)
case opts.withUserId != "":
condition = fmt.Sprintf("%s and user_id = ?", condition)
condition = fmt.Sprintf("%s and fk_user_id = ?", condition)
searchArgs = append(searchArgs, opts.withUserId)
}
@@ -316,13 +317,14 @@ func (r *Repository) searchSessions(ctx context.Context, condition string, searc
}
type Session struct {
UserId string `gorm:"primaryKey"`
FkUserId string `gorm:"primaryKey"`
Id string `gorm:"primaryKey"`
Type string `gorm:"default:null"`
Endpoint string `gorm:"default:null"`
Status string `gorm:"default:null"`
ScopeId string `gorm:"default:null"`
TargetId string `gorm:"default:null"`
UserId string `gorm:"default:null"`
Item string `gorm:"default:null"`
}
@@ -5,6 +5,7 @@ package cache
import (
"context"
"encoding/json"
"sync"
"testing"
@@ -57,6 +58,7 @@ func TestRepository_refreshSessions(t *testing.T) {
Endpoint: "address1",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Type: "tcp",
},
{
@@ -65,6 +67,7 @@ func TestRepository_refreshSessions(t *testing.T) {
Endpoint: "address2",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Type: "tcp",
},
{
@@ -73,14 +76,31 @@ func TestRepository_refreshSessions(t *testing.T) {
Endpoint: "address3",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Type: "tcp",
},
}
var want []*Session
for _, sess := range ss {
si, err := json.Marshal(sess)
require.NoError(t, err)
want = append(want, &Session{
FkUserId: u.Id,
Id: sess.Id,
Type: sess.Type,
Status: sess.Status,
Endpoint: sess.Endpoint,
ScopeId: sess.ScopeId,
TargetId: sess.TargetId,
UserId: sess.UserId,
Item: string(si),
})
}
cases := []struct {
name string
u *user
sess []*sessions.Session
wantCount int
want []*Session
errorContains string
}{
{
@@ -89,8 +109,8 @@ func TestRepository_refreshSessions(t *testing.T) {
Address: addr,
Id: at.UserId,
},
sess: ss,
wantCount: len(ss),
sess: ss,
want: want,
},
{
name: "repeated session with different values",
@@ -102,7 +122,12 @@ func TestRepository_refreshSessions(t *testing.T) {
Id: ss[0].Id,
Status: "a different status",
}),
wantCount: len(ss),
want: append(want[1:], &Session{
FkUserId: want[0].FkUserId,
Id: want[0].Id,
Status: "a different status",
Item: `{"id":"ttcp_1","created_time":"0001-01-01T00:00:00Z","updated_time":"0001-01-01T00:00:00Z","expiration_time":"0001-01-01T00:00:00Z","status":"a different status"}`,
}),
},
{
name: "nil user",
@@ -129,7 +154,7 @@ func TestRepository_refreshSessions(t *testing.T) {
rw := db.New(s)
var got []*Session
require.NoError(t, rw.SearchWhere(ctx, &got, "true", nil))
assert.Len(t, got, tc.wantCount)
assert.ElementsMatch(t, got, tc.want)
t.Cleanup(func() {
refTok := &refreshToken{
@@ -181,6 +206,7 @@ func TestRepository_RefreshSessions_withRefreshTokens(t *testing.T) {
Endpoint: "address1",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Type: "tcp",
},
{
@@ -189,6 +215,7 @@ func TestRepository_RefreshSessions_withRefreshTokens(t *testing.T) {
Endpoint: "address2",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Type: "tcp",
},
},
@@ -199,6 +226,7 @@ func TestRepository_RefreshSessions_withRefreshTokens(t *testing.T) {
Endpoint: "address3",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Type: "tcp",
},
},
@@ -298,6 +326,7 @@ func TestRepository_ListSessions(t *testing.T) {
Endpoint: "address1",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Type: "tcp",
},
{
@@ -306,6 +335,7 @@ func TestRepository_ListSessions(t *testing.T) {
Endpoint: "address2",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Type: "tcp",
},
{
@@ -314,6 +344,7 @@ func TestRepository_ListSessions(t *testing.T) {
Endpoint: "address3",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Type: "tcp",
},
}
@@ -411,6 +442,7 @@ func TestRepository_QuerySessions(t *testing.T) {
Endpoint: "address1",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Type: "tcp",
},
{
@@ -419,6 +451,7 @@ func TestRepository_QuerySessions(t *testing.T) {
Endpoint: "address2",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Type: "tcp",
},
{
@@ -427,6 +460,7 @@ func TestRepository_QuerySessions(t *testing.T) {
Endpoint: "address3",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Type: "tcp",
},
}
+13 -11
View File
@@ -109,8 +109,8 @@ func (r *Repository) refreshTargets(ctx context.Context, u *user, tokens map[Aut
_, err = r.rw.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{}, func(r db.Reader, w db.Writer) error {
switch {
case oldRefreshToken == nil:
if _, err := w.Exec(ctx, "delete from target where user_id = @user_id",
[]any{sql.Named("user_id", u.Id)}); err != nil {
if _, err := w.Exec(ctx, "delete from target where fk_user_id = @fk_user_id",
[]any{sql.Named("fk_user_id", u.Id)}); err != nil {
return err
}
case len(removedIds) > 0:
@@ -182,8 +182,8 @@ func (r *Repository) fullFetchTargets(ctx context.Context, u *user, tokens map[A
event.WriteSysEvent(ctx, op, fmt.Sprintf("updating %d targets for user %v", len(resp), u))
_, err = r.rw.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{}, func(r db.Reader, w db.Writer) error {
if _, err := w.Exec(ctx, "delete from target where user_id = @user_id",
[]any{sql.Named("user_id", u.Id)}); err != nil {
if _, err := w.Exec(ctx, "delete from target where fk_user_id = @fk_user_id",
[]any{sql.Named("fk_user_id", u.Id)}); err != nil {
return err
}
@@ -221,17 +221,18 @@ func upsertTargets(ctx context.Context, w db.Writer, u *user, in []*targets.Targ
return errors.Wrap(ctx, err, op)
}
newTarget := &Target{
UserId: u.Id,
FkUserId: u.Id,
Id: t.Id,
Name: t.Name,
Description: t.Description,
Address: t.Address,
ScopeId: t.ScopeId,
Type: t.Type,
Item: string(item),
}
onConflict := db.OnConflict{
Target: db.Columns{"user_id", "id"},
Action: db.UpdateAll(true),
Target: db.Columns{"fk_user_id", "id"},
Action: db.SetColumns([]string{"name", "description", "address", "scope_id", "type", "item"}),
}
if err := w.Create(ctx, newTarget, db.WithOnConflict(&onConflict)); err != nil {
return errors.Wrap(ctx, err, op)
@@ -262,7 +263,7 @@ func (r *Repository) QueryTargets(ctx context.Context, authTokenId, query string
return nil, errors.New(ctx, errors.InvalidParameter, op, "query is missing")
}
w, err := mql.Parse(query, Target{}, mql.WithIgnoredFields("UserId", "Item"))
w, err := mql.Parse(query, Target{}, mql.WithIgnoredFields("FkUserId", "Item"))
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithCode(errors.InvalidParameter))
}
@@ -290,10 +291,10 @@ func (r *Repository) searchTargets(ctx context.Context, condition string, search
case opts.withAuthTokenId == "" && opts.withUserId == "":
return nil, errors.New(ctx, errors.InvalidParameter, op, "neither user id nor auth token id were provided")
case opts.withAuthTokenId != "":
condition = fmt.Sprintf("%s and user_id in (select user_id from auth_token where id = ?)", condition)
condition = fmt.Sprintf("%s and fk_user_id in (select user_id from auth_token where id = ?)", condition)
searchArgs = append(searchArgs, opts.withAuthTokenId)
case opts.withUserId != "":
condition = fmt.Sprintf("%s and user_id = ?", condition)
condition = fmt.Sprintf("%s and fk_user_id = ?", condition)
searchArgs = append(searchArgs, opts.withUserId)
}
@@ -314,8 +315,9 @@ func (r *Repository) searchTargets(ctx context.Context, condition string, search
}
type Target struct {
UserId string `gorm:"primaryKey"`
FkUserId string `gorm:"primaryKey"`
Id string `gorm:"primaryKey"`
Type string `gorm:"default:null"`
Name string `gorm:"default:null"`
Description string `gorm:"default:null"`
Address string `gorm:"default:null"`
@@ -5,6 +5,7 @@ package cache
import (
"context"
"encoding/json"
"sync"
"testing"
@@ -47,6 +48,7 @@ func TestRepository_refreshTargets(t *testing.T) {
{
Id: "ttcp_1",
Name: "name1",
Description: "description1",
Type: "tcp",
ScopeId: "p_123",
SessionMaxSeconds: 111,
@@ -68,11 +70,26 @@ func TestRepository_refreshTargets(t *testing.T) {
SessionMaxSeconds: 333,
},
}
var want []*Target
for _, tar := range ts {
ti, err := json.Marshal(tar)
require.NoError(t, err)
want = append(want, &Target{
FkUserId: u.Id,
Id: tar.Id,
Name: tar.Name,
Description: tar.Description,
Address: tar.Address,
ScopeId: tar.ScopeId,
Type: tar.Type,
Item: string(ti),
})
}
cases := []struct {
name string
u *user
targets []*targets.Target
wantCount int
want []*Target
errorContains string
}{
{
@@ -81,9 +98,11 @@ func TestRepository_refreshTargets(t *testing.T) {
Id: at.UserId,
Address: addr,
},
targets: ts,
wantCount: len(ts),
targets: ts,
want: want,
},
// this test case must run after the above test case so as to exercise
// the update logic of refresh.
{
name: "repeated target with different values",
u: &user{
@@ -94,7 +113,13 @@ func TestRepository_refreshTargets(t *testing.T) {
Id: ts[0].Id,
Name: "a different name",
}),
wantCount: len(ts),
want: append(want[1:],
&Target{
FkUserId: want[0].FkUserId,
Id: want[0].Id,
Name: "a different name",
Item: `{"id":"ttcp_1","name":"a different name","created_time":"0001-01-01T00:00:00Z","updated_time":"0001-01-01T00:00:00Z"}`,
}),
},
{
name: "nil user",
@@ -121,7 +146,7 @@ func TestRepository_refreshTargets(t *testing.T) {
rw := db.New(s)
var got []*Target
require.NoError(t, rw.SearchWhere(ctx, &got, "true", nil))
assert.Len(t, got, tc.wantCount)
assert.ElementsMatch(t, got, tc.want)
t.Cleanup(func() {
refTok := &refreshToken{
+59 -12
View File
@@ -119,14 +119,14 @@ func TestSearch(t *testing.T) {
require.NoError(t, rw.Create(ctx, at))
targets := []any{
&Target{UserId: u.Id, Id: "t_1", Name: "one", Item: `{"id": "t_1", "name": "one"}`},
&Target{UserId: u.Id, Id: "t_2", Name: "two", Item: `{"id": "t_2", "name": "two"}`},
&Target{FkUserId: u.Id, Id: "t_1", Name: "one", Type: "tcp", Item: `{"id": "t_1", "name": "one", "type": "tcp"}`},
&Target{FkUserId: u.Id, Id: "t_2", Name: "two", Type: "tcp", Item: `{"id": "t_2", "name": "two", "type": "tcp"}`},
}
require.NoError(t, rw.CreateItems(ctx, targets))
sessions := []any{
&Session{UserId: u.Id, Id: "s_1", Endpoint: "one", Item: `{"id": "s_1", "endpoint": "one"}`},
&Session{UserId: u.Id, Id: "s_2", Endpoint: "two", Item: `{"id": "s_2", "endpoint": "two"}`},
&Session{FkUserId: u.Id, Id: "s_1", Endpoint: "one", Type: "tcp", UserId: "u123", Item: `{"id": "s_1", "endpoint": "one", "type": "tcp", "user_id": "u123"}`},
&Session{FkUserId: u.Id, Id: "s_2", Endpoint: "two", Type: "ssh", UserId: "u321", Item: `{"id": "s_2", "endpoint": "two", "type": "ssh", "user_id": "u321"}`},
}
require.NoError(t, rw.CreateItems(ctx, sessions))
}
@@ -147,8 +147,8 @@ func TestSearch(t *testing.T) {
})
assert.NoError(t, err)
assert.EqualValues(t, &SearchResult{Targets: []*targets.Target{
{Id: "t_1", Name: "one"},
{Id: "t_2", Name: "two"},
{Id: "t_1", Name: "one", Type: "tcp"},
{Id: "t_2", Name: "two", Type: "tcp"},
}}, got)
})
@@ -160,7 +160,20 @@ func TestSearch(t *testing.T) {
})
assert.NoError(t, err)
assert.EqualValues(t, &SearchResult{Targets: []*targets.Target{
{Id: "t_1", Name: "one"},
{Id: "t_1", Name: "one", Type: "tcp"},
}}, got)
})
t.Run("query targets on type", func(t *testing.T) {
got, err := ss.Search(ctx, SearchParams{
Resource: "targets",
AuthTokenId: at.Id,
Query: `type="tcp"`,
})
assert.NoError(t, err)
assert.EqualValues(t, &SearchResult{Targets: []*targets.Target{
{Id: "t_1", Name: "one", Type: "tcp"},
{Id: "t_2", Name: "two", Type: "tcp"},
}}, got)
})
@@ -175,6 +188,17 @@ func TestSearch(t *testing.T) {
assert.Nil(t, got)
})
t.Run("query targets bad column owner user id", func(t *testing.T) {
got, err := ss.Search(ctx, SearchParams{
Resource: "targets",
AuthTokenId: at.Id,
Query: `fk_user_id % "u"`,
})
assert.Error(t, err)
assert.ErrorContains(t, err, `invalid column "fk_user_id"`)
assert.Nil(t, got)
})
t.Run("Filter targets", func(t *testing.T) {
got, err := ss.Search(ctx, SearchParams{
Resource: "targets",
@@ -183,7 +207,7 @@ func TestSearch(t *testing.T) {
})
assert.NoError(t, err)
assert.EqualValues(t, &SearchResult{Targets: []*targets.Target{
{Id: "t_1", Name: "one"},
{Id: "t_1", Name: "one", Type: "tcp"},
}}, got)
})
@@ -194,8 +218,8 @@ func TestSearch(t *testing.T) {
})
assert.NoError(t, err)
assert.EqualValues(t, &SearchResult{Sessions: []*sessions.Session{
{Id: "s_1", Endpoint: "one"},
{Id: "s_2", Endpoint: "two"},
{Id: "s_1", Endpoint: "one", Type: "tcp", UserId: "u123"},
{Id: "s_2", Endpoint: "two", Type: "ssh", UserId: "u321"},
}}, got)
})
@@ -207,10 +231,33 @@ func TestSearch(t *testing.T) {
})
assert.NoError(t, err)
assert.EqualValues(t, &SearchResult{Sessions: []*sessions.Session{
{Id: "s_1", Endpoint: "one"},
{Id: "s_1", Endpoint: "one", Type: "tcp", UserId: "u123"},
}}, got)
})
t.Run("query sessions user id", func(t *testing.T) {
got, err := ss.Search(ctx, SearchParams{
Resource: "sessions",
AuthTokenId: at.Id,
Query: `user_id="u123"`,
})
assert.NoError(t, err)
assert.EqualValues(t, &SearchResult{Sessions: []*sessions.Session{
{Id: "s_1", Endpoint: "one", Type: "tcp", UserId: "u123"},
}}, got)
})
t.Run("query sessions bad column owner user id", func(t *testing.T) {
got, err := ss.Search(ctx, SearchParams{
Resource: "sessions",
AuthTokenId: at.Id,
Query: `fk_user_id % "u"`,
})
assert.Error(t, err)
assert.ErrorContains(t, err, `invalid column "fk_user_id"`)
assert.Nil(t, got)
})
t.Run("Filter sessions", func(t *testing.T) {
got, err := ss.Search(ctx, SearchParams{
Resource: "sessions",
@@ -219,7 +266,7 @@ func TestSearch(t *testing.T) {
})
assert.NoError(t, err)
assert.EqualValues(t, &SearchResult{Sessions: []*sessions.Session{
{Id: "s_1", Endpoint: "one"},
{Id: "s_1", Endpoint: "one", Type: "tcp", UserId: "u123"},
}}, got)
})
+1 -1
View File
@@ -149,7 +149,7 @@ func (s *StatusService) resourceStatus(ctx context.Context, u *user, rt resource
ret.LastError = errStatus
err = func() error {
query := fmt.Sprintf("select count(*) from %s where user_id = @user_id", rt)
query := fmt.Sprintf("select count(*) from %s where fk_user_id = @user_id", rt)
r, err := s.repo.rw.Query(ctx, query, []any{sql.Named("user_id", u.Id)})
if err != nil {
return errors.Wrap(ctx, err, op)
+25 -18
View File
@@ -444,6 +444,7 @@ func TestTarget(t *testing.T) {
Description: "target desc",
Address: "some address",
ScopeId: "p_123",
Type: "tcp",
Item: "{id:'tssh_1234567890'}",
}
require.ErrorContains(t, rw.Create(ctx, unknownTarget), "constraint failed")
@@ -451,12 +452,13 @@ func TestTarget(t *testing.T) {
t.Run("target actions", func(t *testing.T) {
target := &Target{
UserId: u.Id,
FkUserId: u.Id,
Id: "tssh_1234567890",
Name: "target",
Description: "target desc",
Address: "some address",
ScopeId: "p_123",
Type: "tcp",
Item: "{id:'tssh_1234567890'}",
}
@@ -471,27 +473,28 @@ func TestTarget(t *testing.T) {
// TODO: Once the sqlite driver properly builds the delete query call
// n, err = rw.Delete(ctx, target) instead of the Exec call
n, err = rw.Exec(ctx, "delete from target where (user_id, id) IN (values (?, ?))",
[]any{target.UserId, target.Id})
n, err = rw.Exec(ctx, "delete from target where (fk_user_id, id) IN (values (?, ?))",
[]any{target.FkUserId, target.Id})
assert.NoError(t, err)
assert.Equal(t, 1, n)
})
t.Run("lookup a target", func(t *testing.T) {
target := &Target{
UserId: u.Id,
FkUserId: u.Id,
Id: "tssh_1234567890",
Name: "target",
Description: "target desc",
Address: "some address",
ScopeId: "p_123",
Type: "tcp",
Item: "{id:'tssh_1234567890'}",
}
require.NoError(t, rw.Create(ctx, target))
lookTar := &Target{
UserId: target.UserId,
Id: target.Id,
FkUserId: target.FkUserId,
Id: target.Id,
}
assert.NoError(t, rw.LookupById(ctx, lookTar))
assert.NotNil(t, lookTar)
@@ -503,12 +506,13 @@ func TestTarget(t *testing.T) {
t.Run("deleting the user deletes the target", func(t *testing.T) {
target := &Target{
UserId: u.Id,
FkUserId: u.Id,
Id: "tssh_1234567890",
Name: "target",
Description: "target desc",
Address: "some address",
ScopeId: "p_123",
Type: "tcp",
Item: "{id:'tssh_1234567890'}",
}
require.NoError(t, rw.Create(ctx, target))
@@ -521,8 +525,8 @@ func TestTarget(t *testing.T) {
require.Equal(t, 1, n)
lookTar := &Target{
UserId: target.UserId,
Id: target.Id,
FkUserId: target.FkUserId,
Id: target.Id,
}
assert.ErrorContains(t, rw.LookupById(ctx, lookTar), "not found")
})
@@ -552,11 +556,12 @@ func TestSession(t *testing.T) {
})
t.Run("session actions", func(t *testing.T) {
session := &Session{
UserId: u.Id,
FkUserId: u.Id,
Id: "s_1234567890",
Endpoint: "endpoint",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Item: "{id:'s_1234567890'}",
}
@@ -571,26 +576,27 @@ func TestSession(t *testing.T) {
// TODO: Once the sqlite driver properly builds the delete query call
// n, err = rw.Delete(ctx, session) instead of the Exec call
n, err = rw.Exec(ctx, "delete from session where (user_id, id) IN (values (?, ?))",
[]any{session.UserId, session.Id})
n, err = rw.Exec(ctx, "delete from session where (fk_user_id, id) IN (values (?, ?))",
[]any{session.FkUserId, session.Id})
assert.NoError(t, err)
assert.Equal(t, 1, n)
})
t.Run("lookup a session", func(t *testing.T) {
session := &Session{
UserId: u.Id,
FkUserId: u.Id,
Id: "s_1234567890",
Endpoint: "endpoint",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Item: "{id:'s_1234567890'}",
}
require.NoError(t, rw.Create(ctx, session))
lookSess := &Session{
UserId: u.Id,
Id: session.Id,
FkUserId: u.Id,
Id: session.Id,
}
assert.NoError(t, rw.LookupById(ctx, lookSess))
assert.NotNil(t, lookSess)
@@ -602,11 +608,12 @@ func TestSession(t *testing.T) {
t.Run("deleting the user deletes the session", func(t *testing.T) {
session := &Session{
UserId: u.Id,
FkUserId: u.Id,
Id: "s_1234567890",
Endpoint: "endpoint",
ScopeId: "p_123",
TargetId: "ttcp_123",
UserId: "u_123",
Item: "{id:'s_1234567890'}",
}
require.NoError(t, rw.Create(ctx, session))
@@ -619,8 +626,8 @@ func TestSession(t *testing.T) {
require.Equal(t, 1, n)
lookSess := &Session{
UserId: session.UserId,
Id: session.Id,
FkUserId: session.FkUserId,
Id: session.Id,
}
assert.ErrorContains(t, rw.LookupById(ctx, lookSess), "not found")
})
@@ -114,7 +114,7 @@ func newTokenHandlerFunc(ctx context.Context, repo *cache.Repository, refresher
AuthTokenId: perReq.AuthTokenId,
}
if err = repo.AddKeyringToken(ctx, perReq.BoundaryAddr, kt); err != nil {
writeError(w, "Failed to add a keyring stored token", http.StatusInternalServerError)
writeError(w, fmt.Sprintf("Failed to add a keyring stored token: %v", err), http.StatusInternalServerError)
return
}
case perReq.AuthToken != "":
+10 -5
View File
@@ -109,7 +109,7 @@ create table if not exists keyring_token (
-- specific fields extracted to facilitate searching over those fields
create table if not exists target (
-- the boundary user id of the user who has was able to read/list this target
user_id text not null
fk_user_id text not null
references user(id)
on delete cascade,
-- the boundary id of the target
@@ -119,19 +119,20 @@ create table if not exists target (
-- from the boundary resource
name text,
description text,
type text,
address text,
scope_id text,
-- item is the json representation of this resource from the perspective of
-- the the requesting user.
item text,
primary key (user_id, id)
primary key (fk_user_id, id)
);
-- session contains cached boundary session resource for a specific user and
-- with specific fields extracted to facilitate searching over those fields
create table if not exists session (
-- the boundary user id of the user who has was able to read/list this resource
user_id text not null
fk_user_id text not null
references user(id)
on delete cascade,
-- the resource id from boundary of this session
@@ -144,10 +145,14 @@ create table if not exists session (
status text,
scope_id text,
target_id text,
-- The user_id is the the id of the user that created this session. This can
-- be different from the fk_user_id which is the id of the boundary user
-- which synced this record into the cache.
user_id text,
-- item is the json representation of this resource from the perspective of
-- of the user whose id is set in user_id
-- of the user whose id is set in fk_user_id
item text,
primary key (user_id, id)
primary key (fk_user_id, id)
);
-- contains errors from the last attempt to sync data from boundary for a