summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/start.go6
-rw-r--r--internal/handlers/auth.go297
-rw-r--r--internal/handlers/main.go3
-rw-r--r--internal/handlers/middleware.go137
-rw-r--r--internal/server/router.go9
-rw-r--r--pkg/cache/interface.go9
-rw-r--r--pkg/cache/main.go146
7 files changed, 222 insertions, 385 deletions
diff --git a/cmd/start.go b/cmd/start.go
index af46d79..429ed8c 100644
--- a/cmd/start.go
+++ b/cmd/start.go
@@ -2,11 +2,9 @@ package cmd
import (
"demoon/config"
- "demoon/internal/crons"
"demoon/internal/database/repos"
database "demoon/internal/database/sql"
"demoon/internal/server"
- "context"
"os"
"log/slog"
@@ -39,8 +37,8 @@ var startCmd = &cobra.Command{
}
repo := repos.NewProvider(db.Conn)
srv := server.NewServer(cfg, log, repo)
- cron := crons.NewCron(context.Background(), repo)
- cron.StartCronJobs()
+ // cron := crons.NewCron(context.Background(), repo)
+ // cron.StartCronJobs()
// listen for new messages
srv.Listen()
},
diff --git a/internal/handlers/auth.go b/internal/handlers/auth.go
index d0ccdff..cdd55d3 100644
--- a/internal/handlers/auth.go
+++ b/internal/handlers/auth.go
@@ -1,162 +1,167 @@
package handlers
import (
- "crypto/hmac"
- "crypto/sha256"
- "demoon/internal/models"
- "demoon/pkg/utils"
- "encoding/base64"
- "encoding/json"
"html/template"
"net/http"
- "strings"
- "time"
-
- "golang.org/x/crypto/bcrypt"
)
+// import (
+// "crypto/hmac"
+// "crypto/sha256"
+// "demoon/internal/models"
+// "demoon/pkg/utils"
+// "encoding/base64"
+// "encoding/json"
+// "html/template"
+// "net/http"
+// "strings"
+// "time"
+
+// "golang.org/x/crypto/bcrypt"
+// )
+
func abortWithError(w http.ResponseWriter, msg string) {
tmpl := template.Must(template.ParseGlob("components/*.html"))
tmpl.ExecuteTemplate(w, "error", msg)
}
-func (h *Handlers) HandleSignup(w http.ResponseWriter, r *http.Request) {
- r.ParseForm()
- username := r.PostFormValue("username")
- if username == "" {
- msg := "username not provided"
- h.log.Error(msg)
- abortWithError(w, msg)
- return
- }
- password := r.PostFormValue("password")
- if password == "" {
- msg := "password not provided"
- h.log.Error(msg)
- abortWithError(w, msg)
- return
- }
- // make sure username does not exists
- cleanName := utils.RemoveSpacesFromStr(username)
- hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), 8)
- // create user in db
- now := time.Now()
- nextMidnight := time.Date(now.Year(), now.Month(), now.Day(),
- 0, 0, 0, 0, time.UTC).Add(time.Hour * 24)
- newUser := &models.UserScore{
- Username: cleanName, Password: string(hashedPassword),
- BurnTime: nextMidnight, CreatedAt: now,
- }
- // login user
- cookie, err := h.makeCookie(cleanName, r.RemoteAddr)
- if err != nil {
- h.log.Error("failed to login", "error", err)
- abortWithError(w, err.Error())
- return
- }
- http.SetCookie(w, cookie)
- // http.Redirect(w, r, "/", 302)
- tmpl, err := template.ParseGlob("components/*.html")
- if err != nil {
- abortWithError(w, err.Error())
- return
- }
- tmpl.ExecuteTemplate(w, "main", newUser)
-}
+// func (h *Handlers) HandleSignup(w http.ResponseWriter, r *http.Request) {
+// r.ParseForm()
+// username := r.PostFormValue("username")
+// if username == "" {
+// msg := "username not provided"
+// h.log.Error(msg)
+// abortWithError(w, msg)
+// return
+// }
+// password := r.PostFormValue("password")
+// if password == "" {
+// msg := "password not provided"
+// h.log.Error(msg)
+// abortWithError(w, msg)
+// return
+// }
+// // make sure username does not exists
+// cleanName := utils.RemoveSpacesFromStr(username)
+// hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), 8)
+// // create user in db
+// now := time.Now()
+// nextMidnight := time.Date(now.Year(), now.Month(), now.Day(),
+// 0, 0, 0, 0, time.UTC).Add(time.Hour * 24)
+// newUser := &models.UserScore{
+// Username: cleanName, Password: string(hashedPassword),
+// BurnTime: nextMidnight, CreatedAt: now,
+// }
+// // login user
+// cookie, err := h.makeCookie(cleanName, r.RemoteAddr)
+// if err != nil {
+// h.log.Error("failed to login", "error", err)
+// abortWithError(w, err.Error())
+// return
+// }
+// http.SetCookie(w, cookie)
+// // http.Redirect(w, r, "/", 302)
+// tmpl, err := template.ParseGlob("components/*.html")
+// if err != nil {
+// abortWithError(w, err.Error())
+// return
+// }
+// tmpl.ExecuteTemplate(w, "main", newUser)
+// }
-func (h *Handlers) HandleLogin(w http.ResponseWriter, r *http.Request) {
- r.ParseForm()
- username := r.PostFormValue("username")
- if username == "" {
- msg := "username not provided"
- h.log.Error(msg)
- abortWithError(w, msg)
- return
- }
- password := r.PostFormValue("password")
- if password == "" {
- msg := "password not provided"
- h.log.Error(msg)
- abortWithError(w, msg)
- return
- }
- cleanName := utils.RemoveSpacesFromStr(username)
- tmpl, err := template.ParseGlob("components/*.html")
- if err != nil {
- abortWithError(w, err.Error())
- return
- }
- cookie, err := h.makeCookie(cleanName, r.RemoteAddr)
- if err != nil {
- h.log.Error("failed to login", "error", err)
- abortWithError(w, err.Error())
- return
- }
- http.SetCookie(w, cookie)
- tmpl.ExecuteTemplate(w, "main", nil)
-}
+// func (h *Handlers) HandleLogin(w http.ResponseWriter, r *http.Request) {
+// r.ParseForm()
+// username := r.PostFormValue("username")
+// if username == "" {
+// msg := "username not provided"
+// h.log.Error(msg)
+// abortWithError(w, msg)
+// return
+// }
+// password := r.PostFormValue("password")
+// if password == "" {
+// msg := "password not provided"
+// h.log.Error(msg)
+// abortWithError(w, msg)
+// return
+// }
+// cleanName := utils.RemoveSpacesFromStr(username)
+// tmpl, err := template.ParseGlob("components/*.html")
+// if err != nil {
+// abortWithError(w, err.Error())
+// return
+// }
+// cookie, err := h.makeCookie(cleanName, r.RemoteAddr)
+// if err != nil {
+// h.log.Error("failed to login", "error", err)
+// abortWithError(w, err.Error())
+// return
+// }
+// http.SetCookie(w, cookie)
+// tmpl.ExecuteTemplate(w, "main", nil)
+// }
-func (h *Handlers) makeCookie(username string, remote string) (*http.Cookie, error) {
- // secret
- // Create a new random session token
- // sessionToken := xid.New().String()
- sessionToken := "token"
- expiresAt := time.Now().Add(time.Duration(h.cfg.SessionLifetime) * time.Second)
- // Set the token in the session map, along with the session information
- session := &models.Session{
- Username: username,
- Expiry: expiresAt,
- }
- cookieName := "session_token"
- // hmac to protect cookies
- hm := hmac.New(sha256.New, []byte(h.cfg.CookieSecret))
- hm.Write([]byte(cookieName))
- hm.Write([]byte(sessionToken))
- signature := hm.Sum(nil)
- // b64 enc to avoid non-ascii
- cookieValue := base64.URLEncoding.EncodeToString([]byte(
- string(signature) + sessionToken))
- cookie := &http.Cookie{
- Name: cookieName,
- Value: cookieValue,
- Secure: true,
- HttpOnly: true,
- SameSite: http.SameSiteNoneMode,
- Domain: h.cfg.ServerConfig.Host,
- }
- h.log.Info("check remote addr for cookie set",
- "remote", remote, "session", session)
- if strings.Contains(remote, "192.168.0") {
- // no idea what is going on
- cookie.Domain = "192.168.0.101"
- }
- // set ctx?
- // set user in session
- if err := h.cacheSetSession(sessionToken, session); err != nil {
- return nil, err
- }
- return cookie, nil
-}
+// func (h *Handlers) makeCookie(username string, remote string) (*http.Cookie, error) {
+// // secret
+// // Create a new random session token
+// // sessionToken := xid.New().String()
+// sessionToken := "token"
+// expiresAt := time.Now().Add(time.Duration(h.cfg.SessionLifetime) * time.Second)
+// // Set the token in the session map, along with the session information
+// session := &models.Session{
+// Username: username,
+// Expiry: expiresAt,
+// }
+// cookieName := "session_token"
+// // hmac to protect cookies
+// hm := hmac.New(sha256.New, []byte(h.cfg.CookieSecret))
+// hm.Write([]byte(cookieName))
+// hm.Write([]byte(sessionToken))
+// signature := hm.Sum(nil)
+// // b64 enc to avoid non-ascii
+// cookieValue := base64.URLEncoding.EncodeToString([]byte(
+// string(signature) + sessionToken))
+// cookie := &http.Cookie{
+// Name: cookieName,
+// Value: cookieValue,
+// Secure: true,
+// HttpOnly: true,
+// SameSite: http.SameSiteNoneMode,
+// Domain: h.cfg.ServerConfig.Host,
+// }
+// h.log.Info("check remote addr for cookie set",
+// "remote", remote, "session", session)
+// if strings.Contains(remote, "192.168.0") {
+// // no idea what is going on
+// cookie.Domain = "192.168.0.101"
+// }
+// // set ctx?
+// // set user in session
+// if err := h.cacheSetSession(sessionToken, session); err != nil {
+// return nil, err
+// }
+// return cookie, nil
+// }
-func (h *Handlers) cacheGetSession(key string) (*models.Session, error) {
- userSessionB, err := h.mc.Get(key)
- if err != nil {
- return nil, err
- }
- var us *models.Session
- if err := json.Unmarshal(userSessionB, &us); err != nil {
- return nil, err
- }
- return us, nil
-}
+// func (h *Handlers) cacheGetSession(key string) (*models.Session, error) {
+// userSessionB, err := h.mc.Get(key)
+// if err != nil {
+// return nil, err
+// }
+// var us *models.Session
+// if err := json.Unmarshal(userSessionB, &us); err != nil {
+// return nil, err
+// }
+// return us, nil
+// }
-func (h *Handlers) cacheSetSession(key string, session *models.Session) error {
- sesb, err := json.Marshal(session)
- if err != nil {
- return err
- }
- h.mc.Set(key, sesb)
- // expire in 10 min
- h.mc.Expire(key, 10*60)
- return nil
-}
+// func (h *Handlers) cacheSetSession(key string, session *models.Session) error {
+// sesb, err := json.Marshal(session)
+// if err != nil {
+// return err
+// }
+// h.mc.Set(key, sesb)
+// // expire in 10 min
+// h.mc.Expire(key, 10*60)
+// return nil
+// }
diff --git a/internal/handlers/main.go b/internal/handlers/main.go
index 960b26d..86f5b09 100644
--- a/internal/handlers/main.go
+++ b/internal/handlers/main.go
@@ -4,7 +4,6 @@ import (
"demoon/config"
"demoon/internal/database/repos"
"demoon/internal/models"
- "demoon/pkg/cache"
"html/template"
"log/slog"
"net/http"
@@ -18,7 +17,6 @@ type Handlers struct {
cfg config.Config
log *slog.Logger
repo repos.FullRepo
- mc cache.Cache
}
// NewHandlers constructor
@@ -32,7 +30,6 @@ func NewHandlers(
cfg: cfg,
log: l,
repo: repo,
- mc: cache.MemCache,
}
return h
}
diff --git a/internal/handlers/middleware.go b/internal/handlers/middleware.go
index 8b871a2..242dfb8 100644
--- a/internal/handlers/middleware.go
+++ b/internal/handlers/middleware.go
@@ -1,75 +1,66 @@
package handlers
-import (
- "context"
- "crypto/hmac"
- "crypto/sha256"
- "encoding/base64"
- "errors"
- "net/http"
-)
-
-func (h *Handlers) GetSession(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- cookieName := "session_token"
- sessionCookie, err := r.Cookie(cookieName)
- if err != nil {
- msg := "auth failed; failed to get session token from cookies"
- h.log.Debug(msg, "error", err)
- next.ServeHTTP(w, r)
- return
- }
- cookieValueB, err := base64.URLEncoding.
- DecodeString(sessionCookie.Value)
- if err != nil {
- msg := "auth failed; failed to decode b64 cookie"
- h.log.Debug(msg, "error", err)
- next.ServeHTTP(w, r)
- return
- }
- cookieValue := string(cookieValueB)
- if len(cookieValue) < sha256.Size {
- h.log.Warn("small cookie", "size", len(cookieValue))
- next.ServeHTTP(w, r)
- return
- }
- // Split apart the signature and original cookie value.
- signature := cookieValue[:sha256.Size]
- sessionToken := cookieValue[sha256.Size:]
- //verify signature
- mac := hmac.New(sha256.New, []byte(h.cfg.CookieSecret))
- mac.Write([]byte(cookieName))
- mac.Write([]byte(sessionToken))
- expectedSignature := mac.Sum(nil)
- if !hmac.Equal([]byte(signature), expectedSignature) {
- h.log.Debug("cookie with an invalid sign")
- next.ServeHTTP(w, r)
- return
- }
- userSession, err := h.cacheGetSession(sessionToken)
- if err != nil {
- msg := "auth failed; session does not exists"
- err = errors.New(msg)
- h.log.Debug(msg, "error", err)
- next.ServeHTTP(w, r)
- return
- }
- if userSession.IsExpired() {
- h.mc.RemoveKey(sessionToken)
- msg := "session is expired"
- h.log.Debug(msg, "error", err, "token", sessionToken)
- next.ServeHTTP(w, r)
- return
- }
- ctx := context.WithValue(r.Context(),
- "username", userSession.Username)
- if err := h.cacheSetSession(sessionToken,
- userSession); err != nil {
- msg := "failed to marshal user session"
- h.log.Warn(msg, "error", err)
- next.ServeHTTP(w, r)
- return
- }
- next.ServeHTTP(w, r.WithContext(ctx))
- })
-}
+//func (h *Handlers) GetSession(next http.Handler) http.Handler {
+// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+// cookieName := "session_token"
+// sessionCookie, err := r.Cookie(cookieName)
+// if err != nil {
+// msg := "auth failed; failed to get session token from cookies"
+// h.log.Debug(msg, "error", err)
+// next.ServeHTTP(w, r)
+// return
+// }
+// cookieValueB, err := base64.URLEncoding.
+// DecodeString(sessionCookie.Value)
+// if err != nil {
+// msg := "auth failed; failed to decode b64 cookie"
+// h.log.Debug(msg, "error", err)
+// next.ServeHTTP(w, r)
+// return
+// }
+// cookieValue := string(cookieValueB)
+// if len(cookieValue) < sha256.Size {
+// h.log.Warn("small cookie", "size", len(cookieValue))
+// next.ServeHTTP(w, r)
+// return
+// }
+// // Split apart the signature and original cookie value.
+// signature := cookieValue[:sha256.Size]
+// sessionToken := cookieValue[sha256.Size:]
+// //verify signature
+// mac := hmac.New(sha256.New, []byte(h.cfg.CookieSecret))
+// mac.Write([]byte(cookieName))
+// mac.Write([]byte(sessionToken))
+// expectedSignature := mac.Sum(nil)
+// if !hmac.Equal([]byte(signature), expectedSignature) {
+// h.log.Debug("cookie with an invalid sign")
+// next.ServeHTTP(w, r)
+// return
+// }
+// userSession, err := h.cacheGetSession(sessionToken)
+// if err != nil {
+// msg := "auth failed; session does not exists"
+// err = errors.New(msg)
+// h.log.Debug(msg, "error", err)
+// next.ServeHTTP(w, r)
+// return
+// }
+// if userSession.IsExpired() {
+// h.mc.RemoveKey(sessionToken)
+// msg := "session is expired"
+// h.log.Debug(msg, "error", err, "token", sessionToken)
+// next.ServeHTTP(w, r)
+// return
+// }
+// ctx := context.WithValue(r.Context(),
+// "username", userSession.Username)
+// if err := h.cacheSetSession(sessionToken,
+// userSession); err != nil {
+// msg := "failed to marshal user session"
+// h.log.Warn(msg, "error", err)
+// next.ServeHTTP(w, r)
+// return
+// }
+// next.ServeHTTP(w, r.WithContext(ctx))
+// })
+//}
diff --git a/internal/server/router.go b/internal/server/router.go
index 989766c..7034103 100644
--- a/internal/server/router.go
+++ b/internal/server/router.go
@@ -10,8 +10,9 @@ func (srv *server) ListenToRequests() {
h := srv.actions
mux := http.NewServeMux()
server := &http.Server{
- Addr: fmt.Sprintf("localhost:%s", srv.config.ServerConfig.Port),
- Handler: h.GetSession(mux),
+ Addr: fmt.Sprintf("localhost:%s", srv.config.ServerConfig.Port),
+ // Handler: h.GetSession(mux),
+ Handler: mux,
ReadTimeout: time.Second * 5,
WriteTimeout: time.Second * 5,
}
@@ -21,8 +22,8 @@ func (srv *server) ListenToRequests() {
mux.HandleFunc("GET /ping", h.Ping)
mux.HandleFunc("GET /", h.MainPage)
- mux.HandleFunc("POST /login", h.HandleLogin)
- mux.HandleFunc("POST /signup", h.HandleSignup)
+ // mux.HandleFunc("POST /login", h.HandleLogin)
+ // mux.HandleFunc("POST /signup", h.HandleSignup)
// ====== elements ======
diff --git a/pkg/cache/interface.go b/pkg/cache/interface.go
deleted file mode 100644
index 606f50f..0000000
--- a/pkg/cache/interface.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package cache
-
-type Cache interface {
- Get(key string) ([]byte, error)
- Set(key string, value []byte)
- Expire(key string, exp int64)
- GetAll() (resp map[string][]byte)
- RemoveKey(key string)
-}
diff --git a/pkg/cache/main.go b/pkg/cache/main.go
deleted file mode 100644
index 2aac109..0000000
--- a/pkg/cache/main.go
+++ /dev/null
@@ -1,146 +0,0 @@
-package cache
-
-import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- "log/slog"
- "os"
- "sync"
- "time"
-)
-
-const storeFileName = "store.json"
-
-// var MemCache Cache
-var (
- MemCache *MemoryCache
- log = slog.New(slog.NewJSONHandler(os.Stdout, nil))
-)
-
-func readJSON(fileName string) (map[string][]byte, error) {
- data := make(map[string][]byte)
- file, err := os.Open(fileName)
- if err != nil {
- return data, err
- }
- defer file.Close()
- decoder := json.NewDecoder(file)
- if err := decoder.Decode(&data); err != nil {
- return data, err
- }
- return data, nil
-}
-
-func init() {
- data, err := readJSON(storeFileName)
- if err != nil {
- log.Warn("failed to load store from file", "error", err)
- }
- MemCache = &MemoryCache{
- data: data,
- timeMap: make(map[string]time.Time),
- lock: &sync.RWMutex{},
- }
- MemCache.StartExpiryRoutine(time.Hour * 24 * 30)
- MemCache.StartBackupRoutine(time.Minute)
-}
-
-type MemoryCache struct {
- data map[string][]byte
- timeMap map[string]time.Time
- lock *sync.RWMutex
-}
-
-// Get a value by key from the cache
-func (mc *MemoryCache) Get(key string) (value []byte, err error) {
- var ok bool
- mc.lock.RLock()
- if value, ok = mc.data[key]; !ok {
- err = fmt.Errorf("not found data in mc for the key: %v", key)
- }
- mc.lock.RUnlock()
- return value, err
-}
-
-// Update a single value in the cache
-func (mc *MemoryCache) Set(key string, value []byte) {
- // no async writing
- mc.lock.Lock()
- mc.data[key] = value
- mc.lock.Unlock()
-}
-
-func (mc *MemoryCache) Expire(key string, exp int64) {
- mc.lock.RLock()
- mc.timeMap[key] = time.Now().Add(time.Duration(exp) * time.Second)
- mc.lock.RUnlock()
-}
-
-func (mc *MemoryCache) GetAll() (resp map[string][]byte) {
- resp = make(map[string][]byte)
- mc.lock.RLock()
- for k, v := range mc.data {
- resp[k] = v
- }
- mc.lock.RUnlock()
- return
-}
-
-func (mc *MemoryCache) GetAllTime() (resp map[string]time.Time) {
- resp = make(map[string]time.Time)
- mc.lock.RLock()
- for k, v := range mc.timeMap {
- resp[k] = v
- }
- mc.lock.RUnlock()
- return
-}
-
-func (mc *MemoryCache) RemoveKey(key string) {
- mc.lock.RLock()
- delete(mc.data, key)
- delete(mc.timeMap, key)
- mc.lock.RUnlock()
-}
-
-func (mc *MemoryCache) StartExpiryRoutine(n time.Duration) {
- ticker := time.NewTicker(n)
- go func() {
- for {
- <-ticker.C
- // get all
- timeData := mc.GetAllTime()
- // check time
- currentTS := time.Now()
- for k, ts := range timeData {
- if ts.Before(currentTS) {
- // delete exp keys
- mc.RemoveKey(k)
- log.Info("remove by expiry", "key", k)
- }
- }
- }
- }()
-}
-
-func (mc *MemoryCache) StartBackupRoutine(n time.Duration) {
- ticker := time.NewTicker(n)
- go func() {
- for {
- <-ticker.C
- // get all
- data := mc.GetAll()
- jsonString, err := json.Marshal(data)
- if err != nil {
- log.Warn("failed to marshal kv store", "error", err)
- continue
- }
- err = ioutil.WriteFile(storeFileName, jsonString, os.ModePerm)
- if err != nil {
- log.Warn("failed to write to json file", "error", err)
- continue
- }
- }
- }()
-}