oficina / home Public

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

Plain git — no account needed to clone.

Download

Download this file

1package home
2
3import (
4 "net/http"
5 "net/http/httptest"
6 "strings"
7 "testing"
8)
9
10func TestNativeAppChoicesKeepTeamAndAppBoundaries(t *testing.T) {
11 for _, app := range []string{"docs", "sheets", "slides", "calendar", "calls", "memoria"} {
12 t.Run(app, func(t *testing.T) {
13 f := newMountedChooser(t)
14 cookie := f.session(t, chooserPerson)
15 path := "/apps/" + app
16 if w := f.request("GET", path, "", "", nil); w.Code != 303 || !strings.Contains(w.Header().Get("Location"), "return_to=%2Fapps%2F"+app) {
17 t.Fatal("lost app after sign-in", w.Code, w.Header())
18 }
19 empty := f.request("GET", path, "", "", cookie)
20 if empty.Code != 200 || !strings.Contains(empty.Body.String(), "No teams available") {
21 t.Fatal("empty", empty.Code)
22 }
23 a := f.team(t, "A1", "alpha", "Alpha", chooserPerson)
24 b := f.team(t, "B2", "beta", "Beta", chooserPerson)
25 c := f.team(t, "C3", "foreign", "Hidden other team", chooserOther)
26 if app != "docs" {
27 for _, row := range []struct {
28 id int64
29 label string
30 }{{a, "alpha"}, {b, "beta"}, {c, "foreign"}} {
31 _, err := f.p.directory.db.Writer().Exec(`INSERT INTO team_instances VALUES(?,?,?,?,?)`, row.id, app, "https://"+row.label+"."+app+".oficina.works", row.label+"-"+app, "live")
32 if err != nil {
33 t.Fatal(err)
34 }
35 }
36 }
37 w := f.request("GET", path, "", "", cookie)
38 if w.Code != 200 || !strings.Contains(w.Body.String(), `action="`+path+`/team"`) || strings.Contains(w.Body.String(), "Hidden other team") {
39 t.Fatal("choice boundaries", w.Code, w.Body.String())
40 }
41 picked := f.request("POST", path+"/team", directoryOrigin, "team=A1", cookie)
42 assertContinuationPage(t, picked, "https://alpha."+app+".oficina.works/")
43 if _, err := f.p.directory.db.Writer().Exec(`DELETE FROM memberships WHERE team_id=? AND person_ref=?`, a, chooserPerson); err != nil {
44 t.Fatal(err)
45 }
46 if w := f.request("POST", path+"/team", directoryOrigin, "team=A1", cookie); w.Code != 404 {
47 t.Fatal("stale team selection accepted", w.Code)
48 }
49 single := f.request("GET", path, "", "", cookie)
50 if single.Code != 303 || single.Header().Get("Location") != "https://beta."+app+".oficina.works/" {
51 t.Fatal("one-team shortcut", single.Code, single.Header())
52 }
53 if w := f.request("POST", path+"/team", "https://attacker.example", "team=B2", cookie); w.Code != 403 {
54 t.Fatal("CSRF", w.Code)
55 }
56 if w := f.request("GET", path+"?return_to=https://attacker.example", "", "", cookie); w.Code != 404 {
57 t.Fatal("untrusted navigation", w.Code)
58 }
59 r := httptest.NewRequest("GET", directoryOrigin+path, nil)
60 r.AddCookie(cookie)
61 r.AddCookie(cookie)
62 dup := httptest.NewRecorder()
63 f.handler.ServeHTTP(dup, r)
64 if dup.Code != http.StatusBadRequest {
65 t.Fatal("duplicate cookie", dup.Code)
66 }
67 wrongApp := "mail"
68 if _, err := f.p.directory.db.Writer().Exec(`UPDATE team_instances SET origin=? WHERE team_id=? AND app=?`, "https://beta."+wrongApp+".oficina.works", b, app); err != nil {
69 t.Fatal(err)
70 }
71 if w := f.request("GET", path, "", "", cookie); w.Code != 503 || w.Header().Get("Location") != "" {
72 t.Fatal("wrong-app origin accepted", w.Code)
73 }
74 })
75 }
76}
77
78func TestProviderAndUnknownAppsDoNotBecomeTeamConsumers(t *testing.T) {
79 f := newMountedChooser(t)
80 for _, app := range []string{"mail", "files", "unknown", "Docs"} {
81 if _, err := f.p.directory.newAppChooser(f.store, app); err == nil {
82 t.Fatal("unintegrated app accepted", app)
83 }
84 if w := f.request("GET", "/apps/"+app, "", "", f.session(t, chooserPerson)); w.Code != 404 {
85 t.Fatal("unintegrated route", app, w.Code)
86 }
87 }
88}
89