Fix direct access to note pages (#324)

* Initialize database

* Document change

* Test regression
This commit is contained in:
Sung Won Cho 2019-11-20 14:38:39 +08:00 committed by GitHub
commit 0bcd06600e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 145 additions and 5 deletions

View file

@ -10,6 +10,13 @@ All notable changes to the projects under this repository will be documented in
The following log documents the history of the server project.
### Unreleased
#### Fixed
- Fix server crash upon landing on a note page (#324).
- Allow to synchronize a large number of records (#321)
### 0.3.1 - 2019-11-12
#### Fixed

View file

@ -55,10 +55,11 @@ func mustFind(box *packr.Box, path string) []byte {
return b
}
func initContext() web.Context {
func initContext(db *gorm.DB) web.Context {
staticBox := packr.New("static", "../../web/public/static")
return web.Context{
DB: db,
IndexHTML: mustFind(rootBox, "index.html"),
RobotsTxt: mustFind(rootBox, "robots.txt"),
ServiceWorkerJs: mustFind(rootBox, "service-worker.js"),
@ -72,8 +73,11 @@ func initServer(app handlers.App) (*http.ServeMux, error) {
return nil, errors.Wrap(err, "initializing router")
}
webCtx := initContext()
webHandlers := web.Init(webCtx)
webCtx := initContext(app.DB)
webHandlers, err := web.Init(webCtx)
if err != nil {
return nil, errors.Wrap(err, "initializing web handlers")
}
mux := http.NewServeMux()
mux.Handle("/api/", http.StripPrefix("/api", apiRouter))

View file

@ -28,6 +28,19 @@ import (
"github.com/pkg/errors"
)
var (
// ErrEmptyDB is an error for missing database connection in the context
ErrEmptyDB = errors.New("No database connection was provided")
// ErrEmptyIndexHTML is an error for missing index.html content in the context
ErrEmptyIndexHTML = errors.New("No index.html content was provided")
// ErrEmptyRobotsTxt is an error for missing robots.txt content in the context
ErrEmptyRobotsTxt = errors.New("No robots.txt content was provided")
// ErrEmptyServiceWorkerJS is an error for missing service worker content in the context
ErrEmptyServiceWorkerJS = errors.New("No service-worker.js content was provided")
// ErrEmptyStaticFileSystem is an error for missing static filesystem in the context
ErrEmptyStaticFileSystem = errors.New("No static filesystem was provided")
)
// Context contains contents of web assets
type Context struct {
DB *gorm.DB
@ -45,14 +58,38 @@ type Handlers struct {
GetStatic http.Handler
}
func validateContext(c Context) error {
if c.DB == nil {
return ErrEmptyDB
}
if c.IndexHTML == nil {
return ErrEmptyIndexHTML
}
if c.RobotsTxt == nil {
return ErrEmptyRobotsTxt
}
if c.ServiceWorkerJs == nil {
return ErrEmptyServiceWorkerJS
}
if c.StaticFileSystem == nil {
return ErrEmptyStaticFileSystem
}
return nil
}
// Init initializes the handlers
func Init(c Context) Handlers {
func Init(c Context) (Handlers, error) {
if err := validateContext(c); err != nil {
return Handlers{}, errors.Wrap(err, "validating context")
}
return Handlers{
GetRoot: getRootHandler(c),
GetRobots: getRobotsHandler(c),
GetServiceWorker: getSWHandler(c),
GetStatic: getStaticHandler(c),
}
}, nil
}
// getRootHandler returns an HTTP handler that serves the app shell

View file

@ -0,0 +1,92 @@
package web
import (
"fmt"
"net/http"
"testing"
"github.com/dnote/dnote/pkg/assert"
"github.com/jinzhu/gorm"
"github.com/pkg/errors"
)
func TestInit(t *testing.T) {
mockIndexHTML := []byte("<html></html>")
mockRobotsTxt := []byte("Allow: *")
mockServiceWorkerJs := []byte("function() {}")
mockStaticFileSystem := http.Dir(".")
testCases := []struct {
ctx Context
expectedErr error
}{
{
ctx: Context{
DB: &gorm.DB{},
IndexHTML: mockIndexHTML,
RobotsTxt: mockRobotsTxt,
ServiceWorkerJs: mockServiceWorkerJs,
StaticFileSystem: mockStaticFileSystem,
},
expectedErr: nil,
},
{
ctx: Context{
DB: nil,
IndexHTML: mockIndexHTML,
RobotsTxt: mockRobotsTxt,
ServiceWorkerJs: mockServiceWorkerJs,
StaticFileSystem: mockStaticFileSystem,
},
expectedErr: ErrEmptyDB,
},
{
ctx: Context{
DB: &gorm.DB{},
IndexHTML: nil,
RobotsTxt: mockRobotsTxt,
ServiceWorkerJs: mockServiceWorkerJs,
StaticFileSystem: mockStaticFileSystem,
},
expectedErr: ErrEmptyIndexHTML,
},
{
ctx: Context{
DB: &gorm.DB{},
IndexHTML: mockIndexHTML,
RobotsTxt: nil,
ServiceWorkerJs: mockServiceWorkerJs,
StaticFileSystem: mockStaticFileSystem,
},
expectedErr: ErrEmptyRobotsTxt,
},
{
ctx: Context{
DB: &gorm.DB{},
IndexHTML: mockIndexHTML,
RobotsTxt: mockRobotsTxt,
ServiceWorkerJs: nil,
StaticFileSystem: mockStaticFileSystem,
},
expectedErr: ErrEmptyServiceWorkerJS,
},
{
ctx: Context{
DB: &gorm.DB{},
IndexHTML: mockIndexHTML,
RobotsTxt: mockRobotsTxt,
ServiceWorkerJs: mockServiceWorkerJs,
StaticFileSystem: nil,
},
expectedErr: ErrEmptyStaticFileSystem,
},
}
for idx, tc := range testCases {
t.Run(fmt.Sprintf("test case %d", idx), func(t *testing.T) {
_, err := Init(tc.ctx)
assert.Equal(t, errors.Cause(err), tc.expectedErr, "error mismatch")
})
}
}