2021-10-08 12:39:31 +00:00
|
|
|
// SPDX-FileCopyrightText: 2021 The NGI Pointer Secure-Scuttlebutt Team of 2020/2021
|
|
|
|
//
|
2021-02-09 11:53:33 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
2021-02-08 16:47:42 +00:00
|
|
|
package sqlite
|
|
|
|
|
|
|
|
import (
|
2021-03-11 16:57:55 +00:00
|
|
|
"context"
|
2021-02-08 16:47:42 +00:00
|
|
|
"database/sql"
|
|
|
|
|
2021-03-11 16:57:55 +00:00
|
|
|
"github.com/friendsofgo/errors"
|
2021-05-10 11:51:05 +00:00
|
|
|
"github.com/mattn/go-sqlite3"
|
2021-03-11 16:57:55 +00:00
|
|
|
"github.com/volatiletech/sqlboiler/v4/boil"
|
|
|
|
"github.com/volatiletech/sqlboiler/v4/queries/qm"
|
|
|
|
|
2022-11-07 09:18:13 +00:00
|
|
|
refs "github.com/ssbc/go-ssb-refs"
|
|
|
|
"github.com/ssbc/go-ssb-room/v2/roomdb"
|
|
|
|
"github.com/ssbc/go-ssb-room/v2/roomdb/sqlite/models"
|
2021-02-08 16:47:42 +00:00
|
|
|
)
|
|
|
|
|
2021-03-02 16:14:02 +00:00
|
|
|
// compiler assertion to ensure the struct fullfills the interface
|
2021-03-18 16:49:52 +00:00
|
|
|
var _ roomdb.AliasesService = (*Aliases)(nil)
|
2021-02-08 16:47:42 +00:00
|
|
|
|
|
|
|
type Aliases struct {
|
|
|
|
db *sql.DB
|
|
|
|
}
|
2021-03-11 16:57:55 +00:00
|
|
|
|
|
|
|
// 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
|
|
|
|
|
2021-03-18 16:49:52 +00:00
|
|
|
// construct query which resolves the Member relation and by which we shoudl look for it
|
|
|
|
qry := append([]qm.QueryMod{qm.Load("Member")}, by)
|
2021-03-11 16:57:55 +00:00
|
|
|
|
|
|
|
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
|
2021-03-18 16:49:52 +00:00
|
|
|
found.Feed = entry.R.Member.PubKey.FeedRef
|
2021-03-11 16:57:55 +00:00
|
|
|
|
|
|
|
return found, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// List returns a list of all registerd aliases
|
|
|
|
func (a Aliases) List(ctx context.Context) ([]roomdb.Alias, error) {
|
2021-03-18 16:49:52 +00:00
|
|
|
all, err := models.Aliases(qm.Load("Member")).All(ctx, a.db)
|
2021-03-11 16:57:55 +00:00
|
|
|
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,
|
2021-03-18 16:49:52 +00:00
|
|
|
Feed: entry.R.Member.PubKey.FeedRef,
|
2021-03-11 16:57:55 +00:00
|
|
|
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
|
2022-11-07 09:18:13 +00:00
|
|
|
memberEntry, err := models.Members(qm.Where("pub_key = ?", userFeed.String())).One(ctx, tx)
|
2021-03-11 16:57:55 +00:00
|
|
|
if err != nil {
|
|
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
|
|
return roomdb.ErrNotFound
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var newEntry models.Alias
|
|
|
|
newEntry.Name = alias
|
2021-03-18 16:49:52 +00:00
|
|
|
newEntry.MemberID = memberEntry.ID
|
2021-03-11 16:57:55 +00:00
|
|
|
newEntry.Signature = signature
|
|
|
|
|
|
|
|
err = newEntry.Insert(ctx, tx, boil.Infer())
|
2021-05-10 11:51:05 +00:00
|
|
|
var sqlErr sqlite3.Error
|
|
|
|
if errors.As(err, &sqlErr) && sqlErr.ExtendedCode == sqlite3.ErrConstraintUnique {
|
|
|
|
return roomdb.ErrAliasTaken{Name: alias}
|
|
|
|
}
|
2021-03-11 16:57:55 +00:00
|
|
|
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 {
|
2021-03-18 16:49:52 +00:00
|
|
|
qry := append([]qm.QueryMod{qm.Load("Member")}, qm.Where("name = ?", alias))
|
2021-03-11 16:57:55 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
})
|
|
|
|
}
|