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() } } }