Initial commit
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
var SessionCookieName = "session" // TODO: Make configurable
|
||||
|
||||
type AuthMiddlewareConfig struct {
|
||||
IsLogged bool
|
||||
WithPermissions []string
|
||||
}
|
||||
|
||||
type Authenticator interface {
|
||||
// Login adds a session cookie to the user
|
||||
Login(w http.ResponseWriter, userID string)
|
||||
// Logout clears the user session cookies (by setting the session cookie timeout to 0)
|
||||
Logout(w http.ResponseWriter)
|
||||
|
||||
// Middleware is a configurable middleware to authenticate http routes based on logged status and permissions
|
||||
Middleware(*AuthMiddlewareConfig) func(http.Handler) http.Handler
|
||||
// LoggedMiddleware accepts all logged users without checking for specific permissions
|
||||
LoggedMiddleware() func(http.Handler) http.Handler
|
||||
|
||||
// UserFromSession returns the userID for this cookie session token
|
||||
UserFromSession(r http.Request) (string, error)
|
||||
}
|
||||
|
||||
type AuthService struct {
|
||||
// CheckUserPassword
|
||||
CheckUserPassword func(userID string, password string) bool
|
||||
|
||||
// GetUserPermissions gets the list of permissions for this user
|
||||
UserPermissions func(userID string) []string
|
||||
|
||||
// SessionTokenFromUser returns a session token that represents this user
|
||||
SessionTokenFromUser func(userID string) string
|
||||
// UserFromSessionToken returns the corresponing user for this session token
|
||||
UserFromSessionToken func(session string) (string, bool)
|
||||
|
||||
// AuthenticationFailed handles failed authentications
|
||||
AuthenticationFailed http.Handler
|
||||
}
|
||||
|
||||
func (auth *AuthService) Login(w http.ResponseWriter, userID string) {
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: SessionCookieName,
|
||||
Value: auth.SessionTokenFromUser(userID),
|
||||
Expires: time.Now().Add(10 * time.Minute), // TODO: Make configurable
|
||||
})
|
||||
}
|
||||
|
||||
func (auth *AuthService) Logout(w http.ResponseWriter) {
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: SessionCookieName,
|
||||
Value: "",
|
||||
Expires: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
func (auth *AuthService) Middleware(config *AuthMiddlewareConfig) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
cookie, err := r.Cookie(SessionCookieName)
|
||||
if err == http.ErrNoCookie && !config.IsLogged {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
auth.AuthenticationFailed.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
userID, exists := auth.UserFromSessionToken(cookie.Value)
|
||||
if !exists {
|
||||
auth.Logout(w)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if config.IsLogged {
|
||||
userPerms := map[string]bool{}
|
||||
for _, perm := range auth.UserPermissions(userID) {
|
||||
userPerms[perm] = true
|
||||
}
|
||||
|
||||
// check the user has all the permissions to access the route
|
||||
hasAll := true
|
||||
for _, perm := range config.WithPermissions {
|
||||
if _, present := userPerms[perm]; !present {
|
||||
hasAll = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !hasAll {
|
||||
auth.AuthenticationFailed.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (auth *AuthService) LoggedMiddleware() func(http.Handler) http.Handler {
|
||||
return auth.Middleware(&AuthMiddlewareConfig{
|
||||
IsLogged: true,
|
||||
WithPermissions: []string{},
|
||||
})
|
||||
}
|
||||
|
||||
func (auth *AuthService) UserFromSession(r http.Request) (string, error) {
|
||||
cookie, err := r.Cookie(SessionCookieName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
userID, exists := auth.UserFromSessionToken(cookie.Value)
|
||||
if !exists {
|
||||
return "", fmt.Errorf(`no user for this session token`)
|
||||
}
|
||||
|
||||
return userID, nil
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package db
|
||||
|
||||
// Entities
|
||||
|
||||
type Utente struct {
|
||||
ID string
|
||||
Username string
|
||||
Permissions []string
|
||||
}
|
||||
|
||||
type Stanza struct {
|
||||
ID string
|
||||
Posti []string
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
type AzioneBase struct {
|
||||
Tipo string
|
||||
}
|
||||
|
||||
type AzioneStanza struct {
|
||||
AzioneBase
|
||||
UserID string
|
||||
StanzaID string
|
||||
}
|
||||
|
||||
type AzioneOccupaPosto struct {
|
||||
AzioneStanza
|
||||
PostoID string
|
||||
}
|
||||
|
||||
type AzioneLiberaPosto struct {
|
||||
AzioneStanza
|
||||
PostoID string
|
||||
}
|
||||
|
||||
// Database Interfaces
|
||||
|
||||
type Store interface {
|
||||
// Entities
|
||||
|
||||
GetUtente(userID string) *Utente
|
||||
GetStanza(stanzaID string) *Stanza
|
||||
|
||||
// Available Seats
|
||||
|
||||
GetPostiOccupati(stanzaID string) []string
|
||||
GetPostiLiberi(stanzaID string) []string
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
module git.phc.dm.unipi.it/aziis98/posti-dm/server
|
||||
|
||||
go 1.17
|
||||
|
||||
require github.com/go-chi/chi/v5 v5.0.7
|
||||
|
||||
require github.com/mattn/go-sqlite3 v1.14.12 // indirect
|
||||
@@ -0,0 +1,4 @@
|
||||
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
|
||||
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0=
|
||||
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
@@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
)
|
||||
|
||||
var HOST = ":3000"
|
||||
|
||||
func main() {
|
||||
r := chi.NewRouter()
|
||||
|
||||
r.Use(middleware.RequestID)
|
||||
r.Use(middleware.RealIP)
|
||||
r.Use(middleware.Logger)
|
||||
r.Use(middleware.Recoverer)
|
||||
|
||||
log.Printf(`Starting server on %s...`, HOST)
|
||||
err := http.ListenAndServe(HOST, r)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user