2021-10-08 12:39:31 +00:00
|
|
|
// SPDX-FileCopyrightText: 2021 The NGI Pointer Secure-Scuttlebutt Team of 2020/2021
|
|
|
|
//
|
2021-03-12 13:11:10 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
2021-03-16 08:10:44 +00:00
|
|
|
// Package alias implements the muxrpc handlers for alias needs.
|
2021-03-11 17:40:33 +00:00
|
|
|
package alias
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2021-03-12 11:16:00 +00:00
|
|
|
"encoding/base64"
|
2021-03-11 17:40:33 +00:00
|
|
|
"encoding/json"
|
2021-05-10 11:51:05 +00:00
|
|
|
"errors"
|
2021-03-11 17:40:33 +00:00
|
|
|
"fmt"
|
2021-03-12 11:16:00 +00:00
|
|
|
"strings"
|
2021-03-11 17:40:33 +00:00
|
|
|
|
2022-11-07 09:18:13 +00:00
|
|
|
"github.com/ssbc/go-muxrpc/v2"
|
2021-05-21 07:27:12 +00:00
|
|
|
kitlog "go.mindeco.de/log"
|
2021-03-12 12:43:52 +00:00
|
|
|
|
2022-11-07 09:18:13 +00:00
|
|
|
refs "github.com/ssbc/go-ssb-refs"
|
|
|
|
"github.com/ssbc/go-ssb-room/v2/internal/aliases"
|
|
|
|
"github.com/ssbc/go-ssb-room/v2/internal/network"
|
|
|
|
"github.com/ssbc/go-ssb-room/v2/roomdb"
|
|
|
|
"github.com/ssbc/go-ssb-room/v2/web/router"
|
2021-03-11 17:40:33 +00:00
|
|
|
)
|
|
|
|
|
2021-03-16 08:10:44 +00:00
|
|
|
// Handler implements the muxrpc methods for alias registration and recvocation
|
2021-03-11 17:40:33 +00:00
|
|
|
type Handler struct {
|
|
|
|
logger kitlog.Logger
|
|
|
|
self refs.FeedRef
|
|
|
|
|
2021-03-19 10:51:06 +00:00
|
|
|
db roomdb.AliasesService
|
2021-03-23 15:50:25 +00:00
|
|
|
|
2021-04-19 12:52:12 +00:00
|
|
|
netInfo network.ServerEndpointDetails
|
|
|
|
|
|
|
|
// roomDomain string // the http(s) domain of the room to signal alias addresses
|
2021-03-11 17:40:33 +00:00
|
|
|
}
|
|
|
|
|
2021-03-16 08:10:44 +00:00
|
|
|
// New returns a fresh alias muxrpc handler
|
2021-04-19 12:52:12 +00:00
|
|
|
func New(log kitlog.Logger, self refs.FeedRef, aliasesDB roomdb.AliasesService, netInfo network.ServerEndpointDetails) Handler {
|
2021-03-23 15:50:25 +00:00
|
|
|
|
2021-03-16 08:10:44 +00:00
|
|
|
var h Handler
|
|
|
|
h.self = self
|
2021-04-19 12:52:12 +00:00
|
|
|
h.netInfo = netInfo
|
2021-03-16 08:10:44 +00:00
|
|
|
h.logger = log
|
2021-03-19 10:51:06 +00:00
|
|
|
h.db = aliasesDB
|
2021-03-16 08:10:44 +00:00
|
|
|
|
|
|
|
return h
|
|
|
|
}
|
|
|
|
|
2021-03-12 11:16:00 +00:00
|
|
|
const sigSuffix = ".sig.ed25519"
|
|
|
|
|
2021-03-23 15:50:25 +00:00
|
|
|
var httpRouter = router.CompleteApp()
|
|
|
|
|
2021-03-16 08:10:44 +00:00
|
|
|
// Register is an async muxrpc method handler for registering aliases.
|
|
|
|
// It receives two string arguments over muxrpc (alias and signature),
|
|
|
|
// checks the signature confirmation is correct (for this room and signed by the key of theconnection)
|
|
|
|
// If it is valid, it registers the alias on the roomdb and returns true. If not it returns an error.
|
2021-03-11 17:40:33 +00:00
|
|
|
func (h Handler) Register(ctx context.Context, req *muxrpc.Request) (interface{}, error) {
|
2021-03-12 11:16:00 +00:00
|
|
|
var args []string
|
2021-03-11 17:40:33 +00:00
|
|
|
|
|
|
|
err := json.Unmarshal(req.RawArgs, &args)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("registerAlias: bad request: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n := len(args); n != 2 {
|
|
|
|
return nil, fmt.Errorf("registerAlias: expected two arguments got %d", n)
|
|
|
|
}
|
|
|
|
|
2021-03-12 11:16:00 +00:00
|
|
|
if !strings.HasSuffix(args[1], sigSuffix) {
|
|
|
|
return nil, fmt.Errorf("registerAlias: signature does not have the expected suffix")
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove the suffix of the base64 string
|
|
|
|
sig := strings.TrimSuffix(args[1], sigSuffix)
|
|
|
|
|
2021-03-11 17:40:33 +00:00
|
|
|
var confirmation aliases.Confirmation
|
|
|
|
confirmation.RoomID = h.self
|
2021-03-12 11:16:00 +00:00
|
|
|
confirmation.Alias = args[0]
|
|
|
|
confirmation.Signature, err = base64.StdEncoding.DecodeString(sig)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("registerAlias: bad signature encoding: %w", err)
|
|
|
|
}
|
|
|
|
|
2021-03-11 17:40:33 +00:00
|
|
|
// check alias is valid
|
2021-03-12 13:11:22 +00:00
|
|
|
if !aliases.IsValid(confirmation.Alias) {
|
|
|
|
return nil, fmt.Errorf("registerAlias: invalid alias")
|
|
|
|
}
|
2021-03-11 17:40:33 +00:00
|
|
|
|
|
|
|
// get the user from the muxrpc connection
|
|
|
|
userID, err := network.GetFeedRefFromAddr(req.RemoteAddr())
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-11-07 09:18:13 +00:00
|
|
|
confirmation.UserID = userID
|
2021-03-11 17:40:33 +00:00
|
|
|
|
|
|
|
// check the signature
|
|
|
|
if !confirmation.Verify() {
|
|
|
|
return nil, fmt.Errorf("registerAlias: invalid signature")
|
|
|
|
}
|
|
|
|
|
2021-03-12 09:53:43 +00:00
|
|
|
err = h.db.Register(ctx, confirmation.Alias, confirmation.UserID, confirmation.Signature)
|
2021-03-11 17:40:33 +00:00
|
|
|
if err != nil {
|
2021-05-10 11:51:05 +00:00
|
|
|
var takenErr roomdb.ErrAliasTaken
|
|
|
|
if errors.As(err, &takenErr) {
|
|
|
|
return nil, takenErr
|
|
|
|
}
|
2021-03-11 17:40:33 +00:00
|
|
|
return nil, fmt.Errorf("registerAlias: could not register alias: %w", err)
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:52:12 +00:00
|
|
|
return h.netInfo.URLForAlias(confirmation.Alias), nil
|
2021-03-11 17:40:33 +00:00
|
|
|
}
|
2021-03-16 08:13:27 +00:00
|
|
|
|
|
|
|
// Revoke checks that the alias is from that user before revoking the alias from the database.
|
|
|
|
func (h Handler) Revoke(ctx context.Context, req *muxrpc.Request) (interface{}, error) {
|
|
|
|
var args []string
|
|
|
|
|
|
|
|
err := json.Unmarshal(req.RawArgs, &args)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("registerAlias: bad request: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n := len(args); n != 1 {
|
|
|
|
return nil, fmt.Errorf("registerAlias: expected two arguments got %d", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
// get the user from the muxrpc connection
|
|
|
|
userID, err := network.GetFeedRefFromAddr(req.RemoteAddr())
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
alias, err := h.db.Resolve(ctx, args[0])
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if !alias.Feed.Equal(userID) {
|
|
|
|
return nil, fmt.Errorf("revokeAlias: not your alias (moderators need to use the web dashboard of the room")
|
|
|
|
}
|
|
|
|
|
|
|
|
err = h.db.Revoke(ctx, alias.Name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, nil
|
|
|
|
}
|
2022-08-19 19:47:33 +00:00
|
|
|
|
|
|
|
func (h Handler) List(ctx context.Context, req *muxrpc.Request) (interface{}, error) {
|
|
|
|
var args []string
|
|
|
|
|
|
|
|
err := json.Unmarshal(req.RawArgs, &args)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("listAlias: bad request: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n := len(args); n != 1 {
|
|
|
|
return nil, fmt.Errorf("listAlias: expected one argument got %d", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
ref, err := refs.ParseFeedRef(args[0])
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("listAlias: invalid feed ref: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
allAliases, err := h.db.List(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("listAlias: could not list aliases: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var filteredAliases []roomdb.Alias
|
|
|
|
for _, alias := range allAliases {
|
|
|
|
if alias.Feed.Equal(ref) {
|
|
|
|
filteredAliases = append(filteredAliases, alias)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return aliasesToListOfAliasStrings(filteredAliases), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func aliasesToListOfAliasStrings(aliases []roomdb.Alias) []string {
|
|
|
|
result := make([]string, 0)
|
|
|
|
for _, alias := range aliases {
|
|
|
|
result = append(result, alias.Name)
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|