70 lines
1.8 KiB
Go
70 lines
1.8 KiB
Go
|
package db
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"database/sql"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"strings"
|
||
|
|
||
|
"git.faercol.me/faercol/polyculeconnect/polyculeconnect/config"
|
||
|
"git.faercol.me/faercol/polyculeconnect/polyculeconnect/internal/model"
|
||
|
_ "github.com/mattn/go-sqlite3"
|
||
|
)
|
||
|
|
||
|
const clientRows = `"client"."id", "client"."secret", "client"."redirect_uris", "client"."trusted_peers", "client"."name"`
|
||
|
|
||
|
type ClientDB interface {
|
||
|
GetClientByID(ctx context.Context, id string) (*model.Client, error)
|
||
|
}
|
||
|
|
||
|
type sqlClientDB struct {
|
||
|
db *sql.DB
|
||
|
}
|
||
|
|
||
|
func strArrayToSlice(rawVal string) []string { // TODO this won't work if there's more than one element
|
||
|
res := []string{}
|
||
|
insideStr, ok := strings.CutPrefix(rawVal, `["`)
|
||
|
if !ok {
|
||
|
return res
|
||
|
}
|
||
|
insideStr, ok = strings.CutSuffix(insideStr, `"]`)
|
||
|
if !ok {
|
||
|
return res
|
||
|
}
|
||
|
|
||
|
return []string{insideStr}
|
||
|
}
|
||
|
|
||
|
func clientFromRow(row *sql.Row) (*model.Client, error) {
|
||
|
var res model.Client
|
||
|
redirectURIsStr := ""
|
||
|
trustedPeersStr := ""
|
||
|
|
||
|
if err := row.Scan(&res.ID, &res.Secret, &redirectURIsStr, &trustedPeersStr, &res.Name); err != nil {
|
||
|
if errors.Is(err, sql.ErrNoRows) {
|
||
|
return nil, ErrNotFound
|
||
|
}
|
||
|
return nil, fmt.Errorf("invalid format for client: %w", err)
|
||
|
}
|
||
|
|
||
|
res.ClientConfig.RedirectURIs = strArrayToSlice(redirectURIsStr)
|
||
|
res.ClientConfig.TrustedPeers = strArrayToSlice(trustedPeersStr)
|
||
|
|
||
|
return &res, nil
|
||
|
}
|
||
|
|
||
|
func (db *sqlClientDB) GetClientByID(ctx context.Context, id string) (*model.Client, error) {
|
||
|
query := fmt.Sprintf(`SELECT %s FROM "client" WHERE "id" = ?`, clientRows)
|
||
|
row := db.db.QueryRowContext(ctx, query, id)
|
||
|
return clientFromRow(row)
|
||
|
}
|
||
|
|
||
|
func New(conf config.AppConfig) (*sqlClientDB, error) {
|
||
|
db, err := sql.Open("sqlite3", conf.StorageConfig.File)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("failed to open DB: %w", err)
|
||
|
}
|
||
|
return &sqlClientDB{db: db}, nil
|
||
|
}
|