all repos — auth-boilerplate @ e32a2dfeddcff5b2677fdffb65af0a78b614f797

A simple Go web-app boilerplate.

main.go (view raw)

  1package main
  2
  3import (
  4	"context"
  5	"errors"
  6	"html/template"
  7	"log"
  8	"net/http"
  9	"os"
 10	"time"
 11
 12	"github.com/birabittoh/auth-boilerplate/auth"
 13	"github.com/birabittoh/auth-boilerplate/email"
 14	"github.com/birabittoh/myks"
 15	"github.com/glebarez/sqlite"
 16	"github.com/joho/godotenv"
 17	"gorm.io/gorm"
 18)
 19
 20type key int
 21
 22type User struct {
 23	gorm.Model
 24	Username     string
 25	Email        string
 26	PasswordHash string
 27	Salt         string
 28}
 29
 30var (
 31	db *gorm.DB
 32	g  *auth.Auth
 33	m  *email.Client
 34
 35	ks           = myks.New[uint](0)
 36	durationDay  = 24 * time.Hour
 37	durationWeek = 7 * durationDay
 38	templates    = template.Must(template.ParseGlob("templates/*.html"))
 39)
 40
 41const userContextKey key = 0
 42
 43func loadEmailConfig() *email.Client {
 44	address := os.Getenv("APP_SMTP_EMAIL")
 45	password := os.Getenv("APP_SMTP_PASSWORD")
 46	host := os.Getenv("APP_SMTP_HOST")
 47	port := os.Getenv("APP_SMTP_PORT")
 48
 49	if address == "" || password == "" || host == "" {
 50		log.Println("Missing email configuration.")
 51		return nil
 52	}
 53
 54	if port == "" {
 55		port = "587"
 56	}
 57
 58	return email.NewClient(address, password, host, port)
 59}
 60
 61func sendEmail(mail email.Email) error {
 62	if m == nil {
 63		return errors.New("email client is not initialized")
 64	}
 65	return m.Send(mail)
 66}
 67
 68func main() {
 69	err := godotenv.Load()
 70	if err != nil {
 71		log.Println("Error loading .env file")
 72	}
 73
 74	// Connessione al database SQLite
 75	db, err = gorm.Open(sqlite.Open("database.db"), &gorm.Config{})
 76	if err != nil {
 77		log.Fatal(err)
 78	}
 79
 80	// Creazione della tabella utenti
 81	db.AutoMigrate(&User{})
 82
 83	// Inizializzazione di gauth
 84	g = auth.NewAuth(os.Getenv("APP_PEPPER"))
 85	m = loadEmailConfig()
 86
 87	// Gestione delle route
 88	http.HandleFunc("GET /", loginRequired(examplePage))
 89	http.HandleFunc("GET /register", getRegisterHandler)
 90	http.HandleFunc("GET /login", getLoginHandler)
 91	http.HandleFunc("GET /reset-password", getResetPasswordHandler)
 92	http.HandleFunc("GET /reset-password-confirm", getResetPasswordConfirmHandler)
 93	http.HandleFunc("GET /logout", logoutHandler)
 94
 95	http.HandleFunc("POST /login", postLoginHandler)
 96	http.HandleFunc("POST /register", postRegisterHandler)
 97	http.HandleFunc("POST /reset-password", postResetPasswordHandler)
 98	http.HandleFunc("POST /reset-password-confirm", postResetPasswordConfirmHandler)
 99
100	port := ":8080"
101	log.Println("Server running on port " + port)
102	log.Fatal(http.ListenAndServe(port, nil))
103}
104
105// Middleware per controllare se l'utente รจ loggato.
106func loginRequired(next http.HandlerFunc) http.HandlerFunc {
107	return func(w http.ResponseWriter, r *http.Request) {
108		cookie, err := r.Cookie("session_token")
109		if err != nil {
110			http.Redirect(w, r, "/login", http.StatusFound)
111			return
112		}
113
114		userID, err := ks.Get(cookie.Value)
115		if err != nil {
116			http.Redirect(w, r, "/login", http.StatusFound)
117			return
118		}
119
120		ctx := context.WithValue(r.Context(), userContextKey, *userID)
121		next(w, r.WithContext(ctx))
122	}
123}
124
125func getLoggedUser(r *http.Request) (user User, ok bool) {
126	userID, ok := r.Context().Value(userContextKey).(uint)
127	db.Find(&user, userID)
128	return user, ok
129}