roomdb: flesh out alias service

* update interface
* update mockdb
* update models
* implement sqlite implementation
This commit is contained in:
Henry 2021-03-11 17:57:55 +01:00
parent 04104c0f9e
commit e6c3305229
12 changed files with 1851 additions and 70 deletions

View File

@ -53,7 +53,22 @@ type AllowListService interface {
}
// AliasService manages alias handle registration and lookup
type AliasService interface{}
type AliasService interface {
// Resolve returns all the relevant information for that alias or an error if it doesnt exist
Resolve(context.Context, string) (Alias, error)
// GetByID returns the alias for that ID or an error
GetByID(context.Context, int64) (Alias, error)
// List returns a list of all registerd aliases
List(ctx context.Context) ([]Alias, error)
// Register receives an alias and signature for it. Validation needs to happen before this.
Register(ctx context.Context, alias string, userFeed refs.FeedRef, signature []byte) error
// Revoke removes an alias from the system
Revoke(ctx context.Context, alias string) error
}
// InviteService manages creation and consumption of invite tokens for joining the room.
type InviteService interface {

View File

@ -2,19 +2,423 @@
package mockdb
import (
"context"
"sync"
"github.com/ssb-ngi-pointer/go-ssb-room/roomdb"
refs "go.mindeco.de/ssb-refs"
)
type FakeAliasService struct {
GetByIDStub func(context.Context, int64) (roomdb.Alias, error)
getByIDMutex sync.RWMutex
getByIDArgsForCall []struct {
arg1 context.Context
arg2 int64
}
getByIDReturns struct {
result1 roomdb.Alias
result2 error
}
getByIDReturnsOnCall map[int]struct {
result1 roomdb.Alias
result2 error
}
ListStub func(context.Context) ([]roomdb.Alias, error)
listMutex sync.RWMutex
listArgsForCall []struct {
arg1 context.Context
}
listReturns struct {
result1 []roomdb.Alias
result2 error
}
listReturnsOnCall map[int]struct {
result1 []roomdb.Alias
result2 error
}
RegisterStub func(context.Context, string, refs.FeedRef, []byte) error
registerMutex sync.RWMutex
registerArgsForCall []struct {
arg1 context.Context
arg2 string
arg3 refs.FeedRef
arg4 []byte
}
registerReturns struct {
result1 error
}
registerReturnsOnCall map[int]struct {
result1 error
}
ResolveStub func(context.Context, string) (roomdb.Alias, error)
resolveMutex sync.RWMutex
resolveArgsForCall []struct {
arg1 context.Context
arg2 string
}
resolveReturns struct {
result1 roomdb.Alias
result2 error
}
resolveReturnsOnCall map[int]struct {
result1 roomdb.Alias
result2 error
}
RevokeStub func(context.Context, string) error
revokeMutex sync.RWMutex
revokeArgsForCall []struct {
arg1 context.Context
arg2 string
}
revokeReturns struct {
result1 error
}
revokeReturnsOnCall map[int]struct {
result1 error
}
invocations map[string][][]interface{}
invocationsMutex sync.RWMutex
}
func (fake *FakeAliasService) GetByID(arg1 context.Context, arg2 int64) (roomdb.Alias, error) {
fake.getByIDMutex.Lock()
ret, specificReturn := fake.getByIDReturnsOnCall[len(fake.getByIDArgsForCall)]
fake.getByIDArgsForCall = append(fake.getByIDArgsForCall, struct {
arg1 context.Context
arg2 int64
}{arg1, arg2})
stub := fake.GetByIDStub
fakeReturns := fake.getByIDReturns
fake.recordInvocation("GetByID", []interface{}{arg1, arg2})
fake.getByIDMutex.Unlock()
if stub != nil {
return stub(arg1, arg2)
}
if specificReturn {
return ret.result1, ret.result2
}
return fakeReturns.result1, fakeReturns.result2
}
func (fake *FakeAliasService) GetByIDCallCount() int {
fake.getByIDMutex.RLock()
defer fake.getByIDMutex.RUnlock()
return len(fake.getByIDArgsForCall)
}
func (fake *FakeAliasService) GetByIDCalls(stub func(context.Context, int64) (roomdb.Alias, error)) {
fake.getByIDMutex.Lock()
defer fake.getByIDMutex.Unlock()
fake.GetByIDStub = stub
}
func (fake *FakeAliasService) GetByIDArgsForCall(i int) (context.Context, int64) {
fake.getByIDMutex.RLock()
defer fake.getByIDMutex.RUnlock()
argsForCall := fake.getByIDArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2
}
func (fake *FakeAliasService) GetByIDReturns(result1 roomdb.Alias, result2 error) {
fake.getByIDMutex.Lock()
defer fake.getByIDMutex.Unlock()
fake.GetByIDStub = nil
fake.getByIDReturns = struct {
result1 roomdb.Alias
result2 error
}{result1, result2}
}
func (fake *FakeAliasService) GetByIDReturnsOnCall(i int, result1 roomdb.Alias, result2 error) {
fake.getByIDMutex.Lock()
defer fake.getByIDMutex.Unlock()
fake.GetByIDStub = nil
if fake.getByIDReturnsOnCall == nil {
fake.getByIDReturnsOnCall = make(map[int]struct {
result1 roomdb.Alias
result2 error
})
}
fake.getByIDReturnsOnCall[i] = struct {
result1 roomdb.Alias
result2 error
}{result1, result2}
}
func (fake *FakeAliasService) List(arg1 context.Context) ([]roomdb.Alias, error) {
fake.listMutex.Lock()
ret, specificReturn := fake.listReturnsOnCall[len(fake.listArgsForCall)]
fake.listArgsForCall = append(fake.listArgsForCall, struct {
arg1 context.Context
}{arg1})
stub := fake.ListStub
fakeReturns := fake.listReturns
fake.recordInvocation("List", []interface{}{arg1})
fake.listMutex.Unlock()
if stub != nil {
return stub(arg1)
}
if specificReturn {
return ret.result1, ret.result2
}
return fakeReturns.result1, fakeReturns.result2
}
func (fake *FakeAliasService) ListCallCount() int {
fake.listMutex.RLock()
defer fake.listMutex.RUnlock()
return len(fake.listArgsForCall)
}
func (fake *FakeAliasService) ListCalls(stub func(context.Context) ([]roomdb.Alias, error)) {
fake.listMutex.Lock()
defer fake.listMutex.Unlock()
fake.ListStub = stub
}
func (fake *FakeAliasService) ListArgsForCall(i int) context.Context {
fake.listMutex.RLock()
defer fake.listMutex.RUnlock()
argsForCall := fake.listArgsForCall[i]
return argsForCall.arg1
}
func (fake *FakeAliasService) ListReturns(result1 []roomdb.Alias, result2 error) {
fake.listMutex.Lock()
defer fake.listMutex.Unlock()
fake.ListStub = nil
fake.listReturns = struct {
result1 []roomdb.Alias
result2 error
}{result1, result2}
}
func (fake *FakeAliasService) ListReturnsOnCall(i int, result1 []roomdb.Alias, result2 error) {
fake.listMutex.Lock()
defer fake.listMutex.Unlock()
fake.ListStub = nil
if fake.listReturnsOnCall == nil {
fake.listReturnsOnCall = make(map[int]struct {
result1 []roomdb.Alias
result2 error
})
}
fake.listReturnsOnCall[i] = struct {
result1 []roomdb.Alias
result2 error
}{result1, result2}
}
func (fake *FakeAliasService) Register(arg1 context.Context, arg2 string, arg3 refs.FeedRef, arg4 []byte) error {
var arg4Copy []byte
if arg4 != nil {
arg4Copy = make([]byte, len(arg4))
copy(arg4Copy, arg4)
}
fake.registerMutex.Lock()
ret, specificReturn := fake.registerReturnsOnCall[len(fake.registerArgsForCall)]
fake.registerArgsForCall = append(fake.registerArgsForCall, struct {
arg1 context.Context
arg2 string
arg3 refs.FeedRef
arg4 []byte
}{arg1, arg2, arg3, arg4Copy})
stub := fake.RegisterStub
fakeReturns := fake.registerReturns
fake.recordInvocation("Register", []interface{}{arg1, arg2, arg3, arg4Copy})
fake.registerMutex.Unlock()
if stub != nil {
return stub(arg1, arg2, arg3, arg4)
}
if specificReturn {
return ret.result1
}
return fakeReturns.result1
}
func (fake *FakeAliasService) RegisterCallCount() int {
fake.registerMutex.RLock()
defer fake.registerMutex.RUnlock()
return len(fake.registerArgsForCall)
}
func (fake *FakeAliasService) RegisterCalls(stub func(context.Context, string, refs.FeedRef, []byte) error) {
fake.registerMutex.Lock()
defer fake.registerMutex.Unlock()
fake.RegisterStub = stub
}
func (fake *FakeAliasService) RegisterArgsForCall(i int) (context.Context, string, refs.FeedRef, []byte) {
fake.registerMutex.RLock()
defer fake.registerMutex.RUnlock()
argsForCall := fake.registerArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4
}
func (fake *FakeAliasService) RegisterReturns(result1 error) {
fake.registerMutex.Lock()
defer fake.registerMutex.Unlock()
fake.RegisterStub = nil
fake.registerReturns = struct {
result1 error
}{result1}
}
func (fake *FakeAliasService) RegisterReturnsOnCall(i int, result1 error) {
fake.registerMutex.Lock()
defer fake.registerMutex.Unlock()
fake.RegisterStub = nil
if fake.registerReturnsOnCall == nil {
fake.registerReturnsOnCall = make(map[int]struct {
result1 error
})
}
fake.registerReturnsOnCall[i] = struct {
result1 error
}{result1}
}
func (fake *FakeAliasService) Resolve(arg1 context.Context, arg2 string) (roomdb.Alias, error) {
fake.resolveMutex.Lock()
ret, specificReturn := fake.resolveReturnsOnCall[len(fake.resolveArgsForCall)]
fake.resolveArgsForCall = append(fake.resolveArgsForCall, struct {
arg1 context.Context
arg2 string
}{arg1, arg2})
stub := fake.ResolveStub
fakeReturns := fake.resolveReturns
fake.recordInvocation("Resolve", []interface{}{arg1, arg2})
fake.resolveMutex.Unlock()
if stub != nil {
return stub(arg1, arg2)
}
if specificReturn {
return ret.result1, ret.result2
}
return fakeReturns.result1, fakeReturns.result2
}
func (fake *FakeAliasService) ResolveCallCount() int {
fake.resolveMutex.RLock()
defer fake.resolveMutex.RUnlock()
return len(fake.resolveArgsForCall)
}
func (fake *FakeAliasService) ResolveCalls(stub func(context.Context, string) (roomdb.Alias, error)) {
fake.resolveMutex.Lock()
defer fake.resolveMutex.Unlock()
fake.ResolveStub = stub
}
func (fake *FakeAliasService) ResolveArgsForCall(i int) (context.Context, string) {
fake.resolveMutex.RLock()
defer fake.resolveMutex.RUnlock()
argsForCall := fake.resolveArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2
}
func (fake *FakeAliasService) ResolveReturns(result1 roomdb.Alias, result2 error) {
fake.resolveMutex.Lock()
defer fake.resolveMutex.Unlock()
fake.ResolveStub = nil
fake.resolveReturns = struct {
result1 roomdb.Alias
result2 error
}{result1, result2}
}
func (fake *FakeAliasService) ResolveReturnsOnCall(i int, result1 roomdb.Alias, result2 error) {
fake.resolveMutex.Lock()
defer fake.resolveMutex.Unlock()
fake.ResolveStub = nil
if fake.resolveReturnsOnCall == nil {
fake.resolveReturnsOnCall = make(map[int]struct {
result1 roomdb.Alias
result2 error
})
}
fake.resolveReturnsOnCall[i] = struct {
result1 roomdb.Alias
result2 error
}{result1, result2}
}
func (fake *FakeAliasService) Revoke(arg1 context.Context, arg2 string) error {
fake.revokeMutex.Lock()
ret, specificReturn := fake.revokeReturnsOnCall[len(fake.revokeArgsForCall)]
fake.revokeArgsForCall = append(fake.revokeArgsForCall, struct {
arg1 context.Context
arg2 string
}{arg1, arg2})
stub := fake.RevokeStub
fakeReturns := fake.revokeReturns
fake.recordInvocation("Revoke", []interface{}{arg1, arg2})
fake.revokeMutex.Unlock()
if stub != nil {
return stub(arg1, arg2)
}
if specificReturn {
return ret.result1
}
return fakeReturns.result1
}
func (fake *FakeAliasService) RevokeCallCount() int {
fake.revokeMutex.RLock()
defer fake.revokeMutex.RUnlock()
return len(fake.revokeArgsForCall)
}
func (fake *FakeAliasService) RevokeCalls(stub func(context.Context, string) error) {
fake.revokeMutex.Lock()
defer fake.revokeMutex.Unlock()
fake.RevokeStub = stub
}
func (fake *FakeAliasService) RevokeArgsForCall(i int) (context.Context, string) {
fake.revokeMutex.RLock()
defer fake.revokeMutex.RUnlock()
argsForCall := fake.revokeArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2
}
func (fake *FakeAliasService) RevokeReturns(result1 error) {
fake.revokeMutex.Lock()
defer fake.revokeMutex.Unlock()
fake.RevokeStub = nil
fake.revokeReturns = struct {
result1 error
}{result1}
}
func (fake *FakeAliasService) RevokeReturnsOnCall(i int, result1 error) {
fake.revokeMutex.Lock()
defer fake.revokeMutex.Unlock()
fake.RevokeStub = nil
if fake.revokeReturnsOnCall == nil {
fake.revokeReturnsOnCall = make(map[int]struct {
result1 error
})
}
fake.revokeReturnsOnCall[i] = struct {
result1 error
}{result1}
}
func (fake *FakeAliasService) Invocations() map[string][][]interface{} {
fake.invocationsMutex.RLock()
defer fake.invocationsMutex.RUnlock()
fake.getByIDMutex.RLock()
defer fake.getByIDMutex.RUnlock()
fake.listMutex.RLock()
defer fake.listMutex.RUnlock()
fake.registerMutex.RLock()
defer fake.registerMutex.RUnlock()
fake.resolveMutex.RLock()
defer fake.resolveMutex.RUnlock()
fake.revokeMutex.RLock()
defer fake.revokeMutex.RUnlock()
copiedInvocations := map[string][][]interface{}{}
for key, value := range fake.invocations {
copiedInvocations[key] = value

View File

@ -3,9 +3,16 @@
package sqlite
import (
"context"
"database/sql"
"github.com/friendsofgo/errors"
"github.com/volatiletech/sqlboiler/v4/boil"
"github.com/volatiletech/sqlboiler/v4/queries/qm"
"github.com/ssb-ngi-pointer/go-ssb-room/roomdb"
"github.com/ssb-ngi-pointer/go-ssb-room/roomdb/sqlite/models"
refs "go.mindeco.de/ssb-refs"
)
// compiler assertion to ensure the struct fullfills the interface
@ -14,3 +21,98 @@ var _ roomdb.AliasService = (*Aliases)(nil)
type Aliases struct {
db *sql.DB
}
// Resolve returns all the relevant information for that alias or an error if it doesnt exist
func (a Aliases) Resolve(ctx context.Context, name string) (roomdb.Alias, error) {
return a.findOne(ctx, qm.Where("name = ?", name))
}
// GetByID returns the alias for that ID or an error
func (a Aliases) GetByID(ctx context.Context, id int64) (roomdb.Alias, error) {
return a.findOne(ctx, qm.Where("id = ?", id))
}
func (a Aliases) findOne(ctx context.Context, by qm.QueryMod) (roomdb.Alias, error) {
var found roomdb.Alias
// construct query which resolves the User relation and by which we shoudl look for it
qry := append([]qm.QueryMod{qm.Load("User")}, by)
entry, err := models.Aliases(qry...).One(ctx, a.db)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return found, roomdb.ErrNotFound
}
return found, err
}
// unpack models into roomdb type
found.ID = entry.ID
found.Name = entry.Name
found.Signature = entry.Signature
found.Feed = entry.R.User.PubKey.FeedRef
return found, nil
}
// List returns a list of all registerd aliases
func (a Aliases) List(ctx context.Context) ([]roomdb.Alias, error) {
all, err := models.Aliases(qm.Load("User")).All(ctx, a.db)
if err != nil {
return nil, err
}
var aliases = make([]roomdb.Alias, len(all))
for i, entry := range all {
aliases[i] = roomdb.Alias{
ID: entry.ID,
Name: entry.Name,
Feed: entry.R.User.PubKey.FeedRef,
Signature: entry.Signature,
}
}
return aliases, nil
}
// Register receives an alias and signature for it. Validation needs to happen before this.
func (a Aliases) Register(ctx context.Context, alias string, userFeed refs.FeedRef, signature []byte) error {
return transact(a.db, func(tx *sql.Tx) error {
// check we have a members entry for the feed and load it to get its ID
allowListEntry, err := models.AllowLists(qm.Where("pub_key = ?", userFeed.Ref())).One(ctx, tx)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return roomdb.ErrNotFound
}
return err
}
var newEntry models.Alias
newEntry.Name = alias
newEntry.UserID = allowListEntry.ID
newEntry.Signature = signature
err = newEntry.Insert(ctx, tx, boil.Infer())
return err
})
}
// Revoke removes an alias from the system
func (a Aliases) Revoke(ctx context.Context, alias string) error {
return transact(a.db, func(tx *sql.Tx) error {
qry := append([]qm.QueryMod{qm.Load("User")}, qm.Where("name = ?", alias))
entry, err := models.Aliases(qry...).One(ctx, a.db)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return roomdb.ErrNotFound
}
return err
}
_, err = entry.Delete(ctx, tx)
return err
})
}

View File

@ -0,0 +1,96 @@
package sqlite
import (
"bytes"
"context"
"crypto/rand"
"errors"
"os"
"path/filepath"
"testing"
"github.com/ssb-ngi-pointer/go-ssb-room/internal/repo"
"github.com/ssb-ngi-pointer/go-ssb-room/roomdb"
"github.com/stretchr/testify/require"
refs "go.mindeco.de/ssb-refs"
)
func TestAliases(t *testing.T) {
ctx := context.Background()
testRepo := filepath.Join("testrun", t.Name())
os.RemoveAll(testRepo)
tr := repo.New(testRepo)
// fake feed for testing, looks ok at least
newMember := refs.FeedRef{ID: bytes.Repeat([]byte("acab"), 8), Algo: refs.RefAlgoFeedSSB1}
// 64 bytes of random for testing (validation is handled by the handlers)
testSig := make([]byte, 64)
rand.Read(testSig)
db, err := Open(tr)
require.NoError(t, err)
t.Run("not found", func(t *testing.T) {
r := require.New(t)
lst, err := db.Aliases.List(ctx)
r.NoError(err)
r.Len(lst, 0)
_, err = db.Aliases.GetByID(ctx, 9999)
r.Error(err)
r.EqualError(err, roomdb.ErrNotFound.Error())
_, err = db.Aliases.Resolve(ctx, "unknown")
r.Error(err)
r.EqualError(err, roomdb.ErrNotFound.Error())
err = db.Aliases.Revoke(ctx, "unknown")
r.Error(err)
r.EqualError(errors.Unwrap(err), roomdb.ErrNotFound.Error())
})
t.Run("register and revoke again", func(t *testing.T) {
r := require.New(t)
testName := "flaky"
// shouldnt work while not a member
err = db.Aliases.Register(ctx, testName, newMember, testSig)
r.Error(err)
// allow the member
err = db.AllowList.Add(ctx, newMember)
r.NoError(err)
err = db.Aliases.Register(ctx, testName, newMember, testSig)
r.NoError(err)
// should have one member now
lst, err := db.Aliases.List(ctx)
r.NoError(err)
r.Len(lst, 1)
aliasByID, err := db.Aliases.GetByID(ctx, lst[0].ID)
r.NoError(err)
r.Equal(testName, aliasByID.Name)
r.Equal(testSig, aliasByID.Signature)
resolvedAlias, err := db.Aliases.Resolve(ctx, testName)
r.NoError(err)
r.Equal(aliasByID, resolvedAlias)
err = db.Aliases.Revoke(ctx, testName)
r.NoError(err)
_, err = db.Aliases.GetByID(ctx, lst[0].ID)
r.Error(err)
r.EqualError(err, roomdb.ErrNotFound.Error())
_, err = db.Aliases.Resolve(ctx, testName)
r.Error(err)
r.EqualError(err, roomdb.ErrNotFound.Error())
})
}

View File

@ -0,0 +1,18 @@
-- +migrate Up
CREATE TABLE aliases (
id integer PRIMARY KEY AUTOINCREMENT NOT NULL,
name text UNIQUE NOT NULL,
user_id integer NOT NULL,
signature blob not null,
FOREIGN KEY ( user_id ) REFERENCES allow_list( "id" )
);
CREATE UNIQUE INDEX aliases_ids ON aliases(id);
CREATE UNIQUE INDEX aliases_names ON aliases(name);
-- +migrate Down
DROP TABLE aliases;
DROP INDEX aliases_ids;
DROP INDEX aliases_names;

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@ import (
// AllowList is an object representing the database table.
type AllowList struct {
ID int64 `boil:"id" json:"id" toml:"id" yaml:"id"`
ID int64 `boil:"id" json:"id" toml:"id" yaml:"id"`
PubKey roomdb.DBFeedRef `boil:"pub_key" json:"pub_key" toml:"pub_key" yaml:"pub_key"`
R *allowListR `boil:"-" json:"-" toml:"-" yaml:"-"`
@ -40,64 +40,45 @@ var AllowListColumns = struct {
// Generated where
type whereHelperint64 struct{ field string }
type whereHelperroomdb_DBFeedRef struct{ field string }
func (w whereHelperint64) EQ(x int64) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.EQ, x) }
func (w whereHelperint64) NEQ(x int64) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.NEQ, x) }
func (w whereHelperint64) LT(x int64) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LT, x) }
func (w whereHelperint64) LTE(x int64) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LTE, x) }
func (w whereHelperint64) GT(x int64) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GT, x) }
func (w whereHelperint64) GTE(x int64) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GTE, x) }
func (w whereHelperint64) IN(slice []int64) qm.QueryMod {
values := make([]interface{}, 0, len(slice))
for _, value := range slice {
values = append(values, value)
}
return qm.WhereIn(fmt.Sprintf("%s IN ?", w.field), values...)
}
func (w whereHelperint64) NIN(slice []int64) qm.QueryMod {
values := make([]interface{}, 0, len(slice))
for _, value := range slice {
values = append(values, value)
}
return qm.WhereNotIn(fmt.Sprintf("%s NOT IN ?", w.field), values...)
}
type whereHelperadmindb_DBFeedRef struct{ field string }
func (w whereHelperadmindb_DBFeedRef) EQ(x roomdb.DBFeedRef) qm.QueryMod {
func (w whereHelperroomdb_DBFeedRef) EQ(x roomdb.DBFeedRef) qm.QueryMod {
return qmhelper.Where(w.field, qmhelper.EQ, x)
}
func (w whereHelperadmindb_DBFeedRef) NEQ(x roomdb.DBFeedRef) qm.QueryMod {
func (w whereHelperroomdb_DBFeedRef) NEQ(x roomdb.DBFeedRef) qm.QueryMod {
return qmhelper.Where(w.field, qmhelper.NEQ, x)
}
func (w whereHelperadmindb_DBFeedRef) LT(x roomdb.DBFeedRef) qm.QueryMod {
func (w whereHelperroomdb_DBFeedRef) LT(x roomdb.DBFeedRef) qm.QueryMod {
return qmhelper.Where(w.field, qmhelper.LT, x)
}
func (w whereHelperadmindb_DBFeedRef) LTE(x roomdb.DBFeedRef) qm.QueryMod {
func (w whereHelperroomdb_DBFeedRef) LTE(x roomdb.DBFeedRef) qm.QueryMod {
return qmhelper.Where(w.field, qmhelper.LTE, x)
}
func (w whereHelperadmindb_DBFeedRef) GT(x roomdb.DBFeedRef) qm.QueryMod {
func (w whereHelperroomdb_DBFeedRef) GT(x roomdb.DBFeedRef) qm.QueryMod {
return qmhelper.Where(w.field, qmhelper.GT, x)
}
func (w whereHelperadmindb_DBFeedRef) GTE(x roomdb.DBFeedRef) qm.QueryMod {
func (w whereHelperroomdb_DBFeedRef) GTE(x roomdb.DBFeedRef) qm.QueryMod {
return qmhelper.Where(w.field, qmhelper.GTE, x)
}
var AllowListWhere = struct {
ID whereHelperint64
PubKey whereHelperadmindb_DBFeedRef
PubKey whereHelperroomdb_DBFeedRef
}{
ID: whereHelperint64{field: "\"allow_list\".\"id\""},
PubKey: whereHelperadmindb_DBFeedRef{field: "\"allow_list\".\"pub_key\""},
PubKey: whereHelperroomdb_DBFeedRef{field: "\"allow_list\".\"pub_key\""},
}
// AllowListRels is where relationship names are stored.
var AllowListRels = struct {
}{}
UserAliases string
}{
UserAliases: "UserAliases",
}
// allowListR is where relationships are stored.
type allowListR struct {
UserAliases AliasSlice `boil:"UserAliases" json:"UserAliases" toml:"UserAliases" yaml:"UserAliases"`
}
// NewStruct creates a new relationship struct
@ -390,6 +371,178 @@ func (q allowListQuery) Exists(ctx context.Context, exec boil.ContextExecutor) (
return count > 0, nil
}
// UserAliases retrieves all the alias's Aliases with an executor via user_id column.
func (o *AllowList) UserAliases(mods ...qm.QueryMod) aliasQuery {
var queryMods []qm.QueryMod
if len(mods) != 0 {
queryMods = append(queryMods, mods...)
}
queryMods = append(queryMods,
qm.Where("\"aliases\".\"user_id\"=?", o.ID),
)
query := Aliases(queryMods...)
queries.SetFrom(query.Query, "\"aliases\"")
if len(queries.GetSelect(query.Query)) == 0 {
queries.SetSelect(query.Query, []string{"\"aliases\".*"})
}
return query
}
// LoadUserAliases allows an eager lookup of values, cached into the
// loaded structs of the objects. This is for a 1-M or N-M relationship.
func (allowListL) LoadUserAliases(ctx context.Context, e boil.ContextExecutor, singular bool, maybeAllowList interface{}, mods queries.Applicator) error {
var slice []*AllowList
var object *AllowList
if singular {
object = maybeAllowList.(*AllowList)
} else {
slice = *maybeAllowList.(*[]*AllowList)
}
args := make([]interface{}, 0, 1)
if singular {
if object.R == nil {
object.R = &allowListR{}
}
args = append(args, object.ID)
} else {
Outer:
for _, obj := range slice {
if obj.R == nil {
obj.R = &allowListR{}
}
for _, a := range args {
if a == obj.ID {
continue Outer
}
}
args = append(args, obj.ID)
}
}
if len(args) == 0 {
return nil
}
query := NewQuery(
qm.From(`aliases`),
qm.WhereIn(`aliases.user_id in ?`, args...),
)
if mods != nil {
mods.Apply(query)
}
results, err := query.QueryContext(ctx, e)
if err != nil {
return errors.Wrap(err, "failed to eager load aliases")
}
var resultSlice []*Alias
if err = queries.Bind(results, &resultSlice); err != nil {
return errors.Wrap(err, "failed to bind eager loaded slice aliases")
}
if err = results.Close(); err != nil {
return errors.Wrap(err, "failed to close results in eager load on aliases")
}
if err = results.Err(); err != nil {
return errors.Wrap(err, "error occurred during iteration of eager loaded relations for aliases")
}
if len(aliasAfterSelectHooks) != 0 {
for _, obj := range resultSlice {
if err := obj.doAfterSelectHooks(ctx, e); err != nil {
return err
}
}
}
if singular {
object.R.UserAliases = resultSlice
for _, foreign := range resultSlice {
if foreign.R == nil {
foreign.R = &aliasR{}
}
foreign.R.User = object
}
return nil
}
for _, foreign := range resultSlice {
for _, local := range slice {
if local.ID == foreign.UserID {
local.R.UserAliases = append(local.R.UserAliases, foreign)
if foreign.R == nil {
foreign.R = &aliasR{}
}
foreign.R.User = local
break
}
}
}
return nil
}
// AddUserAliases adds the given related objects to the existing relationships
// of the allow_list, optionally inserting them as new records.
// Appends related to o.R.UserAliases.
// Sets related.R.User appropriately.
func (o *AllowList) AddUserAliases(ctx context.Context, exec boil.ContextExecutor, insert bool, related ...*Alias) error {
var err error
for _, rel := range related {
if insert {
rel.UserID = o.ID
if err = rel.Insert(ctx, exec, boil.Infer()); err != nil {
return errors.Wrap(err, "failed to insert into foreign table")
}
} else {
updateQuery := fmt.Sprintf(
"UPDATE \"aliases\" SET %s WHERE %s",
strmangle.SetParamNames("\"", "\"", 0, []string{"user_id"}),
strmangle.WhereClause("\"", "\"", 0, aliasPrimaryKeyColumns),
)
values := []interface{}{o.ID, rel.ID}
if boil.IsDebug(ctx) {
writer := boil.DebugWriterFrom(ctx)
fmt.Fprintln(writer, updateQuery)
fmt.Fprintln(writer, values)
}
if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil {
return errors.Wrap(err, "failed to update foreign table")
}
rel.UserID = o.ID
}
}
if o.R == nil {
o.R = &allowListR{
UserAliases: related,
}
} else {
o.R.UserAliases = append(o.R.UserAliases, related...)
}
for _, rel := range related {
if rel.R == nil {
rel.R = &aliasR{
User: o,
}
} else {
rel.R.User = o
}
}
return nil
}
// AllowLists retrieves all the records using an executor.
func AllowLists(mods ...qm.QueryMod) allowListQuery {
mods = append(mods, qm.From("\"allow_list\""))

View File

@ -42,38 +42,6 @@ var AuthFallbackColumns = struct {
// Generated where
type whereHelperstring struct{ field string }
func (w whereHelperstring) EQ(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.EQ, x) }
func (w whereHelperstring) NEQ(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.NEQ, x) }
func (w whereHelperstring) LT(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LT, x) }
func (w whereHelperstring) LTE(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LTE, x) }
func (w whereHelperstring) GT(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GT, x) }
func (w whereHelperstring) GTE(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GTE, x) }
func (w whereHelperstring) IN(slice []string) qm.QueryMod {
values := make([]interface{}, 0, len(slice))
for _, value := range slice {
values = append(values, value)
}
return qm.WhereIn(fmt.Sprintf("%s IN ?", w.field), values...)
}
func (w whereHelperstring) NIN(slice []string) qm.QueryMod {
values := make([]interface{}, 0, len(slice))
for _, value := range slice {
values = append(values, value)
}
return qm.WhereNotIn(fmt.Sprintf("%s NOT IN ?", w.field), values...)
}
type whereHelper__byte struct{ field string }
func (w whereHelper__byte) EQ(x []byte) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.EQ, x) }
func (w whereHelper__byte) NEQ(x []byte) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.NEQ, x) }
func (w whereHelper__byte) LT(x []byte) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LT, x) }
func (w whereHelper__byte) LTE(x []byte) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LTE, x) }
func (w whereHelper__byte) GT(x []byte) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GT, x) }
func (w whereHelper__byte) GTE(x []byte) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GTE, x) }
var AuthFallbackWhere = struct {
ID whereHelperint64
Name whereHelperstring

View File

@ -4,6 +4,7 @@
package models
var TableNames = struct {
Aliases string
AllowList string
AuthFallback string
Invites string
@ -11,6 +12,7 @@ var TableNames = struct {
PinNotices string
Pins string
}{
Aliases: "aliases",
AllowList: "allow_list",
AuthFallback: "auth_fallback",
Invites: "invites",

View File

@ -26,8 +26,8 @@ import (
migrate "github.com/rubenv/sql-migrate"
"github.com/ssb-ngi-pointer/go-ssb-room/roomdb"
"github.com/ssb-ngi-pointer/go-ssb-room/internal/repo"
"github.com/ssb-ngi-pointer/go-ssb-room/roomdb"
)
type Database struct {

View File

@ -40,8 +40,8 @@ func (al AllowList) add(ctx context.Context, tx *sql.Tx, a refs.FeedRef) error {
}
var entry models.AllowList
entry.PubKey.FeedRef = a
err := entry.Insert(ctx, tx, boil.Whitelist("pub_key"))
if err != nil {
var sqlErr sqlite3.Error
@ -99,7 +99,6 @@ func (al AllowList) List(ctx context.Context) (roomdb.ListEntries, error) {
var asRefs = make(roomdb.ListEntries, len(all))
for i, allowed := range all {
asRefs[i] = roomdb.ListEntry{
ID: allowed.ID,
PubKey: allowed.PubKey.FeedRef,

View File

@ -14,6 +14,17 @@ import (
// ErrNotFound is returned by the admin db if an object couldn't be found.
var ErrNotFound = errors.New("roomdb: object not found")
// Alias is how the roomdb stores an alias.
type Alias struct {
ID int64
Name string // or "alias string" as the docs call it
Feed refs.FeedRef // the ssb identity that belongs to the user
Signature []byte
}
// User holds all the information an authenticated user of the site has.
type User struct {
ID int64