mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-01-03 01:59:55 -06:00
97 lines
2.4 KiB
Go
97 lines
2.4 KiB
Go
package authenticator
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/shroff/phylum/server/internal/core/errors"
|
|
"github.com/shroff/phylum/server/internal/core/fs"
|
|
"github.com/shroff/phylum/server/internal/core/user"
|
|
)
|
|
|
|
var errAuthRequired = errors.NewError(http.StatusUnauthorized, "auth_required", "authorization required")
|
|
|
|
const keyUser = "user"
|
|
const keyFileSystem = "filesystem"
|
|
|
|
func GetUser(c *gin.Context) user.User {
|
|
val, ok := c.Get(keyUser)
|
|
if !ok {
|
|
return user.User{}
|
|
}
|
|
return val.(user.User)
|
|
}
|
|
|
|
func GetFileSystem(c *gin.Context) fs.FileSystem {
|
|
val, ok := c.Get(keyFileSystem)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return val.(fs.FileSystem)
|
|
}
|
|
|
|
func Require(c *gin.Context) {
|
|
ctx := c.Request.Context()
|
|
if u, err := extractUserDetails(c); err != nil {
|
|
panic(err)
|
|
} else {
|
|
c.Set(keyUser, u)
|
|
c.Set(keyFileSystem, u.OpenFileSystem(ctx))
|
|
}
|
|
}
|
|
|
|
func extractUserDetails(c *gin.Context) (user.User, error) {
|
|
userManager := user.ManagerFromContext(c.Request.Context())
|
|
if header := c.Request.Header.Get("Authorization"); header == "" {
|
|
if cookie, err := c.Request.Cookie("auth_token"); err == nil {
|
|
token := cookie.Value
|
|
if u, err := userManager.ReadAccessToken(token); err == nil {
|
|
return u, nil
|
|
} else {
|
|
return user.User{}, err
|
|
}
|
|
} else if err != http.ErrNoCookie {
|
|
return user.User{}, err
|
|
}
|
|
return user.User{}, errAuthRequired
|
|
} else if auth, ok := checkAuthHeader(header, "basic"); ok {
|
|
if email, password, ok := decodeBasicAuth(auth); ok {
|
|
if u, err := userManager.VerifyUserPassword(email, password); err == nil {
|
|
return u, nil
|
|
} else {
|
|
return user.User{}, err
|
|
}
|
|
}
|
|
} else if token, ok := checkAuthHeader(header, "bearer"); ok {
|
|
if u, err := userManager.ReadAccessToken(token); err == nil {
|
|
return u, nil
|
|
} else {
|
|
return user.User{}, err
|
|
}
|
|
}
|
|
return user.User{}, errAuthRequired
|
|
}
|
|
|
|
func checkAuthHeader(header, prefix string) (string, bool) {
|
|
prefix = prefix + " "
|
|
if len(header) < len(prefix) || !strings.EqualFold(header[:len(prefix)], prefix) {
|
|
return "", false
|
|
}
|
|
return header[len(prefix):], true
|
|
}
|
|
|
|
func decodeBasicAuth(auth string) (email, password string, ok bool) {
|
|
c, err := base64.StdEncoding.DecodeString(auth)
|
|
if err != nil {
|
|
return "", "", false
|
|
}
|
|
cs := string(c)
|
|
email, password, ok = strings.Cut(cs, ":")
|
|
if !ok {
|
|
return "", "", false
|
|
}
|
|
return email, password, true
|
|
}
|