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/api.go

143 lines
3.7 KiB
Go

package main
import (
"encoding/base64"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
func declareAPIRoutes(router *gin.Engine) {
apiRoutes := router.Group("/api")
apiRoutes.Use(authMiddleware())
declareAPIAuthRoutes(apiRoutes)
declareAPICategoriesRoutes(apiRoutes)
declareAPISurveysRoutes(apiRoutes)
declareAPIWorksRoutes(apiRoutes)
declareAPIKeysRoutes(apiRoutes)
declareAPISharesRoutes(apiRoutes)
declareCallbacksRoutes(apiRoutes)
authRoutes := router.Group("")
authRoutes.Use(authMiddleware(loggedUser))
adminRoutes := router.Group("")
adminRoutes.Use(authMiddleware(adminRestricted))
initializeGitLabOIDC(router, authRoutes, adminRoutes)
apiAuthRoutes := router.Group("/api")
apiAuthRoutes.Use(authMiddleware(loggedUser))
declareAPIAuthAsksRoutes(apiAuthRoutes)
declareAPIAuthQuestionsRoutes(apiAuthRoutes)
declareAPIAuthHelpRoutes(apiAuthRoutes)
declareAPIAuthKeysRoutes(apiAuthRoutes)
declareAPIAuthSurveysRoutes(apiAuthRoutes)
declareAPIAuthUsersRoutes(apiAuthRoutes)
declareAPIAuthWorksRoutes(apiAuthRoutes)
apiAdminRoutes := router.Group("/api")
apiAdminRoutes.Use(authMiddleware(adminRestricted))
apiAdminRoutes.DELETE("/cache", func(c *gin.Context) {
_surveys_cache_mutex.Lock()
_surveys_cache = map[int64]*Survey{}
_surveys_cache_mutex.Unlock()
_questions_cache_mutex.Lock()
_questions_cache = map[int64]*Question{}
_questions_cache_mutex.Unlock()
})
declareAPIAdminAuthRoutes(apiAdminRoutes)
declareAPIAdminAsksRoutes(apiAdminRoutes)
declareAPIAdminCategoriesRoutes(apiRoutes)
declareAPIAuthGradesRoutes(apiAdminRoutes)
declareAPIAdminGradationRoutes(apiAdminRoutes)
declareAPIAdminHelpRoutes(apiAdminRoutes)
declareAPIAdminQuestionsRoutes(apiAdminRoutes)
declareAPIAuthRepositoriesRoutes(apiAdminRoutes)
declareAPIAdminSurveysRoutes(apiAdminRoutes)
declareAPIAdminUsersRoutes(apiAdminRoutes)
declareAPIAdminWorksRoutes(apiAdminRoutes)
}
func loggedUser(u *User, c *gin.Context) bool {
if u != nil {
return true
}
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Permission Denied"})
return false
}
func adminRestricted(u *User, c *gin.Context) bool {
if u != nil && u.IsAdmin {
return true
}
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Permission Denied"})
return false
}
func getSessionFromRequest(c *gin.Context) (*Session, error) {
var encodedSession string
if cookie, err := c.Request.Cookie("auth"); err == nil {
encodedSession = cookie.Value
} else if flds := strings.Fields(c.GetHeader("Authorization")); len(flds) == 2 && flds[0] == "Bearer" {
encodedSession = flds[1]
}
if len(encodedSession) > 0 {
if sessionid, err := base64.StdEncoding.DecodeString(encodedSession); err != nil {
return nil, err
} else {
return getSession(sessionid)
}
}
return nil, nil
}
func authMiddleware(access ...func(*User, *gin.Context) bool) gin.HandlerFunc {
return func(c *gin.Context) {
session, err := getSessionFromRequest(c)
if err != nil {
eraseCookie(c)
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"errmsg": err.Error()})
return
}
var user *User = nil
if session == nil || session.IdUser == nil {
user = nil
} else if std, err := getUser(int(*session.IdUser)); err != nil {
eraseCookie(c)
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"errmsg": err.Error()})
return
} else {
user = std
}
// Check access limitation
for _, a := range access {
if !a(user, c) {
return
}
}
// Retrieve corresponding user
c.Set("Session", session)
c.Set("LoggedUser", user)
// We are now ready to continue
c.Next()
// On return, check if the session has changed
if session != nil && session.HasChanged() {
session.Update()
}
}
}