diff --git a/Dockerfile b/Dockerfile index d63a58d..773a640 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ ADD hlsjs/ /app/hlsjs/ ADD dbmigrations/ /app/dbmigrations/ ADD strings/ /app/strings/ ADD plugins/ /app/plugins/ -ADD logo/GoBlog.png /app/logo/GoBlog.png +ADD logo/ /app/logo/ FROM buildbase AS build diff --git a/captcha.go b/captcha.go index eb831f2..6d01fc9 100644 --- a/captcha.go +++ b/captcha.go @@ -121,10 +121,6 @@ func (a *goBlog) checkCaptcha(w http.ResponseWriter, r *http.Request) bool { } // Check if session contains a captchaId and if captcha is solved if sesCaptchaId, ok := ses.Values["captchaid"]; ok && captcha.VerifyString(sesCaptchaId.(string), r.FormValue("digits")) { - if err != nil { - a.serveError(w, r, err.Error(), http.StatusInternalServerError) - return true - } ses.Values["captcha"] = true err = a.captchaSessions.Save(r, w, ses) if err != nil { diff --git a/config.go b/config.go index 898a61c..21a8f66 100644 --- a/config.go +++ b/config.go @@ -205,14 +205,15 @@ type configAnnouncement struct { } type configUser struct { - Nick string `mapstructure:"nick"` - Name string `mapstructure:"name"` - Password string `mapstructure:"password"` - TOTP string `mapstructure:"totp"` - AppPasswords []*configAppPassword `mapstructure:"appPasswords"` - Email string `mapstructure:"email"` - Link string `mapstructure:"link"` - Identities []string `mapstructure:"identities"` + Nick string `mapstructure:"nick"` + Name string `mapstructure:"name"` + Password string `mapstructure:"password"` + TOTP string `mapstructure:"totp"` + AppPasswords []*configAppPassword `mapstructure:"appPasswords"` + Email string `mapstructure:"email"` + Link string `mapstructure:"link"` + Identities []string `mapstructure:"identities"` + ProfileImageFile string `mapstructure:"profileImageFile"` } type configAppPassword struct { @@ -463,6 +464,10 @@ func (a *goBlog) initConfig(logging bool) error { b.Comments = &configComments{Enabled: false} } } + // Check if path for profile image is set + if a.cfg.User.ProfileImageFile == "" { + return errors.New("no file for profile image configured") + } // Check if sections already migrated to db const sectionMigrationKey = "sections_migrated" if val, err := a.getSettingValue(sectionMigrationKey); err != nil { @@ -580,8 +585,9 @@ func createDefaultConfig() *config { Expiration: 600, }, User: &configUser{ - Nick: "admin", - Password: "secret", + Nick: "admin", + Password: "secret", + ProfileImageFile: "data/profileImage", }, Hooks: &configHooks{ Shell: "/bin/bash", diff --git a/config_test.go b/config_test.go index 78b2b7d..4ac3876 100644 --- a/config_test.go +++ b/config_test.go @@ -10,7 +10,9 @@ import ( func createDefaultTestConfig(t *testing.T) *config { c := createDefaultConfig() - c.Db.File = filepath.Join(t.TempDir(), "blog.db") + dir := t.TempDir() + c.Db.File = filepath.Join(dir, "blog.db") + c.User.ProfileImageFile = filepath.Join(dir, "profileImage") return c } diff --git a/go.mod b/go.mod index 8f85fa8..01a89ad 100644 --- a/go.mod +++ b/go.mod @@ -20,9 +20,9 @@ require ( github.com/dmulholl/mp3lib v1.0.0 github.com/elnormous/contenttype v1.0.4 github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 - github.com/emersion/go-smtp v0.21.0 - github.com/go-ap/activitypub v0.0.0-20240327073638-93645bda3b18 - github.com/go-ap/client v0.0.0-20240327112549-6abf62c47e46 + github.com/emersion/go-smtp v0.21.1 + github.com/go-ap/activitypub v0.0.0-20240408091739-ba76b44c2594 + github.com/go-ap/client v0.0.0-20240408093509-f0721baa55c2 github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 github.com/go-chi/chi/v5 v5.0.12 github.com/go-fed/httpsig v1.1.0 @@ -35,7 +35,7 @@ require ( github.com/jlelse/feeds v1.3.0 github.com/justinas/alice v1.2.0 github.com/kaorimatz/go-opml v0.0.0-20210201121027-bc8e2852d7f9 - github.com/klauspost/compress v1.17.7 + github.com/klauspost/compress v1.17.8 github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible github.com/lopezator/migrator v0.3.1 github.com/mattn/go-sqlite3 v1.14.22 @@ -53,6 +53,7 @@ require ( github.com/spf13/viper v1.18.2 github.com/stretchr/testify v1.9.0 github.com/tdewolff/minify/v2 v2.20.19 + github.com/tiptophelmet/cspolicy v0.1.1 github.com/tkrajina/gpxgo v1.3.1 github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 github.com/traefik/yaegi v0.16.1 @@ -60,15 +61,15 @@ require ( github.com/xhit/go-simple-mail/v2 v2.16.0 github.com/yuin/goldmark v1.7.1 github.com/yuin/goldmark-emoji v1.0.2 - go.hacdias.com/indielib v0.2.3 - golang.org/x/crypto v0.21.0 - golang.org/x/net v0.23.0 - golang.org/x/sync v0.6.0 + go.hacdias.com/indielib v0.3.0 + golang.org/x/crypto v0.22.0 + golang.org/x/net v0.24.0 + golang.org/x/sync v0.7.0 golang.org/x/text v0.14.0 gopkg.in/yaml.v3 v3.0.1 - maunium.net/go/mautrix v0.18.0 - nhooyr.io/websocket v1.8.10 - willnorris.com/go/microformats v1.2.0 + maunium.net/go/mautrix v0.18.1 + nhooyr.io/websocket v1.8.11 + willnorris.com/go/microformats v1.2.1-0.20240301064101-b5d1b9d2120e ) require ( @@ -77,15 +78,14 @@ require ( github.com/andybalholm/cascadia v1.3.2 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/boombuler/barcode v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dlclark/regexp2 v1.11.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-ap/errors v0.0.0-20240304112515-6077fa9c17b0 // indirect - github.com/golang/glog v1.2.0 // indirect - github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/glog v1.2.1 // indirect github.com/gorilla/css v1.0.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -101,7 +101,7 @@ require ( github.com/mmcdole/goxpp v1.1.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rs/xid v1.5.0 // indirect @@ -119,14 +119,12 @@ require ( github.com/tidwall/sjson v1.2.5 // indirect github.com/toorop/go-dkim v0.0.0-20240103092955-90b7d1423f92 // indirect github.com/valyala/fastjson v1.6.4 // indirect - go.mau.fi/util v0.4.1 // indirect + go.mau.fi/util v0.4.2 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect + golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect golang.org/x/image v0.15.0 // indirect - golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sys v0.18.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/protobuf v1.33.0 // indirect + golang.org/x/oauth2 v0.19.0 // indirect + golang.org/x/sys v0.19.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect willnorris.com/go/webmention v0.0.0-20220108183051-4a23794272f0 // indirect ) diff --git a/go.sum b/go.sum index f3ae2ec..790df15 100644 --- a/go.sum +++ b/go.sum @@ -33,8 +33,8 @@ github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500/go.mod h1:S/7n9cop github.com/carlmjohnson/requests v0.23.5 h1:NPANcAofwwSuC6SIMwlgmHry2V3pLrSqRiSBKYbNHHA= github.com/carlmjohnson/requests v0.23.5/go.mod h1:zG9P28thdRnN61aD7iECFhH5iGGKX2jIjKQD9kqYH+o= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cretz/bine v0.2.1-0.20221201125941-b9d31d9c7866 h1:8Cji9JDEuYibvDQrWHvc42r9/HxjlD2kahN67LECXFk= @@ -63,18 +63,18 @@ github.com/elnormous/contenttype v1.0.4/go.mod h1:5KTOW8m1kdX1dLMiUJeN9szzR2xkng github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 h1:hH4PQfOndHDlpzYfLAAfl63E8Le6F2+EL/cdhlkyRJY= github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= -github.com/emersion/go-smtp v0.21.0 h1:ZDZmX9aFUuPlD1lpoT0nC/nozZuIkSCyQIyxdijjCy0= -github.com/emersion/go-smtp v0.21.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ= +github.com/emersion/go-smtp v0.21.1 h1:VQeZSZAKk8ueYii1yR5Zalmy7jI287eWDUqSaJ68vRM= +github.com/emersion/go-smtp v0.21.1/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/go-ap/activitypub v0.0.0-20240327073638-93645bda3b18 h1:1xZFRqYhaY1xsLds3f1h7gJJab55Uz5RD2I5wk7h3gs= -github.com/go-ap/activitypub v0.0.0-20240327073638-93645bda3b18/go.mod h1:yRUfFCoZY6C1CWalauqEQ5xYgSckzEBEO/2MBC6BOME= -github.com/go-ap/client v0.0.0-20240327112549-6abf62c47e46 h1:mcM3DqSF7ctENoY1o+7f0eOJfaqFtcOnUmCeBfAO/0Y= -github.com/go-ap/client v0.0.0-20240327112549-6abf62c47e46/go.mod h1:f8llaNe/TaORRhjtpeBy1r5xvNTEyYDbMNttaP3Uo1s= +github.com/go-ap/activitypub v0.0.0-20240408091739-ba76b44c2594 h1:er3GvGCm7bJwHostjZlsRy7uiUuCquUVF9Fe0TrwiPI= +github.com/go-ap/activitypub v0.0.0-20240408091739-ba76b44c2594/go.mod h1:yRUfFCoZY6C1CWalauqEQ5xYgSckzEBEO/2MBC6BOME= +github.com/go-ap/client v0.0.0-20240408093509-f0721baa55c2 h1:oyGq2OySpTeQb6agZ37/48xxt7PAGT4OtrRLogzK/O8= +github.com/go-ap/client v0.0.0-20240408093509-f0721baa55c2/go.mod h1:t/xYVAyfY/rwtTdUof+GWBWj32YAIWAeeP2PYH3qm8o= github.com/go-ap/errors v0.0.0-20240304112515-6077fa9c17b0 h1:H9MGShwybHLSln6K8RxHPMHiLcD86Lru+5TVW2TcXHY= github.com/go-ap/errors v0.0.0-20240304112515-6077fa9c17b0/go.mod h1:5x8a6P/dhmMGFxWLcyYlyOuJ2lRNaHGhRv+yu8BaTSI= github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 h1:GMKIYXyXPGIp+hYiWOhfqK4A023HdgisDT4YGgf99mw= @@ -91,13 +91,8 @@ github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= -github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= +github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -157,14 +152,12 @@ github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo= github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA= github.com/kaorimatz/go-opml v0.0.0-20210201121027-bc8e2852d7f9 h1:+9REu9CK9D1AQ6C/PXXwGRcoKdT04cuHR5JgGD4DKqc= github.com/kaorimatz/go-opml v0.0.0-20210201121027-bc8e2852d7f9/go.mod h1:OvY5ZBrAC9kOvM2PZs9Lw0BH+5K7tjrT6T7SFhn27OA= -github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4= @@ -203,8 +196,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/paulmach/go.geojson v1.5.0 h1:7mhpMK89SQdHFcEGomT7/LuJhwhEgfmpWYVlVmLEdQw= github.com/paulmach/go.geojson v1.5.0/go.mod h1:DgdUy2rRVDDVgKqrjMe2vZAHMfhDTrjVKt3LmHIXGbU= -github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= -github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtosvtEhg= +github.com/pelletier/go-toml/v2 v2.2.1/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -278,6 +271,8 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/tiptophelmet/cspolicy v0.1.1 h1:TiC1vWOuRcxPlY7GFIdRUpLvfTR3i5PJph66S3qsNpg= +github.com/tiptophelmet/cspolicy v0.1.1/go.mod h1:rUdvHsbJflLSqh5gSWwDuMAxXGlysQpaN5V4vYzmcUM= github.com/tkrajina/gpxgo v1.3.1 h1:b9x0OgF0YqEtLKQoWC6SeCKy4OWUWSt9uzCDPKTI2LY= github.com/tkrajina/gpxgo v1.3.1/go.mod h1:795sjVRFo5wWyN6oOZp0RYienGGBJjpAlgOz2nCngA0= github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y= @@ -300,20 +295,20 @@ github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U= github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark-emoji v1.0.2 h1:c/RgTShNgHTtc6xdz2KKI74jJr6rWi7FPgnP9GAsO5s= github.com/yuin/goldmark-emoji v1.0.2/go.mod h1:RhP/RWpexdp+KHs7ghKnifRoIs/Bq4nDS7tRbCkOwKY= -go.hacdias.com/indielib v0.2.3 h1:9bKEuR//QiyjN4EQPk1Fc4RmuOCBZviZyKgYsZd4coI= -go.hacdias.com/indielib v0.2.3/go.mod h1:zR/7VfuqHQSOmWB3S5fO5p7YQPaThnR5vYt33yMP05c= -go.mau.fi/util v0.4.1 h1:3EC9KxIXo5+h869zDGf5OOZklRd/FjeVnimTwtm3owg= -go.mau.fi/util v0.4.1/go.mod h1:GjkTEBsehYZbSh2LlE6cWEn+6ZIZTGrTMM/5DMNlmFY= +go.hacdias.com/indielib v0.3.0 h1:rbF1gnxSiFtEUQjnmqVdOzofPd5pO/3KEoa7iBIu2Is= +go.hacdias.com/indielib v0.3.0/go.mod h1:6wtl0LcTQ1JPoNld1yVy29qBEPlHeoLBKnGXYg8+dO4= +go.mau.fi/util v0.4.2 h1:RR3TOcRHmCF9Bx/3YG4S65MYfa+nV6/rn8qBWW4Mi30= +go.mau.fi/util v0.4.2/go.mod h1:PlAVfUUcPyHPrwnvjkJM9UFcPE7qGPDJqk+Oufa1Gtw= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= -golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= @@ -331,15 +326,15 @@ golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg= +golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -353,19 +348,18 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= @@ -379,10 +373,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -395,11 +385,11 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/sqlite v1.1.3/go.mod h1:AKDgRWk8lcSQSw+9kxCJnX/yySj8G3rdwYlU57cB45c= gorm.io/gorm v1.20.1/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= gorm.io/gorm v1.20.6/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= -maunium.net/go/mautrix v0.18.0 h1:sNsApeSWB8x0hLjGcdmi5JqO6Tvp2PVkiSStz+Yas6k= -maunium.net/go/mautrix v0.18.0/go.mod h1:STwJZ+6CAeiEQs7fYCkd5aC12XR5DXANE6Swy/PBKGo= -nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= -nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= -willnorris.com/go/microformats v1.2.0 h1:73pzJCLJM69kYE5qsLI9OOC/7sImNVOzya9EQ0+1wmM= -willnorris.com/go/microformats v1.2.0/go.mod h1:RrlwCSvib4qz+JICKiN7rON4phzQ3HAT7j6s4O2cZj4= +maunium.net/go/mautrix v0.18.1 h1:a6mUsJixegBNTXUoqC5RQ9gsumIPzKvCubKwF+zmCt4= +maunium.net/go/mautrix v0.18.1/go.mod h1:2oHaq792cSXFGvxLvYw3Gf1L4WVVP4KZcYys5HVk/h8= +nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0= +nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= +willnorris.com/go/microformats v1.2.1-0.20240301064101-b5d1b9d2120e h1:TRIOwo0NxN4KVSgYlYmiQktd9I96YgZ3942/JVzhwTM= +willnorris.com/go/microformats v1.2.1-0.20240301064101-b5d1b9d2120e/go.mod h1:zzo0hFA/E/nl1ZAjXiXA7KCKwCTdgBU+7HXltGgHeGA= willnorris.com/go/webmention v0.0.0-20220108183051-4a23794272f0 h1:V5+O+YZHchEwu6ZmPcqT1dQ+mHgE356Q+w9SVOQ+QZg= willnorris.com/go/webmention v0.0.0-20220108183051-4a23794272f0/go.mod h1:DgeruqKIsZtcDXVXNbBHa0YYEm88oAnK7PahkDtuCvw= diff --git a/httpMiddlewares.go b/httpMiddlewares.go index 4e9f982..0559da2 100644 --- a/httpMiddlewares.go +++ b/httpMiddlewares.go @@ -3,10 +3,12 @@ package main import ( "net/http" "net/url" - "strings" "github.com/samber/lo" - "go.goblog.app/app/pkgs/builderpool" + "github.com/tiptophelmet/cspolicy" + "github.com/tiptophelmet/cspolicy/directives" + "github.com/tiptophelmet/cspolicy/directives/constraint" + "github.com/tiptophelmet/cspolicy/src" ) func noIndexHeader(next http.Handler) http.Handler { @@ -40,27 +42,33 @@ func headAsGetHandler(next http.Handler) http.Handler { func (a *goBlog) securityHeaders(next http.Handler) http.Handler { // Build CSP domains list - cspBuilder := builderpool.Get() + allowedDomains := []string{} if mp := a.cfg.Micropub.MediaStorage; mp != nil && mp.MediaURL != "" { if u, err := url.Parse(mp.MediaURL); err == nil { - cspBuilder.WriteString(" ") - cspBuilder.WriteString(u.Hostname()) + allowedDomains = append(allowedDomains, u.Hostname()) } } - if len(a.cfg.Server.CSPDomains) > 0 { - cspBuilder.WriteString(" ") - cspBuilder.WriteString(strings.Join(a.cfg.Server.CSPDomains, " ")) + allowedDomains = append(allowedDomains, a.cfg.Server.CSPDomains...) + defaultSrcList := []src.SourceVal{src.Self(), src.Scheme("blob:")} + for _, d := range allowedDomains { + defaultSrcList = append(defaultSrcList, src.Host(d)) } - cspDomains := cspBuilder.String() - csp := "default-src 'self' blob:" + cspDomains + "; img-src 'self'" + cspDomains + " data:; frame-ancestors 'none';" - builderpool.Put(cspBuilder) + imgSrcList := []src.SourceVal{src.Self(), src.Scheme("data:")} + for _, d := range allowedDomains { + imgSrcList = append(imgSrcList, src.Host(d)) + } + fac := &constraint.FrameAncestorsConstraint{} + fac.Sources(src.None()) + csp := cspolicy.Build( + directives.DefaultSrc(defaultSrcList...), + directives.ImgSrc(imgSrcList...), + directives.FrameAncestors(fac), + ) // Return handler return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Strict-Transport-Security", "max-age=31536000;") w.Header().Set("Referrer-Policy", "no-referrer") w.Header().Set("X-Content-Type-Options", "nosniff") - w.Header().Set("X-Frame-Options", "DENY") - w.Header().Set("X-Xss-Protection", "1; mode=block") w.Header().Set("Content-Security-Policy", csp) next.ServeHTTP(w, r) }) diff --git a/indieAuthServer_test.go b/indieAuthServer_test.go index 07a062f..3eee69c 100644 --- a/indieAuthServer_test.go +++ b/indieAuthServer_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "net/http" "net/http/httptest" "net/url" @@ -54,7 +55,7 @@ func Test_indieAuthServer(t *testing.T) { ) require.NotNil(t, iac) - metadata, err := iac.DiscoverMetadata("https://example.org/") + metadata, err := iac.DiscoverMetadata(context.Background(), "https://example.org/") require.NoError(t, err) if assert.NotNil(t, metadata) { assert.Equal(t, "https://example.org/indieauth", metadata.AuthorizationEndpoint) @@ -63,7 +64,7 @@ func Test_indieAuthServer(t *testing.T) { for _, test := range []int{1, 2} { - authinfo, redirect, err := iac.Authenticate("https://example.org/", "create") + authinfo, redirect, err := iac.Authenticate(context.Background(), "https://example.org/", "create") require.NoError(t, err) assert.NotNil(t, authinfo) assert.NotEmpty(t, redirect) @@ -120,14 +121,14 @@ func Test_indieAuthServer(t *testing.T) { if test == 1 { - profile, err := iac.FetchProfile(authinfo, code) + profile, err := iac.FetchProfile(context.Background(), authinfo, code) require.NoError(t, err) assert.NotNil(t, profile) assert.Equal(t, "https://example.org/", profile.Me) } else if test == 2 { - token, _, err := iac.GetToken(authinfo, code) + token, _, err := iac.GetToken(context.Background(), authinfo, code) require.NoError(t, err) assert.NotNil(t, token) assert.NotEqual(t, "", token.AccessToken) diff --git a/profileImage.go b/profileImage.go index 93482e7..2280afd 100644 --- a/profileImage.go +++ b/profileImage.go @@ -32,7 +32,6 @@ const ( profileImagePathJPEG = profileImagePath + "." + string(profileImageFormatJPEG) profileImagePathPNG = profileImagePath + "." + string(profileImageFormatPNG) profileImageSizeRegexPattern = `(?P\d+)(x(?P\d+))?` - profileImageFile = "data/profileImage" profileImageNoImageHash = "x" @@ -93,7 +92,7 @@ func (a *goBlog) serveProfileImage(format profileImageFormat) http.HandlerFunc { var imageReader io.ReadCloser if a.hasProfileImage() { var err error - imageReader, err = os.Open(profileImageFile) + imageReader, err = os.Open(a.cfg.User.ProfileImageFile) if err != nil { a.serveError(w, r, "Failed to open image file", http.StatusInternalServerError) return @@ -146,12 +145,12 @@ func (a *goBlog) profileImageHash() string { if a.profileImageHashString != "" { return nil, nil } - if _, err := os.Stat(profileImageFile); err != nil { + if _, err := os.Stat(a.cfg.User.ProfileImageFile); err != nil { a.profileImageHashString = profileImageNoImageHash return nil, nil } hash := sha256.New() - file, err := os.Open(profileImageFile) + file, err := os.Open(a.cfg.User.ProfileImageFile) if err != nil { a.profileImageHashString = profileImageNoImageHash return nil, nil @@ -183,12 +182,12 @@ func (a *goBlog) serveUpdateProfileImage(w http.ResponseWriter, r *http.Request) return } // Save the file locally - err = os.MkdirAll(filepath.Dir(profileImageFile), 0777) + err = os.MkdirAll(filepath.Dir(a.cfg.User.ProfileImageFile), 0777) if err != nil { a.serveError(w, r, "Failed to create directories", http.StatusBadRequest) return } - dataFile, err := os.OpenFile(profileImageFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) + dataFile, err := os.OpenFile(a.cfg.User.ProfileImageFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) if err != nil { a.serveError(w, r, "Failed to open local file", http.StatusBadRequest) return @@ -210,7 +209,7 @@ func (a *goBlog) serveUpdateProfileImage(w http.ResponseWriter, r *http.Request) func (a *goBlog) serveDeleteProfileImage(w http.ResponseWriter, r *http.Request) { a.profileImageHashString = "" - if err := os.Remove(profileImageFile); err != nil && !errors.Is(err, os.ErrNotExist) { + if err := os.Remove(a.cfg.User.ProfileImageFile); err != nil && !errors.Is(err, os.ErrNotExist) { a.serveError(w, r, "Failed to delete profile image", http.StatusInternalServerError) return } diff --git a/ui_test.go b/ui_test.go index 02e0bb1..23de9a7 100644 --- a/ui_test.go +++ b/ui_test.go @@ -2,6 +2,8 @@ package main import ( "bytes" + "mime/multipart" + "net/http/httptest" "os" "strings" "testing" @@ -136,14 +138,10 @@ func Test_renderInteractions(t *testing.T) { assert.Equal(t, expected, res) } -func Test_renderAuthor(t *testing.T) { - t.SkipNow() - // TODO: Add back some checks for image - +func Test_renderAuthorWithoutProfileImage(t *testing.T) { app := &goBlog{ cfg: createDefaultTestConfig(t), } - // app.cfg.User.Picture = "https://example.com/picture.jpg" app.cfg.User.Name = "John Doe" _ = app.initConfig(false) @@ -157,5 +155,43 @@ func Test_renderAuthor(t *testing.T) { _, err := goquery.NewDocumentFromReader(strings.NewReader(res)) require.NoError(t, err) - assert.Equal(t, "", res) + assert.Equal(t, "", res) +} + +func Test_renderAuthorWithProfileImage(t *testing.T) { + app := &goBlog{ + cfg: createDefaultTestConfig(t), + } + app.cfg.User.Name = "John Doe" + + _ = app.initConfig(false) + + // Update profile image + requestBody := &bytes.Buffer{} + writer := multipart.NewWriter(requestBody) + fileWriter, err := writer.CreateFormFile("file", "newprofile.jpg") + require.NoError(t, err) + _, err = fileWriter.Write(defaultLogo) + require.NoError(t, err) + writer.Close() + req := httptest.NewRequest("POST", "/update", requestBody) + req.Header.Set("Content-Type", writer.FormDataContentType()) + rr := httptest.NewRecorder() + + app.serveUpdateProfileImage(rr, req) + + require.Equal(t, 302, rr.Code) + assert.Equal(t, []string{"/profile.jpg?q=100&v=e3da5a2d765ff693e7eb54cff717ae0f79ec79c06ed3e3adf6054a46c2824f32"}, rr.Header()["Location"]) + + // Check rendering + buf := &bytes.Buffer{} + hb := htmlbuilder.NewHtmlBuilder(buf) + + app.renderAuthor(hb) + res := buf.String() + + _, err = goquery.NewDocumentFromReader(strings.NewReader(res)) + require.NoError(t, err) + + assert.Equal(t, "", res) }