package api import ( "fmt" "github.com/gin-gonic/gin" "log" "net/http" "os" "resource-manager/security" "strings" "time" ) func Auth() gin.HandlerFunc { basicAuth, hasBasicAuth := os.LookupEnv("BASIC_AUTH_CREDENTIALS") var apiAuths []string if list, hasApiAuth := os.LookupEnv("API_CREDENTIALS"); hasApiAuth { apiAuths = strings.Split(list, ",") } return func(c *gin.Context) { if rawToken := c.Query("token"); rawToken != "" { token, err := security.ParseToken(rawToken) if err != nil { abort(c, nil, http.StatusUnauthorized, "invalid token") return } c.Set("secure", "token") c.Set("path", token.Path) return } authHeader := c.GetHeader("Authorization") if strings.HasPrefix(authHeader, "Basic ") && hasBasicAuth { if strings.TrimPrefix(authHeader, "Basic ") == basicAuth { c.Set("secure", security.TypeBasic) return } } if strings.HasPrefix(authHeader, "Api ") && hasBasicAuth { key := strings.TrimPrefix(authHeader, "Api ") if hasValidApiKey(apiAuths, key) { c.Set("secure", security.TypeApi) return } } abort(c, nil, http.StatusUnauthorized, "missing auth") } } func Secure(types ...security.Type) gin.HandlerFunc { return func(c *gin.Context) { value, exists := c.Get("secure") if !exists { abort(c, nil, http.StatusUnauthorized, "missing auth") } else { securityType := value.(security.Type) for _, t := range types { if t == securityType { return } } abort(c, nil, http.StatusUnauthorized, fmt.Sprintf("bad security: received %s type", securityType)) } } } func hasValidApiKey(auths []string, key string) bool { for _, a := range auths { if a == key { return true } } return false } func abort(c *gin.Context, err error, statusCode int, message string) { log.Printf("Aborted with error: %v", err) c.AbortWithStatusJSON(statusCode, gin.H{"status": statusCode, "created": time.Now(), "message": message}) }