2024-10-16 04:34:57 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2024-11-11 19:55:01 +00:00
|
|
|
"errors"
|
2024-10-23 05:25:30 +00:00
|
|
|
"fmt"
|
2024-11-11 19:55:01 +00:00
|
|
|
"math"
|
2024-10-23 05:25:30 +00:00
|
|
|
"net/http"
|
2024-11-11 19:55:01 +00:00
|
|
|
"strconv"
|
|
|
|
"time"
|
2024-10-23 05:25:30 +00:00
|
|
|
|
2024-12-15 17:23:53 +00:00
|
|
|
"git.32bit.cafe/32bitcafe/guestbook/internal/models"
|
2024-11-11 19:55:01 +00:00
|
|
|
"github.com/gorilla/schema"
|
2024-10-16 04:34:57 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func (app *application) serverError(w http.ResponseWriter, r *http.Request, err error) {
|
|
|
|
var (
|
|
|
|
method = r.Method
|
|
|
|
uri = r.URL.RequestURI()
|
|
|
|
)
|
|
|
|
|
|
|
|
app.logger.Error(err.Error(), "method", method, "uri", uri)
|
|
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (app *application) clientError(w http.ResponseWriter, status int) {
|
|
|
|
http.Error(w, http.StatusText(status), status)
|
|
|
|
}
|
|
|
|
|
2024-12-15 17:23:53 +00:00
|
|
|
func (app *application) renderHTMX(w http.ResponseWriter, r *http.Request, status int, page string, data templateData) {
|
|
|
|
ts, ok := app.templateCacheHTMX[page]
|
|
|
|
if !ok {
|
|
|
|
err := fmt.Errorf("the template %s does not exist", page)
|
|
|
|
app.serverError(w, r, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
w.WriteHeader(status)
|
|
|
|
err := ts.Execute(w, data)
|
|
|
|
if err != nil {
|
|
|
|
app.serverError(w, r, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-16 04:34:57 +00:00
|
|
|
func (app *application) render(w http.ResponseWriter, r *http.Request, status int, page string, data templateData) {
|
|
|
|
ts, ok := app.templateCache[page]
|
|
|
|
if !ok {
|
|
|
|
err := fmt.Errorf("the template %s does not exist", page)
|
|
|
|
app.serverError(w, r, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
w.WriteHeader(status)
|
|
|
|
err := ts.ExecuteTemplate(w, "base", data)
|
|
|
|
if err != nil {
|
|
|
|
app.serverError(w, r, err)
|
|
|
|
}
|
|
|
|
}
|
2024-10-23 05:25:30 +00:00
|
|
|
|
2024-11-11 19:55:01 +00:00
|
|
|
func (app *application) nextSequence () uint16 {
|
|
|
|
val := app.sequence
|
|
|
|
if app.sequence == math.MaxUint16 {
|
|
|
|
app.sequence = 0
|
|
|
|
} else {
|
|
|
|
app.sequence += 1
|
|
|
|
}
|
|
|
|
return val
|
|
|
|
}
|
|
|
|
|
|
|
|
func (app *application) createShortId () uint64 {
|
|
|
|
now := time.Now().UTC()
|
|
|
|
epoch, err := time.Parse(time.RFC822Z, "01 Jan 20 00:00 -0000")
|
2024-10-23 05:25:30 +00:00
|
|
|
if err != nil {
|
2024-11-11 19:55:01 +00:00
|
|
|
fmt.Println(err)
|
|
|
|
return 0
|
2024-10-23 05:25:30 +00:00
|
|
|
}
|
2024-11-11 19:55:01 +00:00
|
|
|
d := now.Sub(epoch)
|
|
|
|
ms := d.Milliseconds()
|
|
|
|
seq := app.nextSequence()
|
|
|
|
return (uint64(ms) & 0x0FFFFFFFFFFFFFFF) | (uint64(seq) << 48)
|
|
|
|
}
|
|
|
|
|
|
|
|
func shortIdToSlug(id uint64) string {
|
|
|
|
slug := strconv.FormatUint(id, 36)
|
|
|
|
return slug
|
|
|
|
}
|
|
|
|
|
|
|
|
func slugToShortId(slug string) uint64 {
|
|
|
|
id, _ := strconv.ParseUint(slug, 36, 64)
|
|
|
|
return id
|
2024-10-23 05:25:30 +00:00
|
|
|
}
|
|
|
|
|
2024-11-11 19:55:01 +00:00
|
|
|
func (app *application) decodePostForm(r *http.Request, dst any) error {
|
|
|
|
err := r.ParseForm()
|
2024-10-23 05:25:30 +00:00
|
|
|
if err != nil {
|
2024-11-11 19:55:01 +00:00
|
|
|
return err
|
2024-10-23 05:25:30 +00:00
|
|
|
}
|
2024-11-11 19:55:01 +00:00
|
|
|
|
|
|
|
err = app.formDecoder.Decode(dst, r.PostForm)
|
2024-10-23 05:25:30 +00:00
|
|
|
if err != nil {
|
2024-11-11 19:55:01 +00:00
|
|
|
var multiErrors *schema.MultiError
|
|
|
|
if !errors.As(err, &multiErrors) {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (app *application) isAuthenticated(r *http.Request) bool {
|
|
|
|
isAuthenticated, ok := r.Context().Value(isAuthenticatedContextKey).(bool)
|
|
|
|
if !ok {
|
|
|
|
return false
|
2024-10-23 05:25:30 +00:00
|
|
|
}
|
2024-11-11 19:55:01 +00:00
|
|
|
return isAuthenticated
|
2024-10-23 05:25:30 +00:00
|
|
|
}
|
2024-12-15 17:23:53 +00:00
|
|
|
|
|
|
|
func (app *application) getCurrentUser(r *http.Request) *models.User {
|
|
|
|
if !app.isAuthenticated(r) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
user, ok := r.Context().Value(userNameContextKey).(models.User)
|
|
|
|
if !ok {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return &user
|
|
|
|
}
|