aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/router.go14
-rw-r--r--src/sessions/middleware.go13
-rw-r--r--src/sessions/sessions.go38
-rw-r--r--src/user/routes.go48
4 files changed, 77 insertions, 36 deletions
diff --git a/src/server/router.go b/src/server/router.go
index 6b33a7d..3b43119 100644
--- a/src/server/router.go
+++ b/src/server/router.go
@@ -12,12 +12,11 @@ import (
type HandlerFunc func(s *Server) http.HandlerFunc
type Route struct {
- Name string
- Method string
- Path string
- AuthRequired bool
- HandlerFunc HandlerFunc
- Middlewares []func(http.Handler) http.Handler
+ Name string
+ Method string
+ Path string
+ HandlerFunc HandlerFunc
+ Middlewares []func(http.Handler) http.Handler
}
type Routes []Route
@@ -25,6 +24,7 @@ type Routes []Route
func NewRouter(config *conf.Conf) *chi.Mux {
r := chi.NewRouter()
r.Use(middleware.Logger)
- r.Use(sessions.SetSession)
+ sessions.InitStore()
+ r.Use(sessions.StartSession)
return r
}
diff --git a/src/sessions/middleware.go b/src/sessions/middleware.go
index 6bb3b15..6ae34ac 100644
--- a/src/sessions/middleware.go
+++ b/src/sessions/middleware.go
@@ -5,22 +5,25 @@ import (
"net/http"
)
-func SetSession(next http.Handler) http.Handler {
+func StartSession(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// is there a session_token cookie?
scookie, err := r.Cookie("session_token")
if err != nil || scookie.Value == "" {
// no session value or cookie
next.ServeHTTP(w, r)
+ return
}
+ // check for existing session
cvalue := scookie.Value
vsession, ok := GetSession(cvalue)
if !ok {
// no session
next.ServeHTTP(w, r)
+ return
}
// set session
- ctx := context.WithValue(r.Context(), SessionCtxKey("session"), vsession.Id())
+ ctx := context.WithValue(r.Context(), SessionCtxKey("session"), vsession)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
@@ -30,6 +33,7 @@ func GuestSession(next http.Handler) http.Handler {
// if SessionKey does exist then redirect to `/u/me` as this is an auth session
if v := r.Context().Value(SessionCtxKey("session")); v != nil {
http.Redirect(w, r, "/u/me", http.StatusSeeOther)
+ return
}
// else this is a valid guest request
next.ServeHTTP(w, r)
@@ -40,10 +44,11 @@ func AuthSession(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// if session key exists then this is a valid auth request
if v := r.Context().Value(SessionCtxKey("session")); v != nil {
- http.Redirect(w, r, "/login", http.StatusSeeOther)
+ next.ServeHTTP(w, r)
+ return
}
// else this is a guest session request, redirect to login
- http.Redirect(w, r, "/login", http.StatusSeeOther)
+ http.Redirect(w, r, "/u/auth", http.StatusSeeOther)
})
}
diff --git a/src/sessions/sessions.go b/src/sessions/sessions.go
index 34fe91c..0124c51 100644
--- a/src/sessions/sessions.go
+++ b/src/sessions/sessions.go
@@ -7,19 +7,23 @@ import (
"github.com/google/uuid"
)
-type sessionvalues map[string]any
+type SessionValues map[string]any
type Session struct {
id string
- values sessionvalues
- mu *sync.Mutex
+ values SessionValues
+ lock *sync.Mutex
}
type SessionCtxKey string
-var _sessions map[string]Session
+var _sessions map[string]*Session
-func NewSession(w http.ResponseWriter, values map[string]any) Session {
+func InitStore() {
+ _sessions = map[string]*Session{}
+}
+
+func NewSession(w http.ResponseWriter, values map[string]any) *Session {
token := uuid.NewString()
// set secure cookie in http.ResponseWriter
@@ -30,15 +34,16 @@ func NewSession(w http.ResponseWriter, values map[string]any) Session {
})
// create session and store
- s := Session{
+ s := &Session{
id: token,
- values: sessionvalues(values),
+ values: SessionValues(values),
+ lock: &sync.Mutex{},
}
_sessions[token] = s
return s
}
-func GetSession(id string) (Session, bool) {
+func GetSession(id string) (*Session, bool) {
s, ok := _sessions[id]
return s, ok
}
@@ -48,14 +53,23 @@ func (s *Session) Id() string {
}
func (s *Session) Get(key string) interface{} {
- s.mu.Lock()
- defer s.mu.Unlock()
+ s.lock.Lock()
+ defer s.lock.Unlock()
return s.values[key]
}
func (s *Session) Set(key string, value interface{}) bool {
- s.mu.Lock()
- defer s.mu.Unlock()
+ s.lock.Lock()
+ defer s.lock.Unlock()
s.values[key] = value
+ _sessions[s.id] = s
return true
}
+
+func (s *Session) Destroy(w http.ResponseWriter) {
+ delete(_sessions, s.id)
+ http.SetCookie(w, &http.Cookie{
+ Name: "session_token",
+ Value: "",
+ })
+}
diff --git a/src/user/routes.go b/src/user/routes.go
index d3db728..3bcab06 100644
--- a/src/user/routes.go
+++ b/src/user/routes.go
@@ -20,28 +20,37 @@ var Routes = server.Routes{
server.Route{
Name: "Store",
Method: "POST",
- Path: "/user",
+ Path: "/u",
HandlerFunc: Store,
+ Middlewares: server.NewMiddlewares(sessions.GuestSession),
},
server.Route{
Name: "LoginForm",
Method: "GET",
- Path: "/u/login",
+ Path: "/u/auth",
HandlerFunc: LoginForm,
+ Middlewares: server.NewMiddlewares(sessions.GuestSession),
},
server.Route{
Name: "Authenticate",
Method: "POST",
Path: "/u/auth",
- HandlerFunc: Authenticate,
+ HandlerFunc: Login,
+ Middlewares: server.NewMiddlewares(sessions.GuestSession),
+ },
+ server.Route{
+ Name: "Logout",
+ Method: "GET",
+ Path: "/u/logout",
+ HandlerFunc: Logout,
+ Middlewares: server.NewMiddlewares(sessions.AuthSession),
},
server.Route{
- Name: "Me",
- Method: "GET",
- Path: "/u/me",
- AuthRequired: true,
- HandlerFunc: Show,
- Middlewares: server.NewMiddlewares(sessions.AuthSession),
+ Name: "Me",
+ Method: "GET",
+ Path: "/u/me",
+ HandlerFunc: Show,
+ Middlewares: server.NewMiddlewares(sessions.AuthSession),
},
}
@@ -81,7 +90,7 @@ func Store(s *server.Server) http.HandlerFunc {
}
// Send email validation
// Create cookie session
- sessions.NewSession(w, map[string]interface{}{"uid": user.Id, "username": user.Username})
+ sessions.NewSession(w, sessions.SessionValues{"uid": user.Id, "username": user.Username})
// Redirect to user profile
http.Redirect(w, r, "/u/me", http.StatusSeeOther)
}
@@ -93,13 +102,26 @@ func LoginForm(s *server.Server) http.HandlerFunc {
}
}
-func Authenticate(s *server.Server) http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) {}
+func Login(s *server.Server) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ // look up the user from the db
+ // hash the form secret
+ // compare form hash to db hash
+ // login or dont
+ }
+}
+
+func Logout(s *server.Server) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ session := r.Context().Value("session").(*sessions.Session)
+ session.Destroy(w)
+ http.Redirect(w, r, "/u/auth", http.StatusSeeOther)
+ }
}
func Show(s *server.Server) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
- session := r.Context().Value(sessions.SessionCtxKey("session")).(sessions.Session)
+ session := r.Context().Value(sessions.SessionCtxKey("session")).(*sessions.Session)
username := session.Get("username").(string)
s.Ui.Render(w, "user/me", &struct{ Message, Username string }{"Congrats on getting this far!", username})
}