This repository has been archived on 2024-03-28. You can view files and clone it, but cannot push or open issues or pull requests.
atsebay.t/auth.go

166 lines
3.8 KiB
Go

package main
import (
"encoding/base64"
"net/http"
"strings"
"time"
"unicode"
"github.com/gin-gonic/gin"
)
var LocalAuthFunc = checkAuthKrb5
var allowLocalAuth bool
var localAuthUsers arrayFlags
var mainBanner string
type loginForm struct {
Login string `json:"username"`
Password string `json:"password"`
}
func declareAPIAuthRoutes(router *gin.RouterGroup) {
router.GET("/auth", validateAuthToken)
router.POST("/auth", func(c *gin.Context) {
LocalAuthFunc(c)
})
router.POST("/auth/logout", logout)
}
func declareAPIAdminAuthRoutes(router *gin.RouterGroup) {
router.POST("/auth/impersonate", func(c *gin.Context) {
session := c.MustGet("Session").(*Session)
var u *User
if err := c.ShouldBindJSON(&u); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
return
}
newuser, err := getUser(int(u.Id))
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
return
}
session.IdUser = &newuser.Id
session.Update()
c.JSON(http.StatusOK, authToken{
User: newuser,
CurrentPromo: currentPromo,
MessageBanner: mainBanner,
})
})
}
type authToken struct {
*User
CurrentPromo uint `json:"current_promo"`
Groups []string `json:"groups"`
MessageBanner string `json:"banner,omitempty"`
}
func validateAuthToken(c *gin.Context) {
if u, ok := c.Get("LoggedUser"); !ok || u.(*User) == nil {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"errmsg": "Not connected"})
return
} else {
t := authToken{User: u.(*User), CurrentPromo: currentPromo, MessageBanner: mainBanner}
t.Groups = strings.Split(strings.TrimFunc(t.User.Groups, func(r rune) bool { return !unicode.IsLetter(r) }), ",")
c.JSON(http.StatusOK, t)
}
}
func logout(c *gin.Context) {
eraseCookie(c)
c.JSON(http.StatusOK, true)
}
func completeAuth(c *gin.Context, username string, email string, firstname string, lastname string, promo uint, groups string, session *Session) (usr *User, err error) {
if !userExists(username) {
if promo == 0 {
promo = currentPromo
}
if usr, err = NewUser(username, email, firstname, lastname, promo, groups); err != nil {
return
}
} else if usr, err = getUserByLogin(username); err != nil {
return
}
upd_user := false
// Update user's promo if it has changed
if promo != 0 && promo != usr.Promo {
usr.Promo = promo
upd_user = true
}
// Update user's group if they have been modified
if len(groups) > 0 {
if len(groups) > 255 {
groups = groups[:255]
}
if usr.Groups != groups {
usr.Groups = groups
upd_user = true
}
}
if upd_user {
usr.Update()
}
if session == nil {
session, err = usr.NewSession()
} else {
_, err = session.SetUser(usr)
}
if err != nil {
return
}
http.SetCookie(c.Writer, &http.Cookie{
Name: "auth",
Value: base64.StdEncoding.EncodeToString(session.Id),
Path: baseURL + "/",
Expires: time.Now().Add(30 * 24 * time.Hour),
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Secure: true,
})
return
}
func eraseCookie(c *gin.Context) {
http.SetCookie(c.Writer, &http.Cookie{
Name: "auth",
Value: "",
Path: baseURL + "/",
Expires: time.Unix(0, 0),
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
})
}
func dummyAuth(c *gin.Context) {
var lf map[string]string
if err := c.ShouldBindJSON(&lf); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
return
}
if usr, err := completeAuth(c, lf["username"], lf["email"], lf["firstname"], lf["lastname"], currentPromo, "", nil); err != nil {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"errmsg": err.Error()})
return
} else {
c.JSON(http.StatusOK, authToken{User: usr, CurrentPromo: currentPromo, MessageBanner: mainBanner})
}
}