diff options
author | GrailFinder <wohilas@gmail.com> | 2024-04-20 07:45:00 +0300 |
---|---|---|
committer | GrailFinder <wohilas@gmail.com> | 2024-04-20 07:45:00 +0300 |
commit | b33be53ea9c0be523988a9412fd8e3f6a24782b3 (patch) | |
tree | 2f05cbfc78613f1771eb8143105859983cb91750 | |
parent | ac70f43c3e52e35195353c73af5687b8286ff581 (diff) |
Feat: add auth [wip]
-rw-r--r-- | components/error.html | 9 | ||||
-rw-r--r-- | internal/handlers/auth.go | 81 | ||||
-rw-r--r-- | internal/models/auth.go | 25 | ||||
-rw-r--r-- | internal/server/router.go | 4 | ||||
-rw-r--r-- | pkg/utils/main.go | 24 |
5 files changed, 142 insertions, 1 deletions
diff --git a/components/error.html b/components/error.html new file mode 100644 index 0000000..51b6b05 --- /dev/null +++ b/components/error.html @@ -0,0 +1,9 @@ +{{define "error"}} +<a href="/"> + <div class="bg-orange-100 border-l-4 border-orange-500 text-orange-700 p-4" role="alert"> + <p class="font-bold">An error from server</p> + <p>{{.}}</p> + <p>Click this banner to return to main page.</p> + </div> +</a> +{{end}} diff --git a/internal/handlers/auth.go b/internal/handlers/auth.go new file mode 100644 index 0000000..435f8ff --- /dev/null +++ b/internal/handlers/auth.go @@ -0,0 +1,81 @@ +package handlers + +import ( + "apjournal/internal/models" + "apjournal/pkg/utils" + "fmt" + "html/template" + "net/http" + "strings" + "time" +) + +func abortWithError(w http.ResponseWriter, msg string) { + tmpl := template.Must(template.ParseGlob("components/*.html")) + tmpl.ExecuteTemplate(w, "error", msg) +} + +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) + // allNames := h.s.CacheGetAllNames() + allNames := []string{} + if utils.StrInSlice(cleanName, allNames) { + err := fmt.Errorf("name: %s already taken", cleanName) + h.log.Error("already taken", "error", err) + 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()) + } + http.SetCookie(w, cookie) + http.Redirect(w, r, "/", 302) +} + +func (h *Handlers) makeCookie(username string, remote string) (*http.Cookie, error) { + // 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, + } + // TODO: write session to db + cookie := &http.Cookie{ + Name: "session_token", + Value: sessionToken, + 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 + // domainName = "192.168.0.101" + cookie.Domain = "192.168.0.101" + } + // set ctx? + // c.Set("username", username) + return cookie, nil +} diff --git a/internal/models/auth.go b/internal/models/auth.go new file mode 100644 index 0000000..5dadf8a --- /dev/null +++ b/internal/models/auth.go @@ -0,0 +1,25 @@ +package models + +import ( + "time" +) + +// each session contains the username of the user and the time at which it expires +type Session struct { + Username string + CurrentRoom string + Expiry time.Time +} + +// we'll use this method later to determine if the session has expired +func (s Session) IsExpired() bool { + return s.Expiry.Before(time.Now()) +} + +func ListUsernames(ss map[string]*Session) []string { + resp := make([]string, 0, len(ss)) + for _, s := range ss { + resp = append(resp, s.Username) + } + return resp +} diff --git a/internal/server/router.go b/internal/server/router.go index 75cf4f9..36c2083 100644 --- a/internal/server/router.go +++ b/internal/server/router.go @@ -10,7 +10,7 @@ func (srv *server) ListenToRequests() { h := srv.actions mux := http.NewServeMux() server := &http.Server{ - Addr: "localhost:9000", + Addr: fmt.Sprintf("localhost:%d", srv.config.ServerConfig), Handler: mux, ReadTimeout: time.Second * 5, WriteTimeout: time.Second * 5, @@ -23,6 +23,8 @@ func (srv *server) ListenToRequests() { mux.HandleFunc("GET /", h.MainPage) mux.HandleFunc("POST /", h.HandleForm) mux.HandleFunc("POST /done", h.HandleDoneAction) + mux.HandleFunc("POST /login", h.HandleLogin) + // mux.HandleFunc("POST /signup", h.HandleLogin) // ====== elements ====== mux.HandleFunc("GET /showform", h.ServeShowForm) diff --git a/pkg/utils/main.go b/pkg/utils/main.go new file mode 100644 index 0000000..f49313e --- /dev/null +++ b/pkg/utils/main.go @@ -0,0 +1,24 @@ +package utils + +import ( + "strings" + "unicode" +) + +func RemoveSpacesFromStr(origin string) string { + return strings.Map(func(r rune) rune { + if unicode.IsSpace(r) { + return -1 + } + return r + }, origin) +} + +func StrInSlice(key string, sl []string) bool { + for _, i := range sl { + if key == i { + return true + } + } + return false +} |