fix link generation for alias registration

fixes #160
This commit is contained in:
Henry 2021-04-19 14:52:12 +02:00
parent a78c039cc7
commit 52ec94e878
15 changed files with 118 additions and 64 deletions

View File

@ -50,6 +50,8 @@ var (
httpsDomain string
aliasesAsSubdomains bool
listenAddrDebug string
logToFile string
repoDir string
@ -114,6 +116,8 @@ func initFlags() {
return nil
})
flag.BoolVar(&aliasesAsSubdomains, "aliases-as-subdomains", true, "needs to be disabled if a wildcard certificate for the room is not available. (stub until we have the admin/settings page)")
flag.Parse()
if logToFile != "" {
@ -153,7 +157,7 @@ func runroomsrv() error {
return fmt.Errorf("invalid muxrpc listener: %w", err)
}
portMUXRPC, err := net.LookupPort("tcp", muxrpcPortStr)
_, err = net.LookupPort("tcp", muxrpcPortStr)
if err != nil {
return fmt.Errorf("invalid tcp port for muxrpc listener: %w", err)
}
@ -180,7 +184,6 @@ func runroomsrv() error {
roomsrv.WithLogger(log),
roomsrv.WithAppKey(ak),
roomsrv.WithRepoPath(repoDir),
roomsrv.WithListenAddr(listenAddrShsMux),
roomsrv.WithUNIXSocket(!flagDisableUNIXSock),
}
@ -214,6 +217,23 @@ func runroomsrv() error {
r := repo.New(repoDir)
keyPair, err := repo.DefaultKeyPair(r)
checkAndLog(err)
opts = append(opts, roomsrv.WithKeyPair(keyPair))
networkInfo := network.ServerEndpointDetails{
Development: development,
Domain: httpsDomain,
PortHTTPS: uint(portHTTP),
RoomID: keyPair.Feed,
ListenAddressMUXRPC: listenAddrShsMux,
UseSubdomainForAliases: aliasesAsSubdomains,
}
// open the sqlite version of the roomdb
db, err := sqlite.Open(r)
if err != nil {
@ -234,7 +254,7 @@ func runroomsrv() error {
db.AuthWithSSB,
bridge,
db.Config,
httpsDomain,
networkInfo,
opts...)
if err != nil {
return fmt.Errorf("failed to instantiate ssb server: %w", err)
@ -268,14 +288,7 @@ func runroomsrv() error {
webHandler, err := handlers.New(
kitlog.With(log, "package", "web"),
repo.New(repoDir),
network.ServerEndpointDetails{
Domain: httpsDomain,
PortHTTPS: uint(portHTTP),
PortMUXRPC: uint(portMUXRPC),
RoomID: roomsrv.Whoami(),
Development: development,
},
networkInfo,
roomsrv.StateManager,
roomsrv.Network,
bridge,

View File

@ -10,6 +10,7 @@ import (
"io"
"net"
"net/http"
"net/url"
"time"
"go.cryptoscope.co/muxrpc/v2"
@ -21,21 +22,52 @@ import (
// ServerEndpointDetails encapsulates the endpoint information.
// Like domain name of the room, it's ssb/secret-handshake public key and the HTTP and MUXRPC TCP ports.
type ServerEndpointDetails struct {
PortMUXRPC uint
PortHTTPS uint // 0 assumes default (443)
RoomID refs.FeedRef
Domain string
ListenAddressMUXRPC string // defaults to ":8008"
// Domain sets the DNS name for all the HTTP(S) URLs.
Domain string
PortHTTPS uint // 0 assumes default (443)
// UseSubdomainForAliases controls wether urls for alias resolving
// are generated as https://$alias.$domain instead of https://$domain/alias/$alias
UseSubdomainForAliases bool
// Development instructs url building to happen with http and include the http port
Development bool
}
func (sed ServerEndpointDetails) URLForAlias(a string) string {
var u url.URL
if sed.Development {
u.Path = "/alias/" + a
u.Scheme = "http"
u.Host = fmt.Sprintf("localhost:%d", sed.PortHTTPS)
return u.String()
}
u.Scheme = "https"
if sed.UseSubdomainForAliases {
u.Host = a + "." + sed.Domain
} else {
u.Path = "/alias/" + a
}
return u.String()
}
// MultiserverAddress returns net:domain:muxport~shs:roomPubKeyInBase64
// ie: the room servers https://github.com/ssbc/multiserver-address
func (sed ServerEndpointDetails) MultiserverAddress() string {
addr, err := net.ResolveTCPAddr("tcp", sed.ListenAddressMUXRPC)
if err != nil {
panic(err)
}
var roomPubKey = base64.StdEncoding.EncodeToString(sed.RoomID.PubKey())
return fmt.Sprintf("net:%s:%d~shs:%s", sed.Domain, sed.PortMUXRPC, roomPubKey)
return fmt.Sprintf("net:%s:%d~shs:%s", sed.Domain, addr.Port, roomPubKey)
}
// EndpointStat gives some information about a connected peer

View File

@ -15,7 +15,7 @@ func TestMultiserverAddress(t *testing.T) {
var sed ServerEndpointDetails
sed.Domain = "the.ho.st"
sed.PortMUXRPC = 8008
sed.ListenAddressMUXRPC = ":8008"
sed.RoomID = refs.FeedRef{
ID: bytes.Repeat([]byte("ohai"), 8),

View File

@ -27,15 +27,17 @@ type Handler struct {
db roomdb.AliasesService
roomDomain string // the http(s) domain of the room to signal alias addresses
netInfo network.ServerEndpointDetails
// roomDomain string // the http(s) domain of the room to signal alias addresses
}
// New returns a fresh alias muxrpc handler
func New(log kitlog.Logger, self refs.FeedRef, aliasesDB roomdb.AliasesService, roomDomain string) Handler {
func New(log kitlog.Logger, self refs.FeedRef, aliasesDB roomdb.AliasesService, netInfo network.ServerEndpointDetails) Handler {
var h Handler
h.self = self
h.roomDomain = roomDomain
h.netInfo = netInfo
h.logger = log
h.db = aliasesDB
@ -100,14 +102,7 @@ func (h Handler) Register(ctx context.Context, req *muxrpc.Request) (interface{}
return nil, fmt.Errorf("registerAlias: could not register alias: %w", err)
}
resolveURL, err := httpRouter.Get(router.CompleteAliasResolve).URL("alias", confirmation.Alias)
if err != nil {
return nil, err
}
resolveURL.Host = h.roomDomain
resolveURL.Scheme = "https"
return resolveURL.String(), nil
return h.netInfo.URLForAlias(confirmation.Alias), nil
}
// Revoke checks that the alias is from that user before revoking the alias from the database.

View File

@ -79,7 +79,6 @@ func makeNamedTestBot(t testing.TB, name string, opts []roomsrv.Option) (roomdb.
botOptions := append(opts,
roomsrv.WithLogger(log.With(mainLog, "bot", name)),
roomsrv.WithRepoPath(testPath),
roomsrv.WithListenAddr(":0"),
roomsrv.WithNetworkConnTracker(network.NewLastWinsTracker()),
roomsrv.WithPostSecureConnWrapper(func(conn net.Conn) (net.Conn, error) {
return debug.WrapDump(filepath.Join(testPath, "muxdump"), conn)
@ -98,8 +97,14 @@ func makeNamedTestBot(t testing.TB, name string, opts []roomsrv.Option) (roomdb.
err = db.Config.SetPrivacyMode(context.TODO(), roomdb.ModeRestricted)
r.NoError(err)
netInfo := network.ServerEndpointDetails{
Domain: name,
ListenAddressMUXRPC: ":0",
}
sb := signinwithssb.NewSignalBridge()
theBot, err := roomsrv.New(db.Members, db.DeniedKeys, db.Aliases, db.AuthWithSSB, sb, db.Config, name, botOptions...)
theBot, err := roomsrv.New(db.Members, db.DeniedKeys, db.Aliases, db.AuthWithSSB, sb, db.Config, netInfo, botOptions...)
r.NoError(err)
return db.Members, theBot
}

View File

@ -96,10 +96,15 @@ func (ts *testSession) startGoServer(
) *roomsrv.Server {
r := require.New(ts.t)
netInfo := network.ServerEndpointDetails{
Domain: "go.test.room.server",
ListenAddressMUXRPC: "localhost:0",
}
// prepend defaults
opts = append([]roomsrv.Option{
roomsrv.WithLogger(ts.info),
roomsrv.WithListenAddr("localhost:0"),
roomsrv.WithRepoPath(ts.repo),
roomsrv.WithContext(ts.ctx),
}, opts...)
@ -126,7 +131,7 @@ func (ts *testSession) startGoServer(
fakeConfig := new(mockdb.FakeRoomConfig)
deniedKeysDB := new(mockdb.FakeDeniedKeysService)
srv, err := roomsrv.New(membersDB, deniedKeysDB, aliasDB, authSessionsDB, sb, fakeConfig, "go.test.room.server", opts...)
srv, err := roomsrv.New(membersDB, deniedKeysDB, aliasDB, authSessionsDB, sb, fakeConfig, netInfo, opts...)
r.NoError(err, "failed to init tees a server")
ts.t.Logf("go server: %s", srv.Whoami().Ref())
ts.t.Cleanup(func() {

View File

@ -31,13 +31,13 @@ func (s *Server) initHandlers() {
kitlog.With(s.logger, "unit", "aliases"),
s.Whoami(),
s.Aliases,
s.domain,
s.netInfo,
)
siwssbHandler := signinwithssb.New(
kitlog.With(s.logger, "unit", "auth-with-ssb"),
s.Whoami(),
s.domain,
s.netInfo.Domain,
s.Members,
s.authWithSSB,
s.authWithSSBBridge,

View File

@ -5,7 +5,6 @@ package roomsrv
import (
"context"
"fmt"
"net"
"strings"
kitlog "github.com/go-kit/kit/log"
@ -108,18 +107,6 @@ func WithNetworkConnTracker(ct network.ConnTracker) Option {
}
}
// WithListenAddr changes the muxrpc listener address. By default it listens to ':8008'.
func WithListenAddr(addr string) Option {
return func(s *Server) error {
var err error
s.listenAddr, err = net.ResolveTCPAddr("tcp", addr)
if err != nil {
return fmt.Errorf("failed to parse tcp listen addr: %w", err)
}
return nil
}
}
// WithPreSecureConnWrapper wrapps the connection after it is encrypted.
// Usefull for debugging and measuring traffic.
func WithPreSecureConnWrapper(cw netwrap.ConnWrapper) Option {

View File

@ -46,7 +46,7 @@ type Server struct {
wsAddr string
dialer netwrap.Dialer
domain string // the DNS domain name of the room
netInfo network.ServerEndpointDetails
loadUnixSock bool
@ -85,7 +85,7 @@ func New(
awsdb roomdb.AuthWithSSBService,
bridge *signinwithssb.SignalBridge,
config roomdb.RoomConfig,
domainName string,
netInfo network.ServerEndpointDetails,
opts ...Option,
) (*Server, error) {
var s Server
@ -99,7 +99,7 @@ func New(
s.authWithSSB = awsdb
s.authWithSSBBridge = bridge
s.domain = domainName
s.netInfo = netInfo
for i, opt := range opts {
err := opt(&s)
@ -129,8 +129,10 @@ func New(
s.dialer = netwrap.Dial
}
if s.listenAddr == nil {
s.listenAddr = &net.TCPAddr{Port: network.DefaultPort}
var err error
s.listenAddr, err = net.ResolveTCPAddr("tcp", s.netInfo.ListenAddressMUXRPC)
if err != nil {
return nil, err
}
if s.logger == nil {
@ -152,7 +154,7 @@ func New(
var err error
s.keyPair, err = repo.DefaultKeyPair(s.repo)
if err != nil {
return nil, fmt.Errorf("sbot: failed to get keypair: %w", err)
return nil, fmt.Errorf("roomsrv: failed to get keypair: %w", err)
}
}

View File

@ -118,6 +118,7 @@ func Handler(
r: r,
flashes: fh,
urlTo: urlTo,
netInfo: netInfo,
db: dbs.Members,
}

View File

@ -5,24 +5,27 @@ package admin
import (
"errors"
"fmt"
"html/template"
"net/http"
"strconv"
"go.mindeco.de/http/render"
refs "go.mindeco.de/ssb-refs"
"github.com/gorilla/csrf"
"go.mindeco.de/http/render"
"github.com/ssb-ngi-pointer/go-ssb-room/internal/network"
"github.com/ssb-ngi-pointer/go-ssb-room/roomdb"
"github.com/ssb-ngi-pointer/go-ssb-room/web"
weberrors "github.com/ssb-ngi-pointer/go-ssb-room/web/errors"
"github.com/ssb-ngi-pointer/go-ssb-room/web/members"
"github.com/ssb-ngi-pointer/go-ssb-room/web/router"
refs "go.mindeco.de/ssb-refs"
)
type membersHandler struct {
r *render.Renderer
flashes *weberrors.FlashHelper
urlTo web.URLMaker
netInfo network.ServerEndpointDetails
db roomdb.MembersService
}
@ -149,9 +152,15 @@ func (h membersHandler) details(rw http.ResponseWriter, req *http.Request) (inte
roles := []roomdb.Role{roomdb.RoleMember, roomdb.RoleModerator, roomdb.RoleAdmin}
aliasURLs := make(map[string]template.URL)
for _, a := range member.Aliases {
aliasURLs[a.Name] = template.URL(h.netInfo.URLForAlias(a.Name))
}
return map[string]interface{}{
"Member": member,
"AllRoles": roles,
"AliasURLs": aliasURLs,
csrf.TemplateTag: csrf.TemplateField(req),
}, nil
}

View File

@ -2,6 +2,7 @@ package admin
import (
"bytes"
"fmt"
"net/http"
"net/url"
"testing"
@ -192,8 +193,9 @@ func TestMemberDetails(t *testing.T) {
// check for link to resolve 1st Alias
aliasRobertLink, yes := aliasList.Eq(0).Attr("href")
a.True(yes, "a-tag has href attribute")
// TODO: fix wildcard domain
a.Equal("/alias/robert", aliasRobertLink)
wantURL := fmt.Sprintf("https://robert.%s", ts.netInfo.Domain)
a.Equal(wantURL, aliasRobertLink)
// check for link to revoke 1st Alias
revokeRobertLink, yes := aliasList.Eq(1).Attr("href")
@ -204,8 +206,8 @@ func TestMemberDetails(t *testing.T) {
// check for link to resolve 1st Alias
aliasBobLink, yes := aliasList.Eq(2).Attr("href")
a.True(yes, "a-tag has href attribute")
// TODO: fix wildcard domain
a.Equal("/alias/bob", aliasBobLink)
wantURL = fmt.Sprintf("https://bob.%s", ts.netInfo.Domain)
a.Equal(wantURL, aliasBobLink)
// check for link to revoke 1st Alias
revokeBobLink, yes := aliasList.Eq(3).Attr("href")

View File

@ -77,6 +77,8 @@ func newSession(t *testing.T) *testSession {
ts.netInfo = network.ServerEndpointDetails{
Domain: randutil.String(10),
RoomID: refs.FeedRef{Algo: "ed25519", ID: bytes.Repeat([]byte{0}, 32)},
UseSubdomainForAliases: true,
}
// instantiate the urlTo helper (constructs urls for us!)

View File

@ -83,9 +83,10 @@ func setup(t *testing.T) *testSession {
ts.MockedEndpoints = new(mocked.FakeEndpoints)
ts.NetworkInfo = network.ServerEndpointDetails{
Domain: "localhost",
PortMUXRPC: 8008,
PortHTTPS: 443,
Domain: "localhost",
PortHTTPS: 443,
ListenAddressMUXRPC: ":8008",
RoomID: refs.FeedRef{
ID: bytes.Repeat([]byte("test"), 8),

View File

@ -54,7 +54,7 @@
{{range .Member.Aliases}}
<div class="flex flex-row items-center justify-start">
<a
href="/alias/{{.Name}}"
href="{{index $.AliasURLs .Name }}"
class="underline text-purple-800 bg-purple-100 rounded-lg px-2 py-1"
>{{.Name}}</a>
</div>