Skip to content
Snippets Groups Projects
main.go 3.18 KiB
Newer Older
gbe's avatar
gbe committed
package main

import (
gbe's avatar
gbe committed
	"embed"
	"flag"
gbe's avatar
gbe committed
	"net/http"
gbe's avatar
gbe committed

	"github.com/jmoiron/sqlx"
gbe's avatar
gbe committed
	log "github.com/sirupsen/logrus"
	bolt "go.etcd.io/bbolt"
	"modernc.org/ql"
	_ "modernc.org/ql/driver"

	"git.c3pb.de/gbe/invinoveritas/auth"
gbe's avatar
gbe committed
)

//go:embed templates/*.tpl
var templateFS embed.FS

//go:embed static/*
var staticFS embed.FS

gbe's avatar
gbe committed
func httpError(w http.ResponseWriter, msg string, err error, status int) {
gbe's avatar
gbe committed
	if err != nil {
		msg += ": " + err.Error()
	}

gbe's avatar
gbe committed
	log.WithField("status", status).
		WithError(err).
		Error(msg)
gbe's avatar
gbe committed

	http.Error(w, msg, status)
gbe's avatar
gbe committed
type Handler struct {
gbe's avatar
gbe committed
	sqlDB *sqlx.DB
	ap    authProvider
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)

gbe's avatar
gbe committed
			log.WithFields(log.Fields{
				"method":   r.Method,
				"url":      r.URL,
				"remote":   r.RemoteAddr,
				"duration": d,
				"auth":     auth.Get(r),
			}).Info("handling request")
		}()

		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
	}

gbe's avatar
gbe committed
	log.Info("running test-select on db")
	_, 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
}

gbe's avatar
gbe committed
func main() {
gbe's avatar
gbe committed
	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")
	flag.Parse()

	sqlDB, err := openQLdb(*dbPath)
	if err != nil {
gbe's avatar
gbe committed
		log.WithError(err).Fatalln("can't open DB:")
	}
	defer sqlDB.Close()

	db, err := bolt.Open(*dbPath+".db", 0644, nil)
gbe's avatar
gbe committed
	if err != nil {
gbe's avatar
gbe committed
		log.WithError(err).Fatalln("can't open DB")
gbe's avatar
gbe committed
	}
	defer db.Close()

	err = initSQLdb(context.TODO(), sqlDB)
	if err != nil {
gbe's avatar
gbe committed
		log.WithField("wal_name", ql.WalName(*dbPath+".ql")).
			WithError(err).
			Fatalln("can't initalize DB")
gbe's avatar
gbe committed
	if err != nil {
gbe's avatar
gbe committed
		log.WithError(err).Fatalln("can't initialize DB")
	err = migrateBoltToQL(context.TODO(), db, sqlDB)
	if err != nil {
gbe's avatar
gbe committed
		log.WithError(err).Fatalln("can't migrate bolt to sql db")
	http.HandleFunc("/favicon.ico", http.NotFound)

	http.Handle("/static/", logRequest(http.FileServer(http.FS(staticFS))))
gbe's avatar
gbe committed

gbe's avatar
gbe committed
	ap := authProvider{
gbe's avatar
gbe committed
	}
gbe's avatar
gbe committed

gbe's avatar
gbe committed
	handler := Handler{
gbe's avatar
gbe committed
		sqlDB: sqlDB,
		ap:    ap,
gbe's avatar
gbe committed
	}
	http.Handle("/details/img", auth.Require(logRequest(handler.img()), ap))
	http.Handle("/details/", auth.Require(logRequest(handler.details()), ap))
	http.Handle("/user/", auth.Require(logRequest(handler.user()), ap))
	http.Handle("/", auth.Require(logRequest(handler.index()), ap))
gbe's avatar
gbe committed

	log.Printf("here we go, listening on http://%s", *listenAddr)
gbe's avatar
gbe committed

	err = http.ListenAndServe(*listenAddr, nil)
gbe's avatar
gbe committed
	if err != nil {
gbe's avatar
gbe committed
		log.WithError(err).Fatalln("http handler failed")
gbe's avatar
gbe committed
	}
}