implement bridge between muxrcp and http
This commit is contained in:
parent
afa6bee285
commit
396961e5e8
|
@ -19,6 +19,8 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/signinwithssb"
|
||||
|
||||
// debug
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
|
@ -203,11 +205,14 @@ func runroomsrv() error {
|
|||
return fmt.Errorf("failed to initiate database: %w", err)
|
||||
}
|
||||
|
||||
bridge := signinwithssb.NewSignalBridge()
|
||||
|
||||
// create the shs+muxrpc server
|
||||
roomsrv, err := mksrv.New(
|
||||
db.Members,
|
||||
db.Aliases,
|
||||
db.AuthWithSSB,
|
||||
bridge,
|
||||
httpsDomain,
|
||||
opts...)
|
||||
if err != nil {
|
||||
|
@ -250,6 +255,7 @@ func runroomsrv() error {
|
|||
},
|
||||
roomsrv.StateManager,
|
||||
roomsrv.Network,
|
||||
bridge,
|
||||
handlers.Databases{
|
||||
Aliases: db.Aliases,
|
||||
AuthFallback: db.AuthFallback,
|
||||
|
@ -286,7 +292,8 @@ func runroomsrv() error {
|
|||
STSIncludeSubdomains: false,
|
||||
|
||||
// See for more https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
|
||||
ContentSecurityPolicy: "default-src 'self'", // enforce no external content
|
||||
// helpful: https://report-uri.com/home/generate
|
||||
ContentSecurityPolicy: "default-src 'self'; img-src 'self' data:", // enforce no external content
|
||||
|
||||
BrowserXssFilter: true,
|
||||
FrameDeny: true,
|
||||
|
|
1
go.mod
1
go.mod
|
@ -20,6 +20,7 @@ require (
|
|||
github.com/pkg/errors v0.9.1
|
||||
github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351
|
||||
github.com/russross/blackfriday/v2 v2.1.0
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/unrolled/secure v1.0.8
|
||||
github.com/vcraescu/go-paginator/v2 v2.0.0
|
||||
|
|
2
go.sum
2
go.sum
|
@ -372,6 +372,8 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
|
|||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
package signinwithssb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// SignalBridge implements a way for muxrpc and http handlers to communicate about SIWSSB events
|
||||
type SignalBridge struct {
|
||||
mu *sync.Mutex
|
||||
|
||||
sessions sessionMap
|
||||
}
|
||||
|
||||
type sessionMap map[string]chan Event
|
||||
|
||||
type Event struct {
|
||||
Worked bool
|
||||
Token string
|
||||
}
|
||||
|
||||
// NewSignalBridge returns a new SignalBridge
|
||||
func NewSignalBridge() *SignalBridge {
|
||||
return &SignalBridge{
|
||||
mu: new(sync.Mutex),
|
||||
sessions: make(sessionMap),
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterSession registers a new session on the bridge.
|
||||
// It returns a channel from which future events can be read
|
||||
// and the server challenge, which acts as the session key.
|
||||
func (sb *SignalBridge) RegisterSession() string {
|
||||
sb.mu.Lock()
|
||||
defer sb.mu.Unlock()
|
||||
|
||||
c := GenerateChallenge()
|
||||
_, used := sb.sessions[c]
|
||||
if used {
|
||||
for used { // generate new challanges until we have an un-used one
|
||||
c = GenerateChallenge()
|
||||
_, used = sb.sessions[c]
|
||||
}
|
||||
}
|
||||
|
||||
evtCh := make(chan Event)
|
||||
sb.sessions[c] = evtCh
|
||||
|
||||
go func() { // make sure the session doesn't go stale and collect dust (ie unused memory)
|
||||
time.Sleep(10 * time.Minute)
|
||||
sb.mu.Lock()
|
||||
defer sb.mu.Unlock()
|
||||
delete(sb.sessions, c)
|
||||
}()
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (sb *SignalBridge) GetEventChannel(sc string) (<-chan Event, bool) {
|
||||
sb.mu.Lock()
|
||||
defer sb.mu.Unlock()
|
||||
ch, has := sb.sessions[sc]
|
||||
return ch, has
|
||||
}
|
||||
|
||||
// CompleteSession uses the passed challange to send on and close the open channel.
|
||||
// It will return an error if the session doesn't exist.
|
||||
func (sb *SignalBridge) CompleteSession(sc string, success bool, token string) error {
|
||||
sb.mu.Lock()
|
||||
defer sb.mu.Unlock()
|
||||
|
||||
ch, ok := sb.sessions[sc]
|
||||
if !ok {
|
||||
return fmt.Errorf("no such session")
|
||||
}
|
||||
|
||||
ch <- Event{
|
||||
Worked: success,
|
||||
Token: token,
|
||||
}
|
||||
close(ch)
|
||||
|
||||
// remove session
|
||||
delete(sb.sessions, sc)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package signinwithssb
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBridge(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
|
||||
sb := NewSignalBridge()
|
||||
|
||||
// try to use a non-existant session
|
||||
err := sb.CompleteSession("nope", false)
|
||||
a.Error(err)
|
||||
|
||||
// make a new session
|
||||
updates, sc := sb.RegisterSession()
|
||||
|
||||
b, err := DecodeChallengeString(sc)
|
||||
a.NoError(err)
|
||||
a.Len(b, challengeLength)
|
||||
|
||||
go func() {
|
||||
err := sb.CompleteSession(sc, true)
|
||||
a.NoError(err)
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second / 4)
|
||||
|
||||
select {
|
||||
case evt := <-updates:
|
||||
a.True(evt.Worked)
|
||||
default:
|
||||
t.Error("no updates")
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import (
|
|||
"go.cryptoscope.co/muxrpc/v2"
|
||||
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/network"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/signinwithssb"
|
||||
validate "github.com/ssb-ngi-pointer/go-ssb-room/internal/signinwithssb"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/roomdb"
|
||||
refs "go.mindeco.de/ssb-refs"
|
||||
|
@ -23,6 +24,8 @@ type Handler struct {
|
|||
sessions roomdb.AuthWithSSBService
|
||||
members roomdb.MembersService
|
||||
|
||||
bridge *signinwithssb.SignalBridge
|
||||
|
||||
roomDomain string // the http(s) domain of the room to signal redirect addresses
|
||||
}
|
||||
|
||||
|
@ -30,9 +33,11 @@ type Handler struct {
|
|||
func New(
|
||||
log kitlog.Logger,
|
||||
self refs.FeedRef,
|
||||
sessiondb roomdb.AuthWithSSBService,
|
||||
roomDomain string,
|
||||
membersdb roomdb.MembersService,
|
||||
roomDomain string) Handler {
|
||||
sessiondb roomdb.AuthWithSSBService,
|
||||
bridge *signinwithssb.SignalBridge,
|
||||
) Handler {
|
||||
|
||||
var h Handler
|
||||
h.self = self
|
||||
|
@ -40,6 +45,7 @@ func New(
|
|||
h.logger = log
|
||||
h.sessions = sessiondb
|
||||
h.members = membersdb
|
||||
h.bridge = bridge
|
||||
|
||||
return h
|
||||
}
|
||||
|
@ -50,6 +56,11 @@ func (h Handler) SendSolution(ctx context.Context, req *muxrpc.Request) (interfa
|
|||
return nil, err
|
||||
}
|
||||
|
||||
member, err := h.members.GetByFeed(ctx, *clientID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("client is not a room member")
|
||||
}
|
||||
|
||||
var params []string
|
||||
if err := json.Unmarshal(req.RawArgs, ¶ms); err != nil {
|
||||
return nil, err
|
||||
|
@ -67,18 +78,22 @@ func (h Handler) SendSolution(ctx context.Context, req *muxrpc.Request) (interfa
|
|||
|
||||
sig, err := base64.StdEncoding.DecodeString(params[2])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("sc is not valid base64 data: %w", err)
|
||||
h.bridge.CompleteSession(sol.ServerChallenge, false, "")
|
||||
return nil, fmt.Errorf("signature is not valid base64 data: %w", err)
|
||||
}
|
||||
|
||||
if !sol.Validate(sig) {
|
||||
h.bridge.CompleteSession(sol.ServerChallenge, false, "")
|
||||
return nil, fmt.Errorf("not a valid solution")
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// h.challenges.Solved(sc)
|
||||
// return true, nil
|
||||
tok, err := h.sessions.CreateToken(ctx, member.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("TODO: update SSE")
|
||||
h.bridge.CompleteSession(sol.ServerChallenge, true, tok)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (h Handler) InvalidateAllSolutions(ctx context.Context, req *muxrpc.Request) (interface{}, error) {
|
||||
|
|
|
@ -5,7 +5,6 @@ package roomsrv
|
|||
import (
|
||||
kitlog "github.com/go-kit/kit/log"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/muxrpc/handlers/signinwithssb"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/roomdb"
|
||||
muxrpc "go.cryptoscope.co/muxrpc/v2"
|
||||
"go.cryptoscope.co/muxrpc/v2/typemux"
|
||||
|
||||
|
@ -15,7 +14,7 @@ import (
|
|||
)
|
||||
|
||||
// instantiate and register the muxrpc handlers
|
||||
func (s *Server) initHandlers(aliasDB roomdb.AliasesService) {
|
||||
func (s *Server) initHandlers() {
|
||||
// inistaniate handler packages
|
||||
whoami := whoami.New(s.Whoami())
|
||||
|
||||
|
@ -28,16 +27,17 @@ func (s *Server) initHandlers(aliasDB roomdb.AliasesService) {
|
|||
aliasHandler := alias.New(
|
||||
kitlog.With(s.logger, "unit", "aliases"),
|
||||
s.Whoami(),
|
||||
aliasDB,
|
||||
s.Aliases,
|
||||
s.domain,
|
||||
)
|
||||
|
||||
siwssbHandler := signinwithssb.New(
|
||||
kitlog.With(s.logger, "unit", "auth-with-ssb"),
|
||||
s.Whoami(),
|
||||
s.authWithSSB,
|
||||
s.Members,
|
||||
s.domain,
|
||||
s.Members,
|
||||
s.authWithSSB,
|
||||
s.authWithSSBBridge,
|
||||
)
|
||||
|
||||
// register muxrpc commands
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/maybemod/multicloser"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/network"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/repo"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/signinwithssb"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/roomdb"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/roomstate"
|
||||
refs "go.mindeco.de/ssb-refs"
|
||||
|
@ -68,6 +69,7 @@ type Server struct {
|
|||
Aliases roomdb.AliasesService
|
||||
|
||||
authWithSSB roomdb.AuthWithSSBService
|
||||
authWithSSBBridge *signinwithssb.SignalBridge
|
||||
}
|
||||
|
||||
func (s Server) Whoami() refs.FeedRef {
|
||||
|
@ -78,6 +80,7 @@ func New(
|
|||
membersdb roomdb.MembersService,
|
||||
aliasdb roomdb.AliasesService,
|
||||
awsdb roomdb.AuthWithSSBService,
|
||||
bridge *signinwithssb.SignalBridge,
|
||||
domainName string,
|
||||
opts ...Option,
|
||||
) (*Server, error) {
|
||||
|
@ -88,6 +91,7 @@ func New(
|
|||
s.Aliases = aliasdb
|
||||
|
||||
s.authWithSSB = awsdb
|
||||
s.authWithSSBBridge = bridge
|
||||
|
||||
s.domain = domainName
|
||||
|
||||
|
@ -148,7 +152,7 @@ func New(
|
|||
|
||||
s.StateManager = roomstate.NewManager(s.rootCtx, s.logger)
|
||||
|
||||
s.initHandlers(aliasdb)
|
||||
s.initHandlers()
|
||||
|
||||
if err := s.initNetwork(); err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
let streamName = document.querySelector("#stream-name").attributes.stream.value
|
||||
// get the challange from out of the HTML
|
||||
let sc = document.querySelector("#challange").attributes.ch.value
|
||||
var evtSource = new EventSource(`/sse/events?sc=${sc}`);
|
||||
|
||||
var evtSource = new EventSource(`/sse/events?stream=${streamName}`);
|
||||
var ping = document.querySelector('#ping');
|
||||
var failed = document.querySelector('#failed');
|
||||
|
||||
var eventList = document.querySelector('#event-list');
|
||||
evtSource.onerror = (e) => {
|
||||
failed.textContent = "Warning: The connection to the server was interupted."
|
||||
}
|
||||
|
||||
evtSource.addEventListener("testing", (e) => {
|
||||
// console.log(e)
|
||||
|
||||
var newElement = document.createElement("li");
|
||||
newElement.textContent = `(${e.lastEventId}) message: ${e.data}`;
|
||||
eventList.prepend(newElement);
|
||||
evtSource.addEventListener("ping", (e) => {
|
||||
ping.textContent = e.data;
|
||||
})
|
||||
|
||||
evtSource.addEventListener("failed", (e) => {
|
||||
failed.textContent = e.data;
|
||||
})
|
||||
|
||||
evtSource.addEventListener("success", (e) => {
|
||||
console.log('trigger redirect!')
|
||||
alert(e.data)
|
||||
})
|
|
@ -5,23 +5,25 @@ package auth
|
|||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"image/color"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
kitlog "github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/log/level"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/sessions"
|
||||
|
||||
"github.com/skip2/go-qrcode"
|
||||
"go.cryptoscope.co/muxrpc/v2"
|
||||
"go.mindeco.de/http/render"
|
||||
"go.mindeco.de/logging"
|
||||
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/network"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/randutil"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/signinwithssb"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/roomdb"
|
||||
weberrors "github.com/ssb-ngi-pointer/go-ssb-room/web/errors"
|
||||
|
@ -41,8 +43,12 @@ type WithSSBHandler struct {
|
|||
cookieStore sessions.Store
|
||||
|
||||
endpoints network.Endpoints
|
||||
|
||||
bridge *signinwithssb.SignalBridge
|
||||
}
|
||||
|
||||
type registerToEventSourceMap map[string]<-chan signinwithssb.Event
|
||||
|
||||
func NewWithSSBHandler(
|
||||
m *mux.Router,
|
||||
r *render.Renderer,
|
||||
|
@ -52,6 +58,7 @@ func NewWithSSBHandler(
|
|||
membersDB roomdb.MembersService,
|
||||
sessiondb roomdb.AuthWithSSBService,
|
||||
cookies sessions.Store,
|
||||
bridge *signinwithssb.SignalBridge,
|
||||
) *WithSSBHandler {
|
||||
|
||||
var ssb WithSSBHandler
|
||||
|
@ -61,11 +68,11 @@ func NewWithSSBHandler(
|
|||
ssb.endpoints = endpoints
|
||||
ssb.sessiondb = sessiondb
|
||||
ssb.cookieStore = cookies
|
||||
ssb.bridge = bridge
|
||||
|
||||
m.Get(router.AuthWithSSBSignIn).HandlerFunc(r.HTML("auth/withssb_sign_in.tmpl", ssb.login))
|
||||
|
||||
m.HandleFunc("/sse/login/{sc}", r.HTML("auth/withssb_server_start.tmpl", ssb.startWithServer))
|
||||
|
||||
m.HandleFunc("/sse/events", ssb.eventSource)
|
||||
|
||||
return &ssb
|
||||
|
@ -267,48 +274,41 @@ func (h WithSSBHandler) Logout(w http.ResponseWriter, r *http.Request) {
|
|||
// server-sent-events stuff
|
||||
|
||||
func (h WithSSBHandler) startWithServer(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
logger := logging.FromContext(req.Context())
|
||||
sc := h.bridge.RegisterSession()
|
||||
|
||||
streamName := randutil.String(20)
|
||||
// h.events.CreateStream(streamName)
|
||||
var queryParams = make(url.Values)
|
||||
queryParams.Set("action", "start-http-auth")
|
||||
|
||||
logger = level.Debug(logger)
|
||||
logger = kitlog.With(logger, "event", streamName)
|
||||
var startAuthURI url.URL
|
||||
startAuthURI.Scheme = "ssb"
|
||||
startAuthURI.Opaque = "experimental"
|
||||
startAuthURI.RawQuery = queryParams.Encode()
|
||||
|
||||
logger.Log("event", "started stream")
|
||||
qrCode, err := qrcode.New(startAuthURI.String(), qrcode.High)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
qrCode.BackgroundColor = color.RGBA{R: 0xf9, G: 0xfa, B: 0xfb}
|
||||
qrCode.ForegroundColor = color.Black
|
||||
|
||||
// tick := time.NewTicker(5 * time.Second)
|
||||
// go func() {
|
||||
qrCodeData, err := qrCode.PNG(-8)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// var (
|
||||
// evtBuf = make([]byte, 4)
|
||||
// evtID = uint32(0)
|
||||
// )
|
||||
// for range tick.C {
|
||||
// binary.BigEndian.PutUint32(evtBuf, evtID)
|
||||
// evtID++
|
||||
// h.events.Publish(streamName, &sse.Event{
|
||||
// ID: evtBuf,
|
||||
// Data: []byte(fmt.Sprintf("boring: %d", evtID)),
|
||||
// Event: []byte("testing"),
|
||||
// })
|
||||
// logger.Log("event", "sent", "id", evtID)
|
||||
// }
|
||||
// }()
|
||||
|
||||
// go func() {
|
||||
// time.Sleep(1 * time.Minute)
|
||||
// tick.Stop()
|
||||
// logger.Log("event", "stopped")
|
||||
// }()
|
||||
qrURI := "data:image/png;base64," + base64.StdEncoding.EncodeToString(qrCodeData)
|
||||
|
||||
return struct {
|
||||
StreamName string
|
||||
}{streamName}, nil
|
||||
SSBURI template.URL
|
||||
QRCodeURI template.URL
|
||||
ServerChallenge string
|
||||
}{template.URL(startAuthURI.String()), template.URL(qrURI), sc}, nil
|
||||
}
|
||||
|
||||
type event struct {
|
||||
ID, Data, Event []byte
|
||||
ID uint32
|
||||
Data string
|
||||
Event string
|
||||
}
|
||||
|
||||
func (h WithSSBHandler) eventSource(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -317,37 +317,40 @@ func (h WithSSBHandler) eventSource(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
notifier, ok := w.(http.CloseNotifier)
|
||||
if !ok {
|
||||
http.Error(w, "cant notify about closed requests", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// setup server-sent events
|
||||
// https://html.spec.whatwg.org/multipage/server-sent-events.html
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
w.Header().Set("Cache-Control", "no-cache")
|
||||
w.Header().Set("Connection", "keep-alive")
|
||||
w.Header().Set("Transfer-Encoding", "chunked")
|
||||
|
||||
// Get the StreamID from the URL
|
||||
streamID := r.URL.Query().Get("stream")
|
||||
if streamID == "" {
|
||||
http.Error(w, "Please specify a stream!", http.StatusInternalServerError)
|
||||
sc := r.URL.Query().Get("sc")
|
||||
if sc == "" {
|
||||
http.Error(w, "Please specify a stream!", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
logger := logging.FromContext(r.Context())
|
||||
logger = level.Debug(logger)
|
||||
logger = kitlog.With(logger, "stream", streamID)
|
||||
|
||||
logger = kitlog.With(logger, "stream", sc)
|
||||
logger.Log("event", "stream opened")
|
||||
|
||||
// TODO: load map with channel
|
||||
evtCh, has := h.bridge.GetEventChannel(sc)
|
||||
if !has {
|
||||
http.Error(w, "No such session!", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// tick := time.NewTicker(time.Second / 4)
|
||||
tick := time.NewTicker(time.Second)
|
||||
notify := w.(http.CloseNotifier).CloseNotify()
|
||||
tick := time.NewTicker(3 * time.Second)
|
||||
go func() {
|
||||
<-notify
|
||||
tick.Stop()
|
||||
logger.Log("event", "request closed")
|
||||
}()
|
||||
|
||||
go func() {
|
||||
time.Sleep(5 * time.Minute)
|
||||
time.Sleep(3 * time.Minute)
|
||||
tick.Stop()
|
||||
logger.Log("event", "stopped")
|
||||
}()
|
||||
|
@ -357,32 +360,52 @@ func (h WithSSBHandler) eventSource(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// Push events to client
|
||||
var (
|
||||
evtBuf = make([]byte, 4)
|
||||
evtID = uint32(0)
|
||||
evt event
|
||||
)
|
||||
|
||||
for range tick.C {
|
||||
binary.BigEndian.PutUint32(evtBuf, evtID)
|
||||
evtID++
|
||||
notify := notifier.CloseNotify()
|
||||
for {
|
||||
select {
|
||||
|
||||
evt = event{
|
||||
ID: []byte(fmt.Sprintf("%d", evtID)),
|
||||
Data: []byte(fmt.Sprintf("age: %s", time.Since(start))),
|
||||
Event: []byte("testing"),
|
||||
case <-notify:
|
||||
logger.Log("event", "request closed")
|
||||
return
|
||||
|
||||
case <-tick.C:
|
||||
msg := fmt.Sprintf("Waiting for solution (session age: %s)", time.Since(start))
|
||||
sendServerEvent(w, event{
|
||||
ID: evtID,
|
||||
Data: msg,
|
||||
Event: "ping",
|
||||
})
|
||||
logger.Log("event", "sent", "ping", evtID)
|
||||
|
||||
case update := <-evtCh:
|
||||
evt := event{
|
||||
ID: evtID,
|
||||
Data: "challange validation failed",
|
||||
Event: "failed",
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "id: %s\n", evt.ID)
|
||||
if update.Worked {
|
||||
evt.Event = "success"
|
||||
evt.Data = update.Token
|
||||
}
|
||||
|
||||
sendServerEvent(w, evt)
|
||||
|
||||
logger.Log("event", "sent", "worked", update.Worked)
|
||||
}
|
||||
evtID++
|
||||
flusher.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
func sendServerEvent(w io.Writer, evt event) {
|
||||
fmt.Fprintf(w, "id: %d\n", evt.ID)
|
||||
fmt.Fprintf(w, "data: %s\n", evt.Data)
|
||||
if len(evt.Event) > 0 {
|
||||
fmt.Fprintf(w, "event: %s\n", evt.Event)
|
||||
}
|
||||
// if len(evt.Retry) > 0 {
|
||||
// fmt.Fprintf(w, "retry: %s\n", evt.Retry)
|
||||
// }
|
||||
fmt.Fprint(w, "\n")
|
||||
flusher.Flush()
|
||||
|
||||
logger.Log("event", "sent", "id", evtID)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/network"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/repo"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/signinwithssb"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/roomdb"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/roomstate"
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/web"
|
||||
|
@ -71,6 +72,7 @@ func New(
|
|||
netInfo NetworkInfo,
|
||||
roomState *roomstate.Manager,
|
||||
roomEndpoints network.Endpoints,
|
||||
bridge *signinwithssb.SignalBridge,
|
||||
dbs Databases,
|
||||
) (http.Handler, error) {
|
||||
m := router.CompleteApp()
|
||||
|
@ -237,6 +239,7 @@ func New(
|
|||
dbs.Members,
|
||||
dbs.AuthWithSSB,
|
||||
cookieStore,
|
||||
bridge,
|
||||
)
|
||||
|
||||
// just hooks up the router to the handler
|
||||
|
|
|
@ -25,7 +25,7 @@ func AuthenticateFromContext(r *render.Renderer) Middleware {
|
|||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
if FromContext(req.Context()) == nil {
|
||||
r.Error(w, req, http.StatusUnauthorized, weberrors.ErrBadRequest{})
|
||||
r.Error(w, req, http.StatusUnauthorized, weberrors.ErrNotAuthorized)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, req)
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
<h1 id="welcome" class="text-lg">{{i18n "AuthWithSSBWelcome"}}</h1>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Template Data</h3>
|
||||
<pre>{{.}}</pre>
|
||||
<h3>TODO: qr code of the code</h3>
|
||||
<img src="{{.QRCodeURI}}" alt="QR-Code to pass challange to an App" />
|
||||
<pre>{{.SSBURI}}</pre>
|
||||
|
||||
<h3>Server events</h3>
|
||||
<ul id="event-list"></ul>
|
||||
<p id="ping"></p>
|
||||
<p id="failed" class="text-red-500"></p>
|
||||
</div>
|
||||
<div id="stream-name" stream="{{.StreamName}}"></div>
|
||||
<div id="challange" ch="{{.ServerChallenge}}"></div>
|
||||
<script src="/assets/events-demo.js"></script>
|
||||
{{end}}
|
Loading…
Reference in New Issue