mysql db for session storage
This commit is contained in:
parent
d9301099c6
commit
a6d99c0ccc
@ -78,7 +78,9 @@ func DefaultBookmarks() []Bookmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Bookmark struct {
|
type Bookmark struct {
|
||||||
Title string `json:"title"`
|
SessionID string `json:"-"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
|
||||||
Image string `json:"image"`
|
Image string `json:"image"`
|
||||||
ImageSize string `json:"image_size"`
|
ImageSize string `json:"image_size"`
|
||||||
IconPadding string `json:"icon_padding"`
|
IconPadding string `json:"icon_padding"`
|
||||||
|
90
db.go
Normal file
90
db.go
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.milar.in/milarin/advsql"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Database = &advsql.Database{}
|
||||||
|
|
||||||
|
var (
|
||||||
|
InsertSession = advsql.Insert(Database, "INSERT INTO sessions VALUES (?, ?, ?)", ScanSessionPkFirst)
|
||||||
|
UpdateSession = advsql.Update(Database, "UPDATE sessions SET expiration_date = ?, creation_date = ? WHERE id = ?", ScanSessionPkLast)
|
||||||
|
GetSessionByID = advsql.QueryOne(Database, "SELECT * FROM sessions WHERE id = ?", ScanSessionPkFirst)
|
||||||
|
|
||||||
|
InsertBookmark = advsql.Insert(Database, "INSERT INTO bookmarks VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", ScanBookmarkPkFirst)
|
||||||
|
UpdateBookmark = advsql.Update(Database, "UPDATE bookmarks SET link = ?, image = ?, color = ?, image_size = ?, icon_padding = ?, hide_border = ?, order_priority = ? WHERE session_id = ? AND title = ?", ScanBookmarkPkLast)
|
||||||
|
GetBookmarkBySessionIDAndTitle = advsql.QueryOne(Database, "SELECT * FROM bookmarks WHERE session_id = ? AND title = ?", ScanBookmarkPkFirst)
|
||||||
|
GetBookmarksBySessionIdOrdered = advsql.QueryMany(Database, "SELECT * FROM bookmarks WHERE session_id = ? ORDER BY order_priority", ScanBookmarkPkFirst)
|
||||||
|
DeleteBookmarksBySessionID = advsql.Delete(Database, "DELETE FROM bookmarks WHERE session_id = ?")
|
||||||
|
|
||||||
|
InsertSettings = advsql.Insert(Database, "INSERT INTO settings VALUES (?, ?, ?, ?, ?)", ScanSettingsPkFirst)
|
||||||
|
UpdateSettings = advsql.Update(Database, "UPDATE settings SET background_color = ?, foreground_color = ?, search_query = ?, border_radius = ? WHERE session_id = ?", ScanSettingsPkLast)
|
||||||
|
GetSettingsBySessionID = advsql.QueryOne(Database, "SELECT * FROM settings WHERE session_id = ?", ScanSettingsPkFirst)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Session struct {
|
||||||
|
ID string
|
||||||
|
|
||||||
|
ExpirationDate time.Time
|
||||||
|
CreationDate time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScanSessionPkFirst(u *Session, encode advsql.ScanFunc) error {
|
||||||
|
return encode(&u.ID, &u.ExpirationDate, &u.CreationDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScanSessionPkLast(u *Session, encode advsql.ScanFunc) error {
|
||||||
|
return encode(&u.ExpirationDate, &u.CreationDate, &u.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSession() (*Session, error) {
|
||||||
|
id, err := generateRandomID(32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Session{
|
||||||
|
ID: id,
|
||||||
|
|
||||||
|
CreationDate: time.Now(),
|
||||||
|
ExpirationDate: time.Now().AddDate(1, 0, 0),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScanBookmarkPkFirst(u *Bookmark, encode advsql.ScanFunc) error {
|
||||||
|
return encode(
|
||||||
|
&u.SessionID,
|
||||||
|
&u.Title,
|
||||||
|
&u.Link,
|
||||||
|
&u.Image,
|
||||||
|
&u.Color,
|
||||||
|
&u.ImageSize,
|
||||||
|
&u.IconPadding,
|
||||||
|
&u.HideBorder,
|
||||||
|
&u.Order,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScanBookmarkPkLast(u *Bookmark, encode advsql.ScanFunc) error {
|
||||||
|
return encode(
|
||||||
|
&u.Link,
|
||||||
|
&u.Image,
|
||||||
|
&u.Color,
|
||||||
|
&u.ImageSize,
|
||||||
|
&u.IconPadding,
|
||||||
|
&u.HideBorder,
|
||||||
|
&u.Order,
|
||||||
|
&u.SessionID,
|
||||||
|
&u.Title,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScanSettingsPkFirst(u *Settings, encode advsql.ScanFunc) error {
|
||||||
|
return encode(&u.SessionID, &u.Background, &u.Foreground, &u.Search, &u.BorderRadius)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScanSettingsPkLast(u *Settings, encode advsql.ScanFunc) error {
|
||||||
|
return encode(&u.Background, &u.Foreground, &u.Search, &u.BorderRadius, &u.SessionID)
|
||||||
|
}
|
10
go.mod
10
go.mod
@ -3,15 +3,11 @@ module git.milar.in/milarin/startpage
|
|||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
git.milar.in/milarin/advsql v0.0.16
|
||||||
|
git.milar.in/milarin/channel v0.0.10
|
||||||
git.milar.in/milarin/envvars/v2 v2.0.0
|
git.milar.in/milarin/envvars/v2 v2.0.0
|
||||||
git.milar.in/milarin/slices v0.0.4
|
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/gorilla/sessions v1.2.1
|
|
||||||
github.com/srinathgs/mysqlstore v0.0.0-20200417050510-9cbb9420fc4c
|
|
||||||
golang.org/x/text v0.3.7
|
golang.org/x/text v0.3.7
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
|
||||||
github.com/gorilla/securecookie v1.1.1 // indirect
|
|
||||||
)
|
|
||||||
|
12
go.sum
12
go.sum
@ -1,16 +1,12 @@
|
|||||||
|
git.milar.in/milarin/advsql v0.0.16 h1:vPGPM4Vyb8aR8qcj479JXpC+MlUjeFsPZ6CUIoKkC+I=
|
||||||
|
git.milar.in/milarin/advsql v0.0.16/go.mod h1:bdQrtqZaGkxmbYRi2OhF5T8DDDztnvbE41faIVSZPLQ=
|
||||||
|
git.milar.in/milarin/channel v0.0.10 h1:oHCx69lMF/KIot38OgfVtZ9oBmv5FadZp2MMDPPnC3o=
|
||||||
|
git.milar.in/milarin/channel v0.0.10/go.mod h1:We83LTI8S7u7II3pD+A2ChCDWJfCkcBUCUqii9HjTtM=
|
||||||
git.milar.in/milarin/envvars/v2 v2.0.0 h1:DWRQCWaHqzDD8NGpSgv5tYLuF9A/dVFPAtTvz3oiIqE=
|
git.milar.in/milarin/envvars/v2 v2.0.0 h1:DWRQCWaHqzDD8NGpSgv5tYLuF9A/dVFPAtTvz3oiIqE=
|
||||||
git.milar.in/milarin/envvars/v2 v2.0.0/go.mod h1:HkdEi+gG2lJSmVq547bTlQV4qQ0hO333bE8IrE0B9yY=
|
git.milar.in/milarin/envvars/v2 v2.0.0/go.mod h1:HkdEi+gG2lJSmVq547bTlQV4qQ0hO333bE8IrE0B9yY=
|
||||||
git.milar.in/milarin/slices v0.0.4 h1:z92jgsKcnLPLfgXkTVCzH2XXesfXzhe0Osx+PkfCHVI=
|
|
||||||
git.milar.in/milarin/slices v0.0.4/go.mod h1:NOr53AOeur/qscu/FBj3lsFR262PNYBccLYSTCAXRk4=
|
|
||||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
|
||||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
|
||||||
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
|
|
||||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
|
||||||
github.com/srinathgs/mysqlstore v0.0.0-20200417050510-9cbb9420fc4c h1:HT6QRF79dL2Ed6HCrX9RufkxFGo7+NPkgYF1Uzvv/js=
|
|
||||||
github.com/srinathgs/mysqlstore v0.0.0-20200417050510-9cbb9420fc4c/go.mod h1:kt46Hd+lF0rtpeRgOvYSWYJItOAd73EKkIBZFbX7TXs=
|
|
||||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
137
main.go
137
main.go
@ -2,31 +2,20 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"encoding/gob"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
|
||||||
|
"git.milar.in/milarin/advsql"
|
||||||
|
"git.milar.in/milarin/channel"
|
||||||
"git.milar.in/milarin/envvars/v2"
|
"git.milar.in/milarin/envvars/v2"
|
||||||
"git.milar.in/milarin/slices"
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/srinathgs/mysqlstore"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
intf = flag.String("i", "", "interface")
|
|
||||||
port = flag.Uint("p", 80, "port")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -37,28 +26,18 @@ var (
|
|||||||
StaticFS embed.FS
|
StaticFS embed.FS
|
||||||
|
|
||||||
Templates *template.Template
|
Templates *template.Template
|
||||||
|
|
||||||
SessionStore = Must(mysqlstore.NewMySQLStore(
|
|
||||||
fmt.Sprintf(
|
|
||||||
"%s:%s@tcp(%s:%d)/%s?parseTime=true&loc=Local",
|
|
||||||
envvars.String("DB_USER", ""),
|
|
||||||
envvars.String("DB_PASS", ""),
|
|
||||||
envvars.String("DB_HOST", ""),
|
|
||||||
envvars.Uint16("DB_PORT", 3306),
|
|
||||||
envvars.String("DB_BASE", "startpage"),
|
|
||||||
),
|
|
||||||
"sessions",
|
|
||||||
"/",
|
|
||||||
int((time.Hour * 24 * 365).Seconds()),
|
|
||||||
Must(hex.DecodeString(os.Getenv("SESSION_KEY"))),
|
|
||||||
))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
gob.Register([]Bookmark{})
|
advsql.InitMysqlDatabase(
|
||||||
gob.Register(&Settings{})
|
Database,
|
||||||
|
envvars.String("DB_HOST", ""),
|
||||||
flag.Parse()
|
envvars.Uint16("DB_PORT", 3306),
|
||||||
|
envvars.String("DB_USER", ""),
|
||||||
|
envvars.String("DB_PASS", ""),
|
||||||
|
envvars.String("DB_BASE", "startpage"),
|
||||||
|
)
|
||||||
|
defer Database.Close()
|
||||||
|
|
||||||
if tmpl, err := template.New("homepage").ParseFS(TemplateFS, "templates/*"); err == nil {
|
if tmpl, err := template.New("homepage").ParseFS(TemplateFS, "templates/*"); err == nil {
|
||||||
Templates = tmpl
|
Templates = tmpl
|
||||||
@ -73,18 +52,23 @@ func main() {
|
|||||||
r.HandleFunc("/search", search)
|
r.HandleFunc("/search", search)
|
||||||
r.PathPrefix("/static/").Handler(http.FileServer(http.FS(StaticFS)))
|
r.PathPrefix("/static/").Handler(http.FileServer(http.FS(StaticFS)))
|
||||||
|
|
||||||
if err := http.ListenAndServe(fmt.Sprintf("%s:%d", *intf, *port), r); err != nil {
|
if err := http.ListenAndServe(fmt.Sprintf("%s:%d", envvars.String("HTTP_INTF", ""), envvars.Uint16("HTTP_PORT", 80)), r); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handler(w http.ResponseWriter, r *http.Request) {
|
func handler(w http.ResponseWriter, r *http.Request) {
|
||||||
session, _ := SessionStore.Get(r, "settings")
|
session, err := GetSession(w, r)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
data := &TmplData{
|
data := &TmplData{
|
||||||
text: GetText(r),
|
text: GetText(r),
|
||||||
Bookmarks: GetValueDefault(session, "bookmarks", DefaultBookmarks()),
|
Bookmarks: channel.ToSliceDeref(GetBookmarksBySessionIdOrdered(session.ID)),
|
||||||
Settings: GetValueDefault(session, "settings", DefaultSettings()),
|
Settings: GetSettingsBySessionID(session.ID),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := Templates.ExecuteTemplate(w, "index.html", data); err != nil {
|
if err := Templates.ExecuteTemplate(w, "index.html", data); err != nil {
|
||||||
@ -92,23 +76,14 @@ func handler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProvideFile(path, contentType string) http.HandlerFunc {
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
file, err := StaticFS.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
w.Header().Add("Content-Type", contentType)
|
|
||||||
io.Copy(w, file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func search(w http.ResponseWriter, r *http.Request) {
|
func search(w http.ResponseWriter, r *http.Request) {
|
||||||
session, _ := SessionStore.Get(r, "settings")
|
session, err := GetSession(w, r)
|
||||||
settings := GetValueDefault(session, "settings", DefaultSettings())
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
settings := GetSettingsBySessionID(session.ID)
|
||||||
|
|
||||||
if err := r.ParseForm(); err != nil {
|
if err := r.ParseForm(); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@ -131,21 +106,24 @@ func search(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func customize(w http.ResponseWriter, r *http.Request) {
|
func customize(w http.ResponseWriter, r *http.Request) {
|
||||||
session, _ := SessionStore.Get(r, "settings")
|
session, err := GetSession(w, r)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
text := GetText(r)
|
text := GetText(r)
|
||||||
|
|
||||||
bookmarks := slices.Map(GetValueDefault(session, "bookmarks", DefaultBookmarks()), func(b Bookmark) BookmarkData {
|
|
||||||
return BookmarkData{
|
|
||||||
Bookmark: &b,
|
|
||||||
text: text,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
data := &CustomizeData{
|
data := &CustomizeData{
|
||||||
text: text,
|
text: text,
|
||||||
Bookmarks: bookmarks,
|
Settings: GetSettingsBySessionID(session.ID),
|
||||||
Settings: GetValueDefault(session, "settings", DefaultSettings()),
|
Bookmarks: channel.ToSliceDeref(channel.MapSuccessive(GetBookmarksBySessionIdOrdered(session.ID), func(b *Bookmark) *BookmarkData {
|
||||||
|
return &BookmarkData{
|
||||||
|
Bookmark: b,
|
||||||
|
text: text,
|
||||||
|
}
|
||||||
|
})),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := Templates.ExecuteTemplate(w, "customize.html", data); err != nil {
|
if err := Templates.ExecuteTemplate(w, "customize.html", data); err != nil {
|
||||||
@ -159,21 +137,38 @@ func saveChanges(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
session, _ := SessionStore.Get(r, "settings")
|
session, err := GetSession(w, r)
|
||||||
|
|
||||||
sessionData := &SessionData{}
|
|
||||||
err := json.NewDecoder(r.Body).Decode(&sessionData)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Reorder(sessionData.Bookmarks)
|
sessionData := &SessionData{}
|
||||||
session.Values["bookmarks"] = sessionData.Bookmarks
|
err = json.NewDecoder(r.Body).Decode(&sessionData)
|
||||||
session.Values["settings"] = sessionData.Settings
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err := session.Save(r, w); err != nil {
|
Reorder(sessionData.Bookmarks)
|
||||||
|
if err := DeleteBookmarksBySessionID(session.ID); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, bookmark := range sessionData.Bookmarks {
|
||||||
|
bookmark.SessionID = session.ID
|
||||||
|
if err := InsertBookmark(&bookmark); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionData.Settings.SessionID = session.ID
|
||||||
|
if err := UpdateSettings(sessionData.Settings); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
type Settings struct {
|
type Settings struct {
|
||||||
|
SessionID string `json:"-"`
|
||||||
|
|
||||||
Background string `json:"background_color"`
|
Background string `json:"background_color"`
|
||||||
Foreground string `json:"foreground_color"`
|
Foreground string `json:"foreground_color"`
|
||||||
Search string `json:"search_query"`
|
Search string `json:"search_query"`
|
||||||
|
@ -16,6 +16,12 @@
|
|||||||
background-color: {{ .Settings.Background }};
|
background-color: {{ .Settings.Background }};
|
||||||
color: {{ .Settings.Foreground }};
|
color: {{ .Settings.Foreground }};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{{ if not .Settings.Search }}
|
||||||
|
#search {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
85
utils.go
85
utils.go
@ -1,7 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gorilla/sessions"
|
crand "crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Must[T any](value T, err error) T {
|
func Must[T any](value T, err error) T {
|
||||||
@ -11,25 +14,73 @@ func Must[T any](value T, err error) T {
|
|||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetValue[K any, T any](session *sessions.Session, key K) (T, bool) {
|
func generateRandomID(length int) (string, error) {
|
||||||
value, ok := session.Values[key]
|
data := make([]byte, 32)
|
||||||
if !ok && value == nil {
|
if _, err := crand.Read(data); err != nil {
|
||||||
return *new(T), false
|
return "", err
|
||||||
}
|
}
|
||||||
|
return hex.EncodeToString(data), nil
|
||||||
castedValue, ok := value.(T)
|
|
||||||
if !ok {
|
|
||||||
return *new(T), false
|
|
||||||
}
|
|
||||||
|
|
||||||
return castedValue, true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetValueDefault[K any, T any](session *sessions.Session, key K, defaultValue T) T {
|
func GetSession(w http.ResponseWriter, r *http.Request) (*Session, error) {
|
||||||
v, ok := GetValue[K, T](session, key)
|
cookie, err := r.Cookie("session")
|
||||||
if !ok {
|
if err != nil {
|
||||||
return defaultValue
|
return makeNewSession(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
return v
|
session := GetSessionByID(cookie.Value)
|
||||||
|
if session == nil {
|
||||||
|
return makeNewSession(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// update cookie expiration date
|
||||||
|
session.ExpirationDate = time.Now().AddDate(1, 0, 0)
|
||||||
|
if err := UpdateSession(session); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
http.SetCookie(w, &http.Cookie{
|
||||||
|
Name: "session",
|
||||||
|
Value: session.ID,
|
||||||
|
Expires: session.ExpirationDate,
|
||||||
|
Secure: true,
|
||||||
|
HttpOnly: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
return session, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeNewSession(w http.ResponseWriter) (*Session, error) {
|
||||||
|
session, err := NewSession()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := InsertSession(session); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert default bookmarks
|
||||||
|
for _, bookmark := range DefaultBookmarks() {
|
||||||
|
bookmark.SessionID = session.ID
|
||||||
|
if err := InsertBookmark(&bookmark); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert default settings
|
||||||
|
settings := DefaultSettings()
|
||||||
|
settings.SessionID = session.ID
|
||||||
|
if err := InsertSettings(settings); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
http.SetCookie(w, &http.Cookie{
|
||||||
|
Name: "session",
|
||||||
|
Value: session.ID,
|
||||||
|
Expires: session.ExpirationDate,
|
||||||
|
Secure: true,
|
||||||
|
HttpOnly: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
return session, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user