package office import ( "encoding/json" "os" "strings" "testing" "git.novox.be/novox/mesh-sdk/go/catalogue" ) // 1830/AC1 (unit: manifest check) // Given the catalogue, when only-office's manifest is parsed, then it offers document-server with // credential own jwt, jwt says taken at-start, and serves document-server on port 9070 with a // public-root. func TestManifestOffersDocumentServer(t *testing.T) { raw, err := os.ReadFile("module.json") if err != nil { t.Fatalf("reading module.json: %v", err) } m, err := catalogue.ParseManifest(raw) if err != nil { t.Fatalf("parsing module.json: %v", err) } var offer *catalogue.Offer for i := range m.Provides { if m.Provides[i].Name == "document-server" { offer = &m.Provides[i] break } } if offer == nil { t.Fatal("manifest does not provide document-server") } if offer.Scope != catalogue.ScopeMesh { t.Errorf("document-server scope = %q, want %q", offer.Scope, catalogue.ScopeMesh) } if offer.Credential == nil || offer.Credential.Own != "jwt" { t.Errorf("document-server credential = %+v, want own jwt", offer.Credential) } own, ok := m.OwnSecrets["jwt"] if !ok { t.Fatal("manifest declares no own-secret jwt") } if own.Taken != catalogue.TakenAtStart { t.Errorf("own-secrets.jwt.taken = %q, want %q", own.Taken, catalogue.TakenAtStart) } serve, ok := m.Serves["document-server"] if !ok { t.Fatal("manifest serves no document-server") } if scheme, _ := serve["scheme"].(string); scheme != "http" { t.Errorf("serves.document-server.scheme = %q, want http", scheme) } if port, _ := serve["port"].(float64); port != 9070 { t.Errorf("serves.document-server.port = %v, want 9070", serve["port"]) } if root, _ := serve["public-root"].(string); root != "https://${bound:route:name}/" { t.Errorf("serves.document-server.public-root = %q, want https://${bound:route:name}/", root) } } // 1837/AC1 (unit: manifest check) // Given the catalogue, when only-office's manifest and its server.env template are read, then the // document server's secure-link secret is an own secret taken at start, and server.env hands it to // the container as SECURE_LINK_SECRET, so its document service and its nginx sign and check // Editor.bin links with one value across every restart. func TestSecureLinkSecretIsPinned(t *testing.T) { raw, err := os.ReadFile("module.json") if err != nil { t.Fatalf("reading module.json: %v", err) } m, err := catalogue.ParseManifest(raw) if err != nil { t.Fatalf("parsing module.json: %v", err) } own, ok := m.OwnSecrets["secure-link"] if !ok { t.Fatal("manifest declares no own-secret secure-link") } if own.Taken != catalogue.TakenAtStart { t.Errorf("own-secrets.secure-link.taken = %q, want %q", own.Taken, catalogue.TakenAtStart) } env, err := os.ReadFile("files/server.env") if err != nil { t.Fatalf("reading files/server.env: %v", err) } if !strings.Contains(string(env), "\nSECURE_LINK_SECRET=${secret:secure-link}\n") { t.Errorf("files/server.env does not set SECURE_LINK_SECRET=${secret:secure-link}:\n%s", env) } } // 1837/AC3 (unit: manifest check) // Given the catalogue, when only-office's manifest is read, then the lib directory (mounted at // /var/lib/onlyoffice, where the document service writes the converted files nginx serves) lets // other users pass through it (mode 0711): the image makes it the document service's own, and nginx // runs as another user, so a mode of 0700 makes nginx answer 403 "Permission denied" on Editor.bin. func TestLibDirectoryLetsNginxThrough(t *testing.T) { raw, err := os.ReadFile("module.json") if err != nil { t.Fatalf("reading module.json: %v", err) } var m struct { Resources []struct { ID string `json:"id"` Type string `json:"type"` Mode string `json:"mode"` } `json:"resources"` } if err := json.Unmarshal(raw, &m); err != nil { t.Fatalf("parsing module.json: %v", err) } for _, r := range m.Resources { if r.ID == "lib" && r.Type == "directory" { if r.Mode != "0711" { t.Errorf("lib directory mode = %q, want 0711 so nginx can reach the document service's cache", r.Mode) } return } } t.Fatal("manifest declares no lib directory") }