| 1 | package calendar |
| 2 | |
| 3 | import ( |
| 4 | "amadan.net/rastrillo/rastrillo" |
| 5 | ) |
| 6 | |
| 7 | // ContentSecurityPolicy is the policy Calendar serves standalone. It is |
| 8 | // rastrillo's default policy with one change: style-src keeps |
| 9 | // 'unsafe-inline', which was rastrillo's own default until the bump to |
| 10 | // fb806a2. |
| 11 | // |
| 12 | // The new default (style-src 'self' 'unsafe-hashes' plus pow's honeypot |
| 13 | // hash) refuses every style attribute, and Calendar draws its time with |
| 14 | // them: |
| 15 | // |
| 16 | // - the day and week grids place each event by its start and length |
| 17 | // (top, height, and the packer's left and width, in percent of the |
| 18 | // day: day.html, week.html, pack.go), and each half-hour slot link |
| 19 | // the same way. They are per event and continuous, so they cannot |
| 20 | // be classes in calendar.css; without them every chip and slot |
| 21 | // collapses to the top of its column; |
| 22 | // - every chip, and each calendar's swatch on the Calendars page, |
| 23 | // carries its calendar's hue as --cal-hue (_chip.html, |
| 24 | // calendars.html). The hue is per calendar (personalHue), and |
| 25 | // calendar.css mixes every colour from it. |
| 26 | // |
| 27 | // Hashing them is not possible (the values are per event), and the other |
| 28 | // directives are unchanged, so scripts stay same-origin only and framing, |
| 29 | // base and form targets stay locked. The constant layout that used to be |
| 30 | // style attributes is in calendar.css now. Home mode serves |
| 31 | // connect.FormPolicy, which carries the same style-src. |
| 32 | // TestProductionCSPIsTheDefaultBarStyles keeps every other directive in |
| 33 | // step with rastrillo's default. |
| 34 | const ContentSecurityPolicy = "default-src 'self'; style-src 'self' 'unsafe-inline'; " + |
| 35 | "img-src 'self' data:; frame-ancestors 'none'; base-uri 'self'; form-action 'self'" |
| 36 | |
| 37 | // ServeOptions completes opts with what Calendar serves: its router, its |
| 38 | // error page and its CSP. main passes the result to rastrillo.Serve, and |
| 39 | // the CSP tests pass it to rastrillo.Handler, so the policy they check is |
| 40 | // the one production runs under. |
| 41 | func (a *App) ServeOptions(opts rastrillo.Options) rastrillo.Options { |
| 42 | opts.Mux = a.Handler() |
| 43 | // The same page a handler's own error path renders, so a panic and |
| 44 | // a handled failure look identical to whoever hits one. |
| 45 | opts.ErrorPage = ErrorPage |
| 46 | opts.CSP = ContentSecurityPolicy |
| 47 | return opts |
| 48 | } |
| 49 | |