oficina / docs Public

Clone
git clone https://amadan.net/oficina/docs

Plain git — no account needed to clone.

Download

Download this file

1package docs
2
3import (
4 "bufio"
5 "io"
6 "net/http"
7 "net/http/httptest"
8 "testing"
9 "time"
10)
11
12func TestNativeStreamStopsAfterSessionRevocation(t *testing.T) {
13 app, err := NewForTest(t)
14 if err != nil {
15 t.Fatal(err)
16 }
17 authenticated := app.TestRequest(t, "stream@example.com", "GET", "/", nil)
18 assertNativeStreamRevoked(t, app, "stream@example.com", authenticated)
19}
20
21func TestNativeHomeStreamStopsAfterSessionRevocation(t *testing.T) {
22 f := newRouterHomeFixture(t)
23 browser := f.browser()
24 browser.localSignin(t, "alice@example.com")
25 assertNativeStreamRevoked(t, f.app, "alice@example.com", browser.request("GET", "/", ""))
26}
27
28func assertNativeStreamRevoked(t *testing.T, app *App, address string, authenticated *http.Request) {
29 t.Helper()
30 owner := app.TestPerson(t, address)
31 doc, err := app.Store().Create(t.Context(), owner, "Live fixture")
32 if err != nil {
33 t.Fatal(err)
34 }
35 streamDurations(t, app, 20*time.Millisecond, time.Second)
36 server := httptest.NewServer(app.Handler())
37 defer server.Close()
38 req, _ := http.NewRequest("GET", server.URL+"/d/"+doc.Sqid+"/stream", nil)
39 req.Host = authenticated.Host
40 for _, cookie := range authenticated.Cookies() {
41 req.AddCookie(cookie)
42 }
43 client := server.Client()
44 client.CheckRedirect = func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse }
45 response, err := client.Do(req)
46 if err != nil {
47 t.Fatal(err)
48 }
49 defer response.Body.Close()
50 if response.StatusCode != http.StatusOK || response.Header.Get("Content-Type") != "text/event-stream" {
51 t.Fatalf("stream did not open: status=%d location=%q", response.StatusCode, response.Header.Get("Location"))
52 }
53 reader := bufio.NewReader(response.Body)
54 if name, _ := nextEvent(t, reader, time.Second); name != "update" {
55 t.Fatalf("no initial event: %s", name)
56 }
57 signout := httptest.NewRequest("POST", "/signout", nil)
58 signout.Host = authenticated.Host
59 signout.Header.Set("Sec-Fetch-Site", "same-origin")
60 for _, cookie := range authenticated.Cookies() {
61 signout.AddCookie(cookie)
62 }
63 signedOut := httptest.NewRecorder()
64 app.Handler().ServeHTTP(signedOut, signout)
65 // 303 to /signed-out standalone; 307 on to the issuer's /signout in
66 // Home mode (homeRoutes.signout). Both have ended the Docs session.
67 if signedOut.Code != http.StatusSeeOther && signedOut.Code != http.StatusTemporaryRedirect {
68 t.Fatalf("signout failed: %d", signedOut.Code)
69 }
70 closed := make(chan error, 1)
71 go func() { _, err := io.Copy(io.Discard, reader); closed <- err }()
72 select {
73 case err := <-closed:
74 if err != nil {
75 t.Fatalf("stream failed instead of clean revocation: %v", err)
76 }
77 case <-time.After(300 * time.Millisecond):
78 t.Fatal("revoked session retains stream until TTL")
79 }
80}
81