Add CSP and rework speak.js

This commit is contained in:
Jan-Lukas Else 2021-02-16 21:27:52 +01:00
parent 99789efcd3
commit 58f41085dd
4 changed files with 50 additions and 47 deletions

View File

@ -23,16 +23,17 @@ type config struct {
}
type configServer struct {
Logging bool `mapstructure:"logging"`
LogFile string `mapstructure:"logFile"`
Debug bool `mapstructure:"Debug"`
Port int `mapstructure:"port"`
PublicAddress string `mapstructure:"publicAddress"`
ShortPublicAddress string `mapstructure:"shortPublicAddress"`
PublicHTTPS bool `mapstructure:"publicHttps"`
SecurityHeaders bool `mapstructure:"securityHeaders"`
LetsEncryptMail string `mapstructure:"letsEncryptMail"`
JWTSecret string `mapstructure:"jwtSecret"`
Logging bool `mapstructure:"logging"`
LogFile string `mapstructure:"logFile"`
Debug bool `mapstructure:"Debug"`
Port int `mapstructure:"port"`
PublicAddress string `mapstructure:"publicAddress"`
ShortPublicAddress string `mapstructure:"shortPublicAddress"`
PublicHTTPS bool `mapstructure:"publicHttps"`
SecurityHeaders bool `mapstructure:"securityHeaders"`
CSPDomains []string `mapstructure:"cspDomains"`
LetsEncryptMail string `mapstructure:"letsEncryptMail"`
JWTSecret string `mapstructure:"jwtSecret"`
publicHostname string
shortPublicHostname string
}

13
http.go
View File

@ -4,7 +4,9 @@ import (
"compress/flate"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"sync/atomic"
"github.com/caddyserver/certmagic"
@ -388,13 +390,22 @@ func buildHandler() (http.Handler, error) {
}
func securityHeaders(next http.Handler) http.Handler {
extraCSPDomains := ""
if mp := appConfig.Micropub.MediaStorage; mp != nil && mp.MediaURL != "" {
if u, err := url.Parse(mp.MediaURL); err == nil {
extraCSPDomains += " " + u.Hostname()
}
}
if len(appConfig.Server.CSPDomains) > 0 {
extraCSPDomains += " " + strings.Join(appConfig.Server.CSPDomains, " ")
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Strict-Transport-Security", "max-age=31536000;")
w.Header().Add("Referrer-Policy", "no-referrer")
w.Header().Add("X-Content-Type-Options", "nosniff")
w.Header().Add("X-Frame-Options", "SAMEORIGIN")
w.Header().Add("X-Xss-Protection", "1; mode=block")
// TODO: Add CSP
w.Header().Add("Content-Security-Policy", "default-src 'self'"+extraCSPDomains)
next.ServeHTTP(w, r)
})
}

View File

@ -1,45 +1,37 @@
"use strict";
function getVoice() {
if (window.speechSynthesis) {
return window.speechSynthesis.getVoices().filter(voice => voice.lang.startsWith(document.querySelector('html').lang))[0];
}
return false;
let sb = document.getElementById('speakBtn')
let s = window.speechSynthesis
function gv() {
return s ? s.getVoices().filter(voice => voice.lang.startsWith(document.querySelector('html').lang))[0] : false
}
function initSpeak() {
if (window.speechSynthesis) {
let speakBtn = document.querySelector('#speakBtn');
speakBtn.style.display = '';
speakBtn.onclick = function() { speak() };
speakBtn.textContent = speakText;
function is() {
if (s) {
sb.classList.remove('hide')
sb.onclick = sp
sb.textContent = sb.dataset.speak
}
}
function speak() {
console.log("Start speaking")
let speakBtn = document.querySelector('#speakBtn');
speakBtn.onclick = function() { stopSpeak() };
speakBtn.textContent = stopSpeakText;
let textContent =
((document.querySelector('article .p-name')) ? document.querySelector('article .p-name').innerText + "\n\n" : "")
+ document.querySelector('article .e-content').innerText;
let utterThis = new SpeechSynthesisUtterance(textContent);
utterThis.voice = getVoice();
utterThis.onerror = stopSpeak;
utterThis.onend = stopSpeak;
window.speechSynthesis.speak(utterThis);
function sp() {
sb.onclick = ssp
sb.textContent = sb.dataset.stopspeak
let ut = new SpeechSynthesisUtterance(
((document.querySelector('article .p-name')) ? document.querySelector('article .p-name').innerText + "\n\n" : '') + document.querySelector('article .e-content').innerText
)
ut.voice = gv()
ut.onerror = ssp
ut.onend = ssp
s.speak(ut)
}
function stopSpeak() {
console.log("Stop speaking")
window.speechSynthesis.cancel();
let speakBtn = document.querySelector('#speakBtn');
speakBtn.onclick = function() { speak() };
speakBtn.textContent = speakText;
function ssp() {
s.cancel()
sb.onclick = sp
sb.textContent = sb.dataset.speak
}
window.onbeforeunload = function () {
stopSpeak();
}
initSpeak();
window.onbeforeunload = ssp
is()

View File

@ -1,8 +1,7 @@
{{ define "postactions" }}
<div class="p flex" id="post-actions">
<a href="https://www.addtoany.com/share#url={{ absolute .Data.Path }}{{ with title .Data }}&title={{ . }}{{ end }}" target="_blank" rel="nofollow noopener noreferrer" class="button invert">{{ string .Blog.Lang "share" }}</a>&nbsp;
<button id="speakBtn" class="invert" style="display: none;"></button>
<script>const speakText = "{{ string .Blog.Lang "speak" }}";const stopSpeakText = "{{ string .Blog.Lang "stopspeak" }}";</script>
<button id="speakBtn" class="button invert hide" data-speak="{{ string .Blog.Lang "speak" }}" data-stopspeak="{{ string .Blog.Lang "stopspeak" }}"></button>
<script defer src="{{ asset "js/speak.js" }}"></script>
</div>
{{ end }}