Newer
Older
"github.com/jmoiron/sqlx"
"modernc.org/ql"
_ "modernc.org/ql/driver"
)
//go:embed templates/*.tpl
var templateFS embed.FS
//go:embed static/*
var staticFS embed.FS
func httpError(w http.ResponseWriter, msg string, err error, status int) {
log.WithField("status", status).
WithError(err).
Error(msg)
type sessionProvider interface {
ListSessions(context.Context) ([]session.Info, error)
DeleteSession(ctx context.Context, token string) error
}
type userProvider interface {
ListUsers(context.Context) ([]string, error)
CreateUser(ctx context.Context, name string) (string, error)
DeleteUser(ctx context.Context, name string) error
UpdatePassword(ctx context.Context, name string, oldPW, newPW string) error
}
sp sessionProvider
up userProvider
func logRequest(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
defer func() {
d := time.Since(start)
remote := r.Header.Get("X-Forwarded-For")
if remote == "" {
remote = r.RemoteAddr
}
log.WithFields(log.Fields{
"method": r.Method,
"url": r.URL,
"remote": r.RemoteAddr,
"duration": d,
"auth": auth.Get(r),
}).Info("handling request")
func addCacheHeaders(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Cache-Control", "public, max-age=86400, immutable")
next.ServeHTTP(w, r)
})
}
func openQLdb(path string) (*sqlx.DB, error) {
var retried bool
path += ".ql"
retry:
db, err := sqlx.Open("ql2", path)
if err != nil {
return nil, err
}
_, err = db.Exec(`SELECT count(*) FROM __Table`)
if err != nil && !retried {
log.Println("got err:", err)
retried = true
// WAL may be corrupted. Manually remove it and re-try open. See
// https://gitlab.com/cznic/ql/-/issues/227 for more info.
err := os.Remove(ql.WalName(path))
if err != nil {
return nil, err
}
goto retry
}
if err != nil {
return nil, err
}
return db, nil
}
formatter := log.TextFormatter{
DisableColors: true,
}
log.StandardLogger().Formatter = &formatter
dbPath := flag.String("db", "vino", "Path to database file")
listenAddr := flag.String("listen", "127.0.0.1:7878", "Listening address")
debug := flag.Bool("debug", false, "Enable debug logging")
if *debug {
log.SetLevel(log.DebugLevel)
}
log.WithField("wal_name", ql.WalName(*dbPath+".ql")).
WithError(err).
Fatalln("can't initalize DB")
http.HandleFunc("/favicon.ico", http.NotFound)
http.Handle("/static/", logRequest(addCacheHeaders(http.FileServer(http.FS(staticFS)))))
sessions := session.Provider{
sp: sessions,
up: sessions,
http.Handle("/details/img/", auth.Require(logRequest(addCacheHeaders(handler.img())), sessions.Handler(templateFS), sessions))
http.Handle("/details/", auth.Require(logRequest(handler.details()), sessions.Handler(templateFS), sessions))
http.Handle("/user/", auth.Require(logRequest(handler.user()), sessions.Handler(templateFS), sessions))
http.Handle("/", auth.Require(logRequest(handler.index()), sessions.Handler(templateFS), sessions))
log.Printf("here we go, listening on http://%s", *listenAddr)
err = http.ListenAndServe(*listenAddr, nil)