diff --git a/activityPub_test.go b/activityPub_test.go index 8697650..6824708 100644 --- a/activityPub_test.go +++ b/activityPub_test.go @@ -5,7 +5,6 @@ import ( "encoding/pem" "net/http" "net/http/httptest" - "path/filepath" "testing" "github.com/stretchr/testify/assert" @@ -15,15 +14,10 @@ import ( func Test_loadActivityPubPrivateKey(t *testing.T) { app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - }, + cfg: createDefaultTestConfig(t), } - err := app.initDatabase(false) + err := app.initConfig(false) require.NoError(t, err) - defer app.db.close() require.NotNil(t, app.db) // Generate @@ -55,9 +49,7 @@ func Test_webfinger(t *testing.T) { cfg: createDefaultTestConfig(t), } app.cfg.Server.PublicAddress = "https://example.com" - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) app.prepareWebfinger() diff --git a/authentication_test.go b/authentication_test.go index 7fec897..af56503 100644 --- a/authentication_test.go +++ b/authentication_test.go @@ -29,9 +29,7 @@ func Test_authMiddleware(t *testing.T) { }, } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) app.d = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { diff --git a/blogroll_test.go b/blogroll_test.go index 69a5549..f4e6889 100644 --- a/blogroll_test.go +++ b/blogroll_test.go @@ -4,7 +4,6 @@ import ( "context" "net/http" "net/http/httptest" - "path/filepath" "testing" "github.com/stretchr/testify/assert" @@ -17,34 +16,26 @@ func Test_blogroll(t *testing.T) { app := &goBlog{ httpClient: fc.Client, - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - Server: &configServer{}, - DefaultBlog: "en", - Blogs: map[string]*configBlog{ - "en": { - Lang: "en", - Blogroll: &configBlogroll{ - Enabled: true, - Path: "/br", - AuthHeader: "Authheader", - AuthValue: "Authtoken", - Opml: "https://example.com/opml", - Categories: []string{"A", "B"}, - }, - }, - }, - User: &configUser{}, - Cache: &configCache{ - Enable: false, + cfg: createDefaultTestConfig(t), + } + + app.cfg.Cache.Enable = false + app.cfg.DefaultBlog = "en" + app.cfg.Blogs = map[string]*configBlog{ + "en": { + Lang: "en", + Blogroll: &configBlogroll{ + Enabled: true, + Path: "/br", + AuthHeader: "Authheader", + AuthValue: "Authtoken", + Opml: "https://example.com/opml", + Categories: []string{"A", "B"}, }, }, } - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) fc.setFakeResponse(http.StatusOK, ` diff --git a/blogstats_test.go b/blogstats_test.go index cb7754d..7ded1ed 100644 --- a/blogstats_test.go +++ b/blogstats_test.go @@ -5,7 +5,6 @@ import ( "io" "net/http" "net/http/httptest" - "path/filepath" "testing" "github.com/stretchr/testify/assert" @@ -14,36 +13,26 @@ import ( ) func Test_blogStats(t *testing.T) { + app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), + cfg: createDefaultTestConfig(t), + } + + app.cfg.Blogs = map[string]*configBlog{ + "en": { + Lang: "en", + BlogStats: &configBlogStats{ + Enabled: true, + Path: "/stats", }, - Server: &configServer{ - PublicAddress: "https://example.com", - }, - Blogs: map[string]*configBlog{ - "en": { - Lang: "en", - BlogStats: &configBlogStats{ - Enabled: true, - Path: "/stats", - }, - Sections: map[string]*configSection{ - "test": {}, - }, - }, - }, - DefaultBlog: "en", - User: &configUser{}, - Webmention: &configWebmention{ - DisableSending: true, + Sections: map[string]*configSection{ + "test": {}, }, }, } + app.cfg.DefaultBlog = "en" - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) // Insert post diff --git a/captcha_test.go b/captcha_test.go index 345c5d8..fe4c419 100644 --- a/captcha_test.go +++ b/captcha_test.go @@ -23,9 +23,7 @@ func Test_captchaMiddleware(t *testing.T) { cfg: createDefaultTestConfig(t), } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) app.d = alice.New(app.checkIsCaptcha, app.captchaMiddleware).ThenFunc(func(rw http.ResponseWriter, r *http.Request) { diff --git a/comments_test.go b/comments_test.go index b82463d..74ed627 100644 --- a/comments_test.go +++ b/comments_test.go @@ -5,7 +5,6 @@ import ( "net/http" "net/http/httptest" "net/url" - "path/filepath" "strings" "testing" @@ -18,25 +17,20 @@ import ( func Test_comments(t *testing.T) { app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), + cfg: createDefaultTestConfig(t), + } + app.cfg.Blogs = map[string]*configBlog{ + "en": { + Lang: "en", + Comments: &configComments{ + Enabled: true, }, - Server: &configServer{ - PublicAddress: "https://example.com", - }, - Blogs: map[string]*configBlog{ - "en": { - Lang: "en", - }, - }, - DefaultBlog: "en", - User: &configUser{}, }, } + app.cfg.DefaultBlog = "en" - _ = app.initDatabase(false) - defer app.db.close() + err := app.initConfig(false) + require.NoError(t, err) app.initComponents(false) t.Run("Successful comment", func(t *testing.T) { @@ -44,7 +38,7 @@ func Test_comments(t *testing.T) { // Create comment data := url.Values{} - data.Add("target", "https://example.com/test") + data.Add("target", "http://localhost:8080/test") data.Add("comment", "This is just a test") data.Add("name", "Test name") data.Add("website", "https://goblog.app") @@ -115,7 +109,7 @@ func Test_comments(t *testing.T) { // Create comment data := url.Values{} - data.Add("target", "https://example.com/test") + data.Add("target", "http://localhost:8080/test") data.Add("comment", "This is just a test") req := httptest.NewRequest(http.MethodPost, commentPath, strings.NewReader(data.Encode())) @@ -151,7 +145,7 @@ func Test_comments(t *testing.T) { t.Run("Empty comment", func(t *testing.T) { data := url.Values{} - data.Add("target", "https://example.com/test") + data.Add("target", "http://localhost:8080/test") data.Add("comment", "") req := httptest.NewRequest(http.MethodPost, commentPath, strings.NewReader(data.Encode())) diff --git a/config.go b/config.go index 81be721..6135182 100644 --- a/config.go +++ b/config.go @@ -341,13 +341,17 @@ func (a *goBlog) loadConfigFile(file string) error { return v.Unmarshal(a.cfg) } -func (a *goBlog) initConfig() error { +func (a *goBlog) initConfig(logging bool) error { if a.cfg == nil { a.cfg = createDefaultConfig() } if a.cfg.initialized { return nil } + // Init database + if err := a.initDatabase(logging); err != nil { + return err + } // Check config // Parse addresses and hostnames if a.cfg.Server.PublicAddress == "" { @@ -402,12 +406,24 @@ func (a *goBlog) initConfig() error { b.Comments = &configComments{Enabled: false} } } + // Check if sections already migrated to db + const sectionMigrationKey = "sections_migrated" + if val, err := a.getSettingValue(sectionMigrationKey); err != nil { + return err + } else if val == "" { + if err = a.saveAllSections(); err != nil { + return err + } + if err = a.saveSettingValue(sectionMigrationKey, "1"); err != nil { + return err + } + } + // Load db sections + if err = a.loadSections(); err != nil { + return err + } // Check config for each blog for _, blog := range a.cfg.Blogs { - // Copy sections key to section name - for k, s := range blog.Sections { - s.Name = k - } // Check if language is set if blog.Lang == "" { blog.Lang = "en" diff --git a/contact_test.go b/contact_test.go index 74d60d5..ef60e60 100644 --- a/contact_test.go +++ b/contact_test.go @@ -5,7 +5,6 @@ import ( "net/http" "net/http/httptest" "net/url" - "path/filepath" "strings" "testing" @@ -24,35 +23,27 @@ func Test_contact(t *testing.T) { // Init everything app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), + cfg: createDefaultTestConfig(t), + } + app.cfg.Blogs = map[string]*configBlog{ + "en": { + Lang: "en", + // Config for contact + Contact: &configContact{ + Enabled: true, + SMTPPort: port, + SMTPHost: "127.0.0.1", + SMTPUser: "user", + SMTPPassword: "pass", + EmailTo: "to@example.org", + EmailFrom: "from@example.org", + EmailSubject: "Neue Kontaktnachricht", }, - Server: &configServer{ - PublicAddress: "https://example.com", - }, - Blogs: map[string]*configBlog{ - "en": { - Lang: "en", - // Config for contact - Contact: &configContact{ - Enabled: true, - SMTPPort: port, - SMTPHost: "127.0.0.1", - SMTPUser: "user", - SMTPPassword: "pass", - EmailTo: "to@example.org", - EmailFrom: "from@example.org", - EmailSubject: "Neue Kontaktnachricht", - }, - }, - }, - DefaultBlog: "en", - User: &configUser{}, }, } - _ = app.initDatabase(false) - defer app.db.close() + app.cfg.DefaultBlog = "en" + + _ = app.initConfig(false) app.initComponents(false) // Make contact form request diff --git a/database.go b/database.go index 6c84adb..fc5068a 100644 --- a/database.go +++ b/database.go @@ -31,6 +31,9 @@ type database struct { } func (a *goBlog) initDatabase(logging bool) (err error) { + if a.db != nil { + return + } if logging { log.Println("Initialize database...") } diff --git a/dbmigrations/00029.sql b/dbmigrations/00029.sql new file mode 100644 index 0000000..e50c660 --- /dev/null +++ b/dbmigrations/00029.sql @@ -0,0 +1,9 @@ +create table sections ( + blog text not null, + name text not null, + title text not null default '', + description text not null default '', + pathtemplate text not null default '', + showfull boolean not null default false, + primary key (blog, name) +); \ No newline at end of file diff --git a/dbmigrations/00030.sql b/dbmigrations/00030.sql new file mode 100644 index 0000000..73911e9 --- /dev/null +++ b/dbmigrations/00030.sql @@ -0,0 +1,5 @@ +create table settings ( + name text not null, + value text not null default '', + primary key (name) +); \ No newline at end of file diff --git a/editor_test.go b/editor_test.go index f0fc2a3..d200a01 100644 --- a/editor_test.go +++ b/editor_test.go @@ -15,9 +15,7 @@ func Test_editorPreview(t *testing.T) { app := &goBlog{ cfg: createDefaultTestConfig(t), } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) h := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { diff --git a/errors_test.go b/errors_test.go index 52863c1..aba0088 100644 --- a/errors_test.go +++ b/errors_test.go @@ -4,7 +4,6 @@ import ( "io" "net/http" "net/http/httptest" - "path/filepath" "testing" "github.com/stretchr/testify/assert" @@ -13,25 +12,10 @@ import ( func Test_errors(t *testing.T) { app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - Server: &configServer{ - PublicAddress: "https://example.com", - }, - Blogs: map[string]*configBlog{ - "en": { - Lang: "en", - }, - }, - DefaultBlog: "en", - User: &configUser{}, - }, + cfg: createDefaultTestConfig(t), } - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) t.Run("Test 404, no HTML", func(t *testing.T) { diff --git a/export_test.go b/export_test.go index 46dc1f1..0cb00d8 100644 --- a/export_test.go +++ b/export_test.go @@ -11,14 +11,9 @@ import ( func Test_export(t *testing.T) { app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - }, + cfg: createDefaultTestConfig(t), } - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initMarkdown() err := app.db.savePost(&post{ diff --git a/feeds_test.go b/feeds_test.go index 296eb9d..29da48c 100644 --- a/feeds_test.go +++ b/feeds_test.go @@ -15,10 +15,9 @@ func Test_feeds(t *testing.T) { app := &goBlog{ cfg: createDefaultTestConfig(t), } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) + app.d = app.buildRouter() handlerClient := newHandlerClient(app.d) diff --git a/geoTrack_test.go b/geoTrack_test.go index d74dc90..285968d 100644 --- a/geoTrack_test.go +++ b/geoTrack_test.go @@ -2,7 +2,6 @@ package main import ( "os" - "path/filepath" "testing" "github.com/stretchr/testify/assert" @@ -11,24 +10,18 @@ import ( func Test_geoTrack(t *testing.T) { app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - Server: &configServer{}, - Blogs: map[string]*configBlog{ - "en": { - Lang: "en", - }, - "de": { - Lang: "de", - }, - }, + cfg: createDefaultTestConfig(t), + } + app.cfg.Blogs = map[string]*configBlog{ + "en": { + Lang: "en", + }, + "de": { + Lang: "de", }, } - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) // First test (just with track) diff --git a/geo_test.go b/geo_test.go index 9eb7e08..92822e6 100644 --- a/geo_test.go +++ b/geo_test.go @@ -16,9 +16,8 @@ func Test_geo(t *testing.T) { httpClient: fc.Client, cfg: createDefaultTestConfig(t), } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + + _ = app.initConfig(false) app.initComponents(false) p := &post{ diff --git a/http.go b/http.go index e101cf6..bc5acea 100644 --- a/http.go +++ b/http.go @@ -32,7 +32,7 @@ const ( func (a *goBlog) startServer() (err error) { log.Println("Start server(s)...") // Load router - a.d = a.buildRouter() + a.reloadRouter() // Set basic middlewares h := alice.New() h = h.Append(middleware.Heartbeat("/ping")) @@ -43,7 +43,9 @@ func (a *goBlog) startServer() (err error) { if a.httpsConfigured(false) { h = h.Append(a.securityHeaders) } - finalHandler := h.Then(a.d) + finalHandler := h.ThenFunc(func(w http.ResponseWriter, r *http.Request) { + a.d.ServeHTTP(w, r) + }) // Start Onion service if a.cfg.Server.Tor { go func() { @@ -116,6 +118,10 @@ const ( feedPath = ".{feed:(rss|json|atom)}" ) +func (a *goBlog) reloadRouter() { + a.d = a.buildRouter() +} + func (a *goBlog) buildRouter() http.Handler { mapRouter := &maprouter.MapRouter{ Handlers: map[string]http.Handler{}, diff --git a/httpLogs_test.go b/httpLogs_test.go index a41b0d8..5b7529a 100644 --- a/httpLogs_test.go +++ b/httpLogs_test.go @@ -15,7 +15,7 @@ func Test_httpLogsConfig(t *testing.T) { app := &goBlog{ cfg: createDefaultTestConfig(t), } - _ = app.initConfig() + _ = app.initConfig(false) assert.Equal(t, false, app.cfg.Server.Logging) assert.Equal(t, "data/access.log", app.cfg.Server.LogFile) diff --git a/httpRouters.go b/httpRouters.go index 1bf447d..3804cfe 100644 --- a/httpRouters.go +++ b/httpRouters.go @@ -170,6 +170,9 @@ func (a *goBlog) blogRouter(blog string, conf *configBlog) func(r chi.Router) { // Sitemap r.Group(a.blogSitemapRouter(conf)) + // Settings + r.Route(conf.getRelativePath(settingsPath), a.blogSettingsRouter(conf)) + } } @@ -442,3 +445,14 @@ func (a *goBlog) blogSitemapRouter(conf *configBlog) func(r chi.Router) { r.Get(conf.getRelativePath(sitemapBlogPostsPath), a.serveSitemapBlogPosts) } } + +// Blog - Settings +func (a *goBlog) blogSettingsRouter(_ *configBlog) func(r chi.Router) { + return func(r chi.Router) { + r.Use(a.authMiddleware) + r.Get("/", a.serveSettings) + r.Post(settingsDeleteSectionPath, a.settingsDeleteSection) + r.Post(settingsCreateSectionPath, a.settingsCreateSection) + r.Post(settingsUpdateSectionPath, a.settingsUpdateSection) + } +} diff --git a/indexnow_test.go b/indexnow_test.go index dbbc59a..e5ea677 100644 --- a/indexnow_test.go +++ b/indexnow_test.go @@ -19,9 +19,8 @@ func Test_indexNow(t *testing.T) { httpClient: fc.Client, } app.cfg.IndexNow = &configIndexNow{Enabled: true} - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + + _ = app.initConfig(false) app.initComponents(false) // Create http router diff --git a/indieAuthServer_test.go b/indieAuthServer_test.go index 3b744f5..96a4fde 100644 --- a/indieAuthServer_test.go +++ b/indieAuthServer_test.go @@ -5,7 +5,6 @@ import ( "net/http/httptest" "net/url" "os" - "path/filepath" "strings" "testing" @@ -22,35 +21,25 @@ func Test_indieAuthServer(t *testing.T) { app := &goBlog{ httpClient: newFakeHttpClient().Client, - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - Server: &configServer{ - PublicAddress: "https://example.org", - }, - DefaultBlog: "en", - Blogs: map[string]*configBlog{ - "en": { - Lang: "en", - }, - }, - User: &configUser{ - Name: "John Doe", - Nick: "jdoe", - }, - Cache: &configCache{ - Enable: false, - }, + cfg: createDefaultTestConfig(t), + } + app.cfg.Server.PublicAddress = "https://example.org" + app.cfg.Blogs = map[string]*configBlog{ + "en": { + Lang: "en", }, } + app.cfg.User = &configUser{ + Name: "John Doe", + Nick: "jdoe", + } + app.cfg.Cache.Enable = false + + _ = app.initConfig(false) + app.initComponents(false) app.d = app.buildRouter() - _ = app.initDatabase(false) - defer app.db.close() - app.initComponents(false) - app.ias.Client = newHandlerClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) diff --git a/indieAuth_test.go b/indieAuth_test.go index 5a8a335..0c5bc38 100644 --- a/indieAuth_test.go +++ b/indieAuth_test.go @@ -3,7 +3,6 @@ package main import ( "net/http" "net/http/httptest" - "path/filepath" "strings" "testing" @@ -15,22 +14,10 @@ func Test_checkIndieAuth(t *testing.T) { app := &goBlog{ httpClient: newFakeHttpClient().Client, - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - Server: &configServer{}, - DefaultBlog: "en", - Blogs: map[string]*configBlog{ - "en": { - Lang: "en", - }, - }, - }, + cfg: createDefaultTestConfig(t), } - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) req := httptest.NewRequest(http.MethodGet, "/", nil) diff --git a/main.go b/main.go index c971df8..5c8625d 100644 --- a/main.go +++ b/main.go @@ -64,7 +64,7 @@ func main() { app.logErrAndQuit("Failed to load config file:", err.Error()) return } - if err = app.initConfig(); err != nil { + if err = app.initConfig(false); err != nil { app.logErrAndQuit("Failed to init config:", err.Error()) return } @@ -129,12 +129,6 @@ func main() { // Execute pre-start hooks app.preStartHooks() - // Initialize database - if err = app.initDatabase(true); err != nil { - app.logErrAndQuit("Failed to init database:", err.Error()) - return - } - // Link check tool after init of markdown if len(os.Args) >= 2 && os.Args[1] == "check" { app.initMarkdown() diff --git a/micropub_test.go b/micropub_test.go index 8cd6b8e..3a774d3 100644 --- a/micropub_test.go +++ b/micropub_test.go @@ -14,9 +14,7 @@ func Test_micropubQuery(t *testing.T) { app := &goBlog{ cfg: createDefaultTestConfig(t), } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) // Create a test post with tags diff --git a/ntfy_test.go b/ntfy_test.go index 3f05138..e0f3f53 100644 --- a/ntfy_test.go +++ b/ntfy_test.go @@ -18,9 +18,7 @@ func Test_ntfySending(t *testing.T) { httpClient: fakeClient.Client, } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) t.Run("Default", func(t *testing.T) { diff --git a/postsDb_test.go b/postsDb_test.go index d1b23a0..5763de9 100644 --- a/postsDb_test.go +++ b/postsDb_test.go @@ -1,7 +1,6 @@ package main import ( - "path/filepath" "testing" "time" @@ -25,9 +24,7 @@ func Test_postsDb(t *testing.T) { }, }, } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) now := toLocalSafe(time.Now().String()) @@ -229,14 +226,9 @@ func Test_ftsWithoutTitle(t *testing.T) { // Added because there was a bug where there were no search results without title app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - }, + cfg: createDefaultTestConfig(t), } - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initMarkdown() err := app.db.savePost(&post{ @@ -261,14 +253,9 @@ func Test_postsPriority(t *testing.T) { // Added because there was a bug where there were no search results without title app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - }, + cfg: createDefaultTestConfig(t), } - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initMarkdown() err := app.db.savePost(&post{ @@ -312,14 +299,9 @@ func Test_postsPriority(t *testing.T) { func Test_usesOfMediaFile(t *testing.T) { app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - }, + cfg: createDefaultTestConfig(t), } - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) err := app.db.savePost(&post{ Path: "/test/abc", @@ -368,8 +350,7 @@ func Test_replaceParams(t *testing.T) { app := &goBlog{ cfg: createDefaultTestConfig(t), } - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) err := app.db.savePost(&post{ Path: "/test/abc", @@ -399,9 +380,7 @@ func Test_postDeletesParams(t *testing.T) { app := &goBlog{ cfg: createDefaultTestConfig(t), } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) err := app.createPost(&post{ diff --git a/postsDeleter_test.go b/postsDeleter_test.go index 4206490..ff8b80e 100644 --- a/postsDeleter_test.go +++ b/postsDeleter_test.go @@ -11,9 +11,8 @@ func Test_checkDeletedPosts(t *testing.T) { app := &goBlog{ cfg: createDefaultTestConfig(t), } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + + _ = app.initConfig(false) app.initComponents(false) // Create a post diff --git a/postsScheduler_test.go b/postsScheduler_test.go index 492eb2e..3e274bc 100644 --- a/postsScheduler_test.go +++ b/postsScheduler_test.go @@ -1,7 +1,6 @@ package main import ( - "path/filepath" "testing" "time" @@ -12,28 +11,18 @@ import ( func Test_postsScheduler(t *testing.T) { app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), + cfg: createDefaultTestConfig(t), + } + app.cfg.Blogs = map[string]*configBlog{ + "en": { + Sections: map[string]*configSection{ + "test": {}, }, - Server: &configServer{ - PublicAddress: "https://example.com", - }, - DefaultBlog: "en", - Blogs: map[string]*configBlog{ - "en": { - Sections: map[string]*configSection{ - "test": {}, - }, - Lang: "en", - }, - }, - Micropub: &configMicropub{}, + Lang: "en", }, } - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) err := app.db.savePost(&post{ diff --git a/posts_test.go b/posts_test.go index c535cd0..61421cc 100644 --- a/posts_test.go +++ b/posts_test.go @@ -16,9 +16,7 @@ func Test_serveDate(t *testing.T) { app := &goBlog{ cfg: createDefaultTestConfig(t), } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) app.d = app.buildRouter() @@ -106,9 +104,7 @@ func Test_servePost(t *testing.T) { Username: "test", Password: "test", }) - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) app.d = app.buildRouter() diff --git a/privateMode_test.go b/privateMode_test.go index 9fd73ce..558e553 100644 --- a/privateMode_test.go +++ b/privateMode_test.go @@ -3,7 +3,6 @@ package main import ( "net/http" "net/http/httptest" - "path/filepath" "testing" "github.com/go-chi/chi/v5/middleware" @@ -16,36 +15,28 @@ func Test_privateMode(t *testing.T) { // Init app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "db.db"), - }, - Server: &configServer{}, - PrivateMode: &configPrivateMode{ - Enabled: true, - }, - User: &configUser{ - Name: "Test", - Nick: "test", - Password: "testpw", - AppPasswords: []*configAppPassword{ - { - Username: "testapp", - Password: "pw", - }, - }, - }, - DefaultBlog: "en", - Blogs: map[string]*configBlog{ - "en": { - Lang: "en", + cfg: createDefaultTestConfig(t), + } + app.cfg.PrivateMode = &configPrivateMode{Enabled: true} + app.cfg.User = + &configUser{ + Name: "Test", + Nick: "test", + Password: "testpw", + AppPasswords: []*configAppPassword{ + { + Username: "testapp", + Password: "pw", }, }, + } + app.cfg.Blogs = map[string]*configBlog{ + "en": { + Lang: "en", }, } - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) handler := alice.New(middleware.WithValue(blogKey, "en"), app.privateModeHandler).ThenFunc(func(rw http.ResponseWriter, r *http.Request) { diff --git a/queue_test.go b/queue_test.go index 7537b3c..501fb60 100644 --- a/queue_test.go +++ b/queue_test.go @@ -2,7 +2,6 @@ package main import ( "context" - "path/filepath" "testing" "time" @@ -12,14 +11,9 @@ import ( func Test_queue(t *testing.T) { app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - }, + cfg: createDefaultTestConfig(t), } - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) time1 := time.Now() @@ -65,30 +59,3 @@ func Test_queue(t *testing.T) { require.Equal(t, []byte("1"), qi.content) } - -func Benchmark_queue(b *testing.B) { - app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(b.TempDir(), "test.db"), - }, - }, - } - _ = app.initDatabase(false) - defer app.db.close() - - err := app.enqueue("test", []byte("1"), time.Now()) - require.NoError(b, err) - - b.Run("Peek with item", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _, _ = app.peekQueue(context.Background(), "test") - } - }) - - b.Run("Peek without item", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _, _ = app.peekQueue(context.Background(), "abc") - } - }) -} diff --git a/reactions_test.go b/reactions_test.go index 3423977..93559c1 100644 --- a/reactions_test.go +++ b/reactions_test.go @@ -15,9 +15,7 @@ func Test_reactionsLowLevel(t *testing.T) { app := &goBlog{ cfg: createDefaultTestConfig(t), } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) err := app.saveReaction("🖕", "/testpost") @@ -97,9 +95,7 @@ func Test_reactionsHighLevel(t *testing.T) { app := &goBlog{ cfg: createDefaultTestConfig(t), } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) // Send unsuccessful reaction diff --git a/settings.go b/settings.go new file mode 100644 index 0000000..40ce3c2 --- /dev/null +++ b/settings.go @@ -0,0 +1,129 @@ +package main + +import ( + "net/http" + "sort" + + "github.com/samber/lo" +) + +const settingsPath = "/settings" + +func (a *goBlog) serveSettings(w http.ResponseWriter, r *http.Request) { + blog, bc := a.getBlog(r) + + sections := lo.Values(bc.Sections) + sort.Slice(sections, func(i, j int) bool { return sections[i].Name < sections[j].Name }) + + a.render(w, r, a.renderSettings, &renderData{ + Data: &settingsRenderData{ + blog: blog, + sections: sections, + }, + }) +} + +const settingsDeleteSectionPath = "/deletesection" + +func (a *goBlog) settingsDeleteSection(w http.ResponseWriter, r *http.Request) { + blog, bc := a.getBlog(r) + section := r.FormValue("sectionname") + // Check if any post uses this section + count, err := a.db.countPosts(&postsRequestConfig{ + blog: blog, + sections: []string{section}, + }) + if err != nil { + a.serveError(w, r, "Failed to check if section is still used", http.StatusInternalServerError) + return + } + if count > 0 { + a.serveError(w, r, "Section is still used", http.StatusBadRequest) + return + } + // Delete section + err = a.deleteSection(blog, section) + if err != nil { + a.serveError(w, r, "Failed to delete section from the database", http.StatusInternalServerError) + return + } + // Reload sections + err = a.loadSections() + if err != nil { + a.serveError(w, r, "Failed to reload section configuration from the database", http.StatusInternalServerError) + return + } + a.reloadRouter() + a.cache.purge() + http.Redirect(w, r, bc.getRelativePath(settingsPath), http.StatusFound) +} + +const settingsCreateSectionPath = "/createsection" + +func (a *goBlog) settingsCreateSection(w http.ResponseWriter, r *http.Request) { + blog, bc := a.getBlog(r) + // Read values + sectionName := r.FormValue("sectionname") + sectionTitle := r.FormValue("sectiontitle") + if sectionName == "" || sectionTitle == "" { + a.serveError(w, r, "Missing values for name or title", http.StatusBadRequest) + return + } + // Create section + section := &configSection{ + Name: sectionName, + Title: sectionTitle, + } + err := a.addSection(blog, section) + if err != nil { + a.serveError(w, r, "Failed to insert section into database", http.StatusInternalServerError) + return + } + // Reload sections + err = a.loadSections() + if err != nil { + a.serveError(w, r, "Failed to reload section configuration from the database", http.StatusInternalServerError) + return + } + a.reloadRouter() + a.cache.purge() + http.Redirect(w, r, bc.getRelativePath(settingsPath), http.StatusFound) +} + +const settingsUpdateSectionPath = "/updatesection" + +func (a *goBlog) settingsUpdateSection(w http.ResponseWriter, r *http.Request) { + blog, bc := a.getBlog(r) + // Read values + sectionName := r.FormValue("sectionname") + sectionTitle := r.FormValue("sectiontitle") + if sectionName == "" || sectionTitle == "" { + a.serveError(w, r, "Missing values for name or title", http.StatusBadRequest) + return + } + sectionDescription := r.FormValue("sectiondescription") + sectionPathTemplate := r.FormValue("sectionpathtemplate") + sectionShowFull := r.FormValue("sectionshowfull") == "on" + // Create section + section := &configSection{ + Name: sectionName, + Title: sectionTitle, + Description: sectionDescription, + PathTemplate: sectionPathTemplate, + ShowFull: sectionShowFull, + } + err := a.updateSection(blog, sectionName, section) + if err != nil { + a.serveError(w, r, "Failed to update section in database", http.StatusInternalServerError) + return + } + // Reload sections + err = a.loadSections() + if err != nil { + a.serveError(w, r, "Failed to reload section configuration from the database", http.StatusInternalServerError) + return + } + a.reloadRouter() + a.cache.purge() + http.Redirect(w, r, bc.getRelativePath(settingsPath), http.StatusFound) +} diff --git a/settingsDb.go b/settingsDb.go new file mode 100644 index 0000000..560f06c --- /dev/null +++ b/settingsDb.go @@ -0,0 +1,103 @@ +package main + +import ( + "database/sql" + "errors" +) + +func (a *goBlog) getSettingValue(name string) (string, error) { + row, err := a.db.queryRow("select value from settings where name = @name", sql.Named("name", name)) + if err != nil { + return "", + err + } + var value string + err = row.Scan(&value) + if errors.Is(err, sql.ErrNoRows) { + return "", nil + } else if err != nil { + return "", err + } + return value, nil +} + +func (a *goBlog) saveSettingValue(name, value string) error { + _, err := a.db.exec( + "insert into settings (name, value) values (@name, @value) on conflict (name) do update set value = @value2", + sql.Named("name", name), + sql.Named("value", value), + sql.Named("value2", value), + ) + return err +} + +func (a *goBlog) loadSections() error { + for blog, bc := range a.cfg.Blogs { + sections, err := a.getSections(blog) + if err != nil { + return err + } + bc.Sections = sections + } + return nil +} + +func (a *goBlog) getSections(blog string) (map[string]*configSection, error) { + rows, err := a.db.query("select name, title, description, pathtemplate, showfull from sections where blog = @blog", sql.Named("blog", blog)) + if err != nil { + return nil, err + } + sections := map[string]*configSection{} + for rows.Next() { + section := &configSection{} + err = rows.Scan(§ion.Name, §ion.Title, §ion.Description, §ion.PathTemplate, §ion.ShowFull) + if err != nil { + return nil, err + } + sections[section.Name] = section + } + return sections, nil +} + +func (a *goBlog) saveAllSections() error { + for blog, bc := range a.cfg.Blogs { + for k, s := range bc.Sections { + s.Name = k + if err := a.addSection(blog, s); err != nil { + return err + } + } + } + return nil +} + +func (a *goBlog) addSection(blog string, section *configSection) error { + _, err := a.db.exec( + "insert into sections (blog, name, title, description, pathtemplate, showfull) values (@blog, @name, @title, @description, @pathtemplate, @showfull)", + sql.Named("blog", blog), + sql.Named("name", section.Name), + sql.Named("title", section.Title), + sql.Named("description", section.Description), + sql.Named("pathtemplate", section.PathTemplate), + sql.Named("showfull", section.ShowFull), + ) + return err +} + +func (a *goBlog) deleteSection(blog string, name string) error { + _, err := a.db.exec("delete from sections where blog = @blog and name = @name", sql.Named("blog", blog), sql.Named("name", name)) + return err +} + +func (a *goBlog) updateSection(blog string, name string, section *configSection) error { + _, err := a.db.exec( + "update sections set title = @title, description = @description, pathtemplate = @pathtemplate, showfull = @showfull where blog = @blog and name = @name", + sql.Named("title", section.Title), + sql.Named("description", section.Description), + sql.Named("pathtemplate", section.PathTemplate), + sql.Named("showfull", section.ShowFull), + sql.Named("blog", blog), + sql.Named("name", section.Name), + ) + return err +} diff --git a/shortPath_test.go b/shortPath_test.go index 04d5921..73829ba 100644 --- a/shortPath_test.go +++ b/shortPath_test.go @@ -1,7 +1,6 @@ package main import ( - "path/filepath" "testing" "github.com/stretchr/testify/assert" @@ -10,14 +9,10 @@ import ( func Test_shortenPath(t *testing.T) { app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - }, + cfg: createDefaultTestConfig(t), } - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) + db := app.db res1, err := db.shortenPath("/a") diff --git a/sitemap_test.go b/sitemap_test.go index da84707..4814d73 100644 --- a/sitemap_test.go +++ b/sitemap_test.go @@ -16,9 +16,8 @@ func Test_sitemap(t *testing.T) { app := &goBlog{ cfg: createDefaultTestConfig(t), } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + + _ = app.initConfig(false) app.initComponents(false) app.d = app.buildRouter() diff --git a/strings/de.yaml b/strings/de.yaml index 71befb0..3328664 100644 --- a/strings/de.yaml +++ b/strings/de.yaml @@ -43,6 +43,7 @@ noposts: "Hier sind keine Posts." oldcontent: "⚠️ Dieser Eintrag ist bereits über ein Jahr alt. Er ist möglicherweise nicht mehr aktuell. Meinungen können sich geändert haben." pinned: "Angepinnt" posts: "Posts" +postsections: "Post-Bereiche" prev: "Zurück" privateposts: "Private Posts" privatepostsdesc: "Posts mit dem Status `private`, die nur eingeloggt sichtbar sind." @@ -51,7 +52,13 @@ replyto: "Antwort an" scheduledposts: "Geplante Posts" scheduledpostsdesc: "Beiträge mit dem Status `scheduled`, die veröffentlicht werden, wenn das `published`-Datum erreicht ist." search: "Suchen" +sectiondescription: "Beschreibung" +sectionname: "Name" +sectionpathtemplate: "Pfadvorlage" +sectionshowfull: "Vollständigen Inhalt in der Zusammenfassung anzeigen" +sectiontitle: "Title" send: "Senden (zur Überprüfung)" +settings: "Einstellungen" share: "Online teilen" shorturl: "Kurz-Link:" speak: "Vorlesen" diff --git a/strings/default.yaml b/strings/default.yaml index 48163e4..e754533 100644 --- a/strings/default.yaml +++ b/strings/default.yaml @@ -53,6 +53,7 @@ oldcontent: "⚠️ This entry is already over one year old. It may no longer be password: "Password" pinned: "Pinned" posts: "Posts" +postsections: "Post sections" prev: "Previous" privateposts: "Private posts" privatepostsdesc: "Posts with status `private` that are visible only when logged in." @@ -63,7 +64,13 @@ scheduledposts: "Scheduled posts" scheduledpostsdesc: "Posts with status `scheduled` that are published when the `published` date is reached." scopes: "Scopes" search: "Search" +sectiondescription: "Description" +sectionname: "Name" +sectionpathtemplate: "Path template" +sectionshowfull: "Show full content in summary" +sectiontitle: "Title" send: "Send (to review)" +settings: "Settings" share: "Share online" shorturl: "Short link:" speak: "Read aloud" diff --git a/telegram_test.go b/telegram_test.go index 842839d..eb71969 100644 --- a/telegram_test.go +++ b/telegram_test.go @@ -122,9 +122,7 @@ func Test_telegram(t *testing.T) { cfg: cfg, httpClient: fakeClient.Client, } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initMarkdown() app.initTelegram() @@ -156,9 +154,7 @@ func Test_telegram(t *testing.T) { httpClient: fakeClient.Client, } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initTelegram() diff --git a/ui.go b/ui.go index e7a3f85..0fc95eb 100644 --- a/ui.go +++ b/ui.go @@ -125,6 +125,10 @@ func (a *goBlog) renderBase(hb *htmlBuilder, rd *renderData, title, main func(hb hb.writeElementClose("a") } hb.write(" • ") + hb.writeElementOpen("a", "href", rd.Blog.getRelativePath("/settings")) + hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "settings")) + hb.writeElementClose("a") + hb.write(" • ") hb.writeElementOpen("a", "href", "/logout") hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "logout")) hb.writeElementClose("a") @@ -1480,3 +1484,104 @@ func (a *goBlog) renderEditor(hb *htmlBuilder, rd *renderData) { }, ) } + +type settingsRenderData struct { + blog string + sections []*configSection +} + +func (a *goBlog) renderSettings(hb *htmlBuilder, rd *renderData) { + srd, ok := rd.Data.(*settingsRenderData) + if !ok { + return + } + a.renderBase( + hb, rd, + func(hb *htmlBuilder) { + a.renderTitleTag(hb, rd.Blog, a.ts.GetTemplateStringVariant(rd.Blog.Lang, "settings")) + }, + func(hb *htmlBuilder) { + hb.writeElementOpen("main") + + // Title + hb.writeElementOpen("h1") + hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "settings")) + hb.writeElementClose("h1") + + // Post sections + hb.writeElementOpen("h2") + hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "postsections")) + hb.writeElementClose("h2") + + for _, section := range srd.sections { + hb.writeElementOpen("details") + + hb.writeElementOpen("summary") + hb.writeElementOpen("h3") + hb.writeEscaped(section.Name) + hb.writeElementClose("h3") + hb.writeElementClose("summary") + + hb.writeElementOpen("form", "class", "fw p", "method", "post") + + hb.writeElementOpen("input", "type", "hidden", "name", "sectionname", "value", section.Name) + + // Title + hb.writeElementOpen("input", "type", "text", "name", "sectiontitle", "placeholder", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "sectiontitle"), "required", "", "value", section.Title) + // Description + hb.writeElementOpen( + "textarea", + "name", "sectiondescription", + "class", "monospace", + "placeholder", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "sectiondescription"), + ) + hb.writeEscaped(section.Description) + hb.writeElementClose("textarea") + // Path template + hb.writeElementOpen("input", "type", "text", "name", "sectionpathtemplate", "placeholder", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "sectionpathtemplate"), "value", section.PathTemplate) + // Show full + hb.writeElementOpen("input", "type", "checkbox", "name", "sectionshowfull", "id", "showfull-"+section.Name, lo.If(section.ShowFull, "checked").Else(""), "") + hb.writeElementOpen("label", "for", "showfull-"+section.Name) + hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "sectionshowfull")) + hb.writeElementClose("label") + + // Actions + hb.writeElementOpen("div", "class", "p") + // Update + hb.writeElementOpen( + "input", "type", "submit", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "update"), + "formaction", rd.Blog.getRelativePath(settingsPath+settingsUpdateSectionPath), + ) + // Delete + hb.writeElementOpen( + "input", "type", "submit", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "delete"), + "formaction", rd.Blog.getRelativePath(settingsPath+settingsDeleteSectionPath), + "class", "confirm", "data-confirmmessage", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "confirmdelete"), + ) + hb.writeElementOpen("script", "src", a.assetFileName("js/formconfirm.js"), "defer", "") + hb.writeElementClose("script") + hb.writeElementClose("div") + + hb.writeElementClose("form") + hb.writeElementClose("details") + } + + // Create new section + hb.writeElementOpen("form", "class", "fw p", "method", "post") + // Name + hb.writeElementOpen("input", "type", "text", "name", "sectionname", "placeholder", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "sectionname"), "required", "") + // Title + hb.writeElementOpen("input", "type", "text", "name", "sectiontitle", "placeholder", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "sectiontitle"), "required", "") + // Create button + hb.writeElementOpen("div") + hb.writeElementOpen( + "input", "type", "submit", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "create"), + "formaction", rd.Blog.getRelativePath(settingsPath+settingsCreateSectionPath), + ) + hb.writeElementClose("div") + hb.writeElementClose("form") + + hb.writeElementClose("main") + }, + ) +} diff --git a/ui_test.go b/ui_test.go index 1464ce5..a001900 100644 --- a/ui_test.go +++ b/ui_test.go @@ -20,9 +20,7 @@ func Test_renderPostTax(t *testing.T) { app := &goBlog{ cfg: createDefaultTestConfig(t), } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) p := &post{ @@ -48,9 +46,7 @@ func Test_renderOldContentWarning(t *testing.T) { app := &goBlog{ cfg: createDefaultTestConfig(t), } - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) p := &post{ @@ -76,10 +72,10 @@ func Test_renderInteractions(t *testing.T) { cfg: createDefaultTestConfig(t), } app.cfg.Server.PublicAddress = "https://example.com" - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + + _ = app.initConfig(false) app.initComponents(false) + app.d = app.buildRouter() err = app.createPost(&post{ @@ -145,9 +141,8 @@ func Test_renderAuthor(t *testing.T) { } app.cfg.User.Picture = "https://example.com/picture.jpg" app.cfg.User.Name = "John Doe" - _ = app.initConfig() - _ = app.initDatabase(false) - defer app.db.close() + + _ = app.initConfig(false) app.initComponents(false) buf := &bytes.Buffer{} diff --git a/webmentionVerification_test.go b/webmentionVerification_test.go index 6d5a3ab..86b373c 100644 --- a/webmentionVerification_test.go +++ b/webmentionVerification_test.go @@ -3,7 +3,6 @@ package main import ( "net/http" "os" - "path/filepath" "strings" "testing" @@ -21,23 +20,16 @@ func Test_verifyMention(t *testing.T) { app := &goBlog{ httpClient: mockClient.Client, - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - Server: &configServer{ - PublicAddress: "https://example.org", - }, - }, + cfg: createDefaultTestConfig(t), d: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if strings.HasSuffix(r.URL.Path, "/") { http.Redirect(w, r, r.URL.Path[:len(r.URL.Path)-1], http.StatusFound) } }), } + app.cfg.Server.PublicAddress = "https://example.org" - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) m := &mention{ @@ -71,21 +63,14 @@ func Test_verifyMentionBidgy(t *testing.T) { app := &goBlog{ httpClient: mockClient.Client, - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - Server: &configServer{ - PublicAddress: "https://example.org", - }, - }, + cfg: createDefaultTestConfig(t), d: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // do nothing }), } + app.cfg.Server.PublicAddress = "https://example.org" - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) m := &mention{ @@ -115,21 +100,14 @@ func Test_verifyMentionColin(t *testing.T) { app := &goBlog{ httpClient: mockClient.Client, - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - Server: &configServer{ - PublicAddress: "https://jlelse.blog", - }, - }, + cfg: createDefaultConfig(), d: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // do nothing }), } + app.cfg.Server.PublicAddress = "https://jlelse.blog" - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) m := &mention{ diff --git a/webmention_test.go b/webmention_test.go index 2488f42..fc6a925 100644 --- a/webmention_test.go +++ b/webmention_test.go @@ -1,7 +1,6 @@ package main import ( - "path/filepath" "testing" "time" @@ -11,25 +10,16 @@ import ( func Test_webmentions(t *testing.T) { app := &goBlog{ - cfg: &config{ - Db: &configDb{ - File: filepath.Join(t.TempDir(), "test.db"), - }, - Server: &configServer{ - PublicAddress: "https://example.com", - }, - Blogs: map[string]*configBlog{ - "en": { - Lang: "en", - }, - }, - DefaultBlog: "en", - User: &configUser{}, + cfg: createDefaultTestConfig(t), + } + app.cfg.Server.PublicAddress = "https://example.com" + app.cfg.Blogs = map[string]*configBlog{ + "en": { + Lang: "en", }, } - _ = app.initDatabase(false) - defer app.db.close() + _ = app.initConfig(false) app.initComponents(false) _ = app.db.insertWebmention(&mention{