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

import (
gbe's avatar
gbe committed
	"context"
	"database/sql"
gbe's avatar
gbe committed
	"embed"
gbe's avatar
gbe committed
	"errors"
gbe's avatar
gbe committed
	"log"
	"net/http"
gbe's avatar
gbe committed

gbe's avatar
gbe committed
	"github.com/Masterminds/squirrel"
gbe's avatar
gbe committed
	"github.com/jmoiron/sqlx"
	_ "modernc.org/sqlite" // Imported for side effects: registers DB 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
type Handler struct {
	db *sqlx.DB
}

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()
	}

	log.Println(msg)

	http.Error(w, msg, status)
gbe's avatar
gbe committed
type authProvider struct {
	db *sqlx.DB
}

func (a authProvider) Valid(ctx context.Context, user, pass string) (bool, error) {
	query, args, err := squirrel.Select("password").
		From("users").
		Where(squirrel.Eq{"name": user}).
		ToSql()
	if err != nil {
		return false, err
	}

	var dbPass string
	err = a.db.GetContext(ctx, &dbPass, query, args...)
	if errors.Is(err, sql.ErrNoRows) {
		// User not found isn't an error, it's just an invalid auth.
		return false, nil
	}

	if err != nil {
		return false, err
	}
gbe's avatar
gbe committed
	if dbPass == pass {
		return true, nil
gbe's avatar
gbe committed
	return false, nil
}

func logRequest(r *http.Request) {
	log.Println("handling", r.Method, r.URL, "from", r.RemoteAddr, "by", auth.User(r))
}

gbe's avatar
gbe committed
func main() {
gbe's avatar
gbe committed
	db, err := sqlx.Open("sqlite", "vino.sqlite")
	if err != nil {
		log.Fatalln("can't open DB:", err)
	}
	defer db.Close()

	err = initDB(db)
	if err != nil {
		log.Fatalln("can't initialize DB:", err)
	}

	http.HandleFunc("/favicon.ico", http.NotFound)

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

gbe's avatar
gbe committed
	handler := Handler{
		db: db,
	}
gbe's avatar
gbe committed

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

	http.HandleFunc("/details/img", auth.Require(http.HandlerFunc(handler.img), ap))
	http.HandleFunc("/details/", auth.Require(http.HandlerFunc(handler.details), ap))
	http.HandleFunc("/", auth.Require(http.HandlerFunc(handler.index), ap))
gbe's avatar
gbe committed

gbe's avatar
gbe committed
	const listenAddr = ":7878"
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.Fatalln("http handler failed:", err)
gbe's avatar
gbe committed
	}
}