oficina / sheets Public

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

Plain git — no account needed to clone.

Download

Download this file

1package sheets
2
3import (
4 "net/http"
5
6 "amadan.net/rastrillo/rastrillo"
7)
8
9// ContentSecurityPolicy is the policy Sheets serves under standalone.
10// It is rastrillo's default policy with one change: style-src keeps
11// 'unsafe-inline', which was rastrillo's own default until the bump to
12// fb806a2.
13//
14// The new default (style-src 'self' 'unsafe-hashes' plus pow's honeypot
15// hash) refuses every style attribute, and Sheets' documents are drawn
16// with them:
17//
18// - the scriptless table and public-link views paint each cell's fill
19// and text colour as custom properties on the cell (table.html,
20// tablepaint.go). The colours are the document's own, unbounded, so
21// they cannot be moved into sheets.css, and a per-document
22// stylesheet would be a new route and cache for every view;
23// - the Format menu's fill and text palettes draw each swatch's
24// colour the same way (sheet.html);
25// - the vendored Jspreadsheet and jsuites write style attributes of
26// their own (setAttribute("style", …) and style="…" in markup),
27// which this app does not patch: it is vendored as shipped.
28//
29// Hashing them is not possible (the values are per document), and the
30// other directives are unchanged, so scripts stay same-origin only and
31// framing, base and form targets stay locked. Home mode serves
32// connect.FormPolicy, which carries the same style-src.
33// TestProductionCSPIsTheDefaultBarStyles keeps every other directive in
34// step with rastrillo's default.
35const ContentSecurityPolicy = "default-src 'self'; style-src 'self' 'unsafe-inline'; " +
36 "img-src 'self' data:; frame-ancestors 'none'; base-uri 'self'; form-action 'self'"
37
38// ServeOptions completes opts with what Sheets serves: its router, its
39// error page and its CSP. main passes the result to rastrillo.Serve,
40// and the CSP tests pass it to rastrillo.Handler, so the policy they
41// check is the one production runs under.
42func (a *App) ServeOptions(opts rastrillo.Options) rastrillo.Options {
43 // rastrillo.Options.Mux wants a *http.ServeMux; the app's own
44 // router is a chi.Router (an http.Handler), so it mounts under one.
45 mux := http.NewServeMux()
46 mux.Handle("/", a.Router())
47 opts.Mux = mux
48 // A panic outside the router's signed-in group (where the app's own
49 // recoverer renders the viewer's chrome) is the same error page, not
50 // rastrillo's plain text (spec §3.3).
51 opts.ErrorPage = a.ErrorPage
52 opts.CSP = ContentSecurityPolicy
53 return opts
54}
55