summaryrefslogtreecommitdiff
path: root/internal/middleware
diff options
context:
space:
mode:
authorLibravatar tobi <tobi.smethurst@protonmail.com>2025-05-22 12:34:39 +0200
committerLibravatar kim <gruf@noreply.codeberg.org>2025-05-22 12:34:39 +0200
commit00e58c60cd59882199a7e378416a279de2b5212d (patch)
treec2846ea546174498ed5b4ad68ac9a0039749a9c2 /internal/middleware
parent[chore] Upgrade to Go 1.24 (#4187) (diff)
downloadgotosocial-00e58c60cd59882199a7e378416a279de2b5212d.tar.xz
[feature] Add ListenBrainz functionality on the web view (#4184)
This pull request adds a very simple ad-hoc ListenBrainz widget to the frontend web view, with progressive enhancement (in all fail states it just falls back to rendering the field as normal). This necessitated adding the ListenBrainz API endpoint to the `connect-src` part of our Content-Security-Policy header. We might want to tweak this to only add that endpoint to `connect-src` for profiles, and then only for profiles that include a ListenBrainz field, but this would require significant dicking about with the middleware, and checks inside the app logic, such that it might not be worthwhile (after all, we control all the scripts right now anyway). Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4184 Co-authored-by: tobi <tobi.smethurst@protonmail.com> Co-committed-by: tobi <tobi.smethurst@protonmail.com>
Diffstat (limited to 'internal/middleware')
-rw-r--r--internal/middleware/contentsecuritypolicy.go16
-rw-r--r--internal/middleware/contentsecuritypolicy_test.go12
2 files changed, 20 insertions, 8 deletions
diff --git a/internal/middleware/contentsecuritypolicy.go b/internal/middleware/contentsecuritypolicy.go
index fb35c3a08..eb5168376 100644
--- a/internal/middleware/contentsecuritypolicy.go
+++ b/internal/middleware/contentsecuritypolicy.go
@@ -37,6 +37,7 @@ func ContentSecurityPolicy(extraURIs ...string) gin.HandlerFunc {
func BuildContentSecurityPolicy(extraURIs ...string) string {
const (
defaultSrc = "default-src"
+ connectSrc = "connect-src"
objectSrc = "object-src"
imgSrc = "img-src"
mediaSrc = "media-src"
@@ -48,7 +49,7 @@ func BuildContentSecurityPolicy(extraURIs ...string) string {
)
// CSP values keyed by directive.
- values := make(map[string][]string, 4)
+ values := make(map[string][]string, 5)
/*
default-src
@@ -70,6 +71,16 @@ func BuildContentSecurityPolicy(extraURIs ...string) string {
}
/*
+ connect-src
+ https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/connect-src
+ */
+
+ // Restrictive default policy, but
+ // include ListenBrainz API for fields.
+ const listenBrains = "https://api.listenbrainz.org/1/user/"
+ values[connectSrc] = append(values[defaultSrc], listenBrains) //nolint
+
+ /*
object-src
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/object-src
*/
@@ -118,9 +129,10 @@ func BuildContentSecurityPolicy(extraURIs ...string) string {
// Iterate through an ordered slice rather than
// iterating through the map, since we want these
// policyDirectives in a determinate order.
- policyDirectives := make([]string, 4)
+ policyDirectives := make([]string, 5)
for i, directive := range []string{
defaultSrc,
+ connectSrc,
objectSrc,
imgSrc,
mediaSrc,
diff --git a/internal/middleware/contentsecuritypolicy_test.go b/internal/middleware/contentsecuritypolicy_test.go
index a337763df..ef6dc2bf8 100644
--- a/internal/middleware/contentsecuritypolicy_test.go
+++ b/internal/middleware/contentsecuritypolicy_test.go
@@ -32,38 +32,38 @@ func TestBuildContentSecurityPolicy(t *testing.T) {
for _, test := range []cspTest{
{
extraURLs: nil,
- expected: "default-src 'self'; object-src 'none'; img-src 'self' blob:; media-src 'self'",
+ expected: "default-src 'self'; connect-src 'self' https://api.listenbrainz.org/1/user/; object-src 'none'; img-src 'self' blob:; media-src 'self'",
},
{
extraURLs: []string{
"https://some-bucket-provider.com",
},
- expected: "default-src 'self'; object-src 'none'; img-src 'self' blob: https://some-bucket-provider.com; media-src 'self' https://some-bucket-provider.com",
+ expected: "default-src 'self'; connect-src 'self' https://api.listenbrainz.org/1/user/; object-src 'none'; img-src 'self' blob: https://some-bucket-provider.com; media-src 'self' https://some-bucket-provider.com",
},
{
extraURLs: []string{
"https://some-bucket-provider.com:6969",
},
- expected: "default-src 'self'; object-src 'none'; img-src 'self' blob: https://some-bucket-provider.com:6969; media-src 'self' https://some-bucket-provider.com:6969",
+ expected: "default-src 'self'; connect-src 'self' https://api.listenbrainz.org/1/user/; object-src 'none'; img-src 'self' blob: https://some-bucket-provider.com:6969; media-src 'self' https://some-bucket-provider.com:6969",
},
{
extraURLs: []string{
"http://some-bucket-provider.com:6969",
},
- expected: "default-src 'self'; object-src 'none'; img-src 'self' blob: http://some-bucket-provider.com:6969; media-src 'self' http://some-bucket-provider.com:6969",
+ expected: "default-src 'self'; connect-src 'self' https://api.listenbrainz.org/1/user/; object-src 'none'; img-src 'self' blob: http://some-bucket-provider.com:6969; media-src 'self' http://some-bucket-provider.com:6969",
},
{
extraURLs: []string{
"https://s3.nl-ams.scw.cloud",
},
- expected: "default-src 'self'; object-src 'none'; img-src 'self' blob: https://s3.nl-ams.scw.cloud; media-src 'self' https://s3.nl-ams.scw.cloud",
+ expected: "default-src 'self'; connect-src 'self' https://api.listenbrainz.org/1/user/; object-src 'none'; img-src 'self' blob: https://s3.nl-ams.scw.cloud; media-src 'self' https://s3.nl-ams.scw.cloud",
},
{
extraURLs: []string{
"https://s3.nl-ams.scw.cloud",
"https://s3.somewhere.else.example.org",
},
- expected: "default-src 'self'; object-src 'none'; img-src 'self' blob: https://s3.nl-ams.scw.cloud https://s3.somewhere.else.example.org; media-src 'self' https://s3.nl-ams.scw.cloud https://s3.somewhere.else.example.org",
+ expected: "default-src 'self'; connect-src 'self' https://api.listenbrainz.org/1/user/; object-src 'none'; img-src 'self' blob: https://s3.nl-ams.scw.cloud https://s3.somewhere.else.example.org; media-src 'self' https://s3.nl-ams.scw.cloud https://s3.somewhere.else.example.org",
},
} {
csp := middleware.BuildContentSecurityPolicy(test.extraURLs...)