You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by ly...@apache.org on 2024/02/21 06:47:45 UTC
(incubator-devlake) 01/01: refactor(middlewares): add `CheckAuthorizationHeader`
This is an automated email from the ASF dual-hosted git repository.
lynwee pushed a commit to branch lw-fix-open-api
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
commit 92fef05f970ede18e65d1fecbff5e38e5f3447c2
Author: Lynwee Hou <li...@merico.dev>
AuthorDate: Wed Feb 21 14:45:24 2024 +0800
refactor(middlewares): add `CheckAuthorizationHeader`
---
backend/server/api/middlewares.go | 154 ++++++++++++++++++++------------------
1 file changed, 83 insertions(+), 71 deletions(-)
diff --git a/backend/server/api/middlewares.go b/backend/server/api/middlewares.go
index 9e274c259..32ec5e854 100644
--- a/backend/server/api/middlewares.go
+++ b/backend/server/api/middlewares.go
@@ -20,6 +20,7 @@ package api
import (
"encoding/base64"
"fmt"
+ "github.com/apache/incubator-devlake/core/log"
"net/http"
"regexp"
"strings"
@@ -95,11 +96,13 @@ func OAuth2ProxyAuthentication(basicRes context.BasicRes) gin.HandlerFunc {
}
}
+type apiBody struct {
+ Success bool `json:"success"`
+ Message string `json:"message"`
+}
+
func RestAuthentication(router *gin.Engine, basicRes context.BasicRes) gin.HandlerFunc {
- type ApiBody struct {
- Success bool `json:"success"`
- Message string `json:"message"`
- }
+
db := basicRes.GetDal()
logger := basicRes.GetLogger()
if db == nil {
@@ -115,88 +118,97 @@ func RestAuthentication(router *gin.Engine, basicRes context.BasicRes) gin.Handl
return
}
path = strings.TrimPrefix(path, "/rest")
-
authHeader := c.GetHeader("Authorization")
- if authHeader == "" {
- c.Abort()
- c.JSON(http.StatusUnauthorized, &ApiBody{
- Success: false,
- Message: "token is missing",
- })
+ ok := CheckAuthorizationHeader(c, logger, db, apiKeyHelper, authHeader, path)
+ if !ok {
return
- }
- apiKeyStr := strings.TrimPrefix(authHeader, "Bearer ")
- if apiKeyStr == authHeader || apiKeyStr == "" {
+ } else {
+ router.HandleContext(c)
c.Abort()
- c.JSON(http.StatusUnauthorized, &ApiBody{
- Success: false,
- Message: "token is not present or malformed",
- })
return
}
+ }
+}
- hashedApiKey, err := apiKeyHelper.DigestToken(apiKeyStr)
- if err != nil {
- logger.Error(err, "DigestToken")
- c.Abort()
- c.JSON(http.StatusInternalServerError, &ApiBody{
- Success: false,
- Message: err.Error(),
- })
- return
- }
+func CheckAuthorizationHeader(c *gin.Context, logger log.Logger, db dal.Dal, apiKeyHelper *apikeyhelper.ApiKeyHelper, authHeader, path string) bool {
+ if authHeader == "" {
+ c.Abort()
+ c.JSON(http.StatusUnauthorized, &apiBody{
+ Success: false,
+ Message: "token is missing",
+ })
+ return false
+ }
+ apiKeyStr := strings.TrimPrefix(authHeader, "Bearer ")
+ if apiKeyStr == authHeader || apiKeyStr == "" {
+ c.Abort()
+ c.JSON(http.StatusUnauthorized, &apiBody{
+ Success: false,
+ Message: "token is not present or malformed",
+ })
+ return false
+ }
- apiKey, err := apiKeyHelper.GetApiKey(nil, dal.Where("api_key = ?", hashedApiKey))
- if err != nil {
- c.Abort()
- if db.IsErrorNotFound(err) {
- c.JSON(http.StatusForbidden, &ApiBody{
- Success: false,
- Message: "api key is invalid",
- })
- } else {
- logger.Error(err, "query api key from db")
- c.JSON(http.StatusInternalServerError, &ApiBody{
- Success: false,
- Message: err.Error(),
- })
- }
- return
- }
+ hashedApiKey, err := apiKeyHelper.DigestToken(apiKeyStr)
+ if err != nil {
+ logger.Error(err, "DigestToken")
+ c.Abort()
+ c.JSON(http.StatusInternalServerError, &apiBody{
+ Success: false,
+ Message: err.Error(),
+ })
+ return false
+ }
- if apiKey.ExpiredAt != nil && time.Until(*apiKey.ExpiredAt) < 0 {
- c.Abort()
- c.JSON(http.StatusForbidden, &ApiBody{
- Success: false,
- Message: "api key has expired",
- })
- return
- }
- matched, matchErr := regexp.MatchString(apiKey.AllowedPath, path)
- if matchErr != nil {
- logger.Error(err, "regexp match path error")
- c.Abort()
- c.JSON(http.StatusInternalServerError, &ApiBody{
+ apiKey, err := apiKeyHelper.GetApiKey(nil, dal.Where("api_key = ?", hashedApiKey))
+ if err != nil {
+ c.Abort()
+ if db.IsErrorNotFound(err) {
+ c.JSON(http.StatusForbidden, &apiBody{
Success: false,
- Message: matchErr.Error(),
+ Message: "api key is invalid",
})
- return
- }
- if !matched {
- c.JSON(http.StatusForbidden, &ApiBody{
+ } else {
+ logger.Error(err, "query api key from db")
+ c.JSON(http.StatusInternalServerError, &apiBody{
Success: false,
- Message: "path doesn't match api key's scope",
+ Message: err.Error(),
})
- return
}
+ return false
+ }
- logger.Info("redirect path: %s to: %s", c.Request.URL.Path, path)
- c.Request.URL.Path = path
- c.Set(common.USER, &common.User{
- Name: apiKey.Creator.Creator,
- Email: apiKey.Creator.CreatorEmail,
+ if apiKey.ExpiredAt != nil && time.Until(*apiKey.ExpiredAt) < 0 {
+ c.Abort()
+ c.JSON(http.StatusForbidden, &apiBody{
+ Success: false,
+ Message: "api key has expired",
})
- router.HandleContext(c)
+ return false
+ }
+ matched, matchErr := regexp.MatchString(apiKey.AllowedPath, path)
+ if matchErr != nil {
+ logger.Error(err, "regexp match path error")
c.Abort()
+ c.JSON(http.StatusInternalServerError, &apiBody{
+ Success: false,
+ Message: matchErr.Error(),
+ })
+ return false
}
+ if !matched {
+ c.JSON(http.StatusForbidden, &apiBody{
+ Success: false,
+ Message: "path doesn't match api key's scope",
+ })
+ return false
+ }
+
+ logger.Info("redirect path: %s to: %s", c.Request.URL.Path, path)
+ c.Request.URL.Path = path
+ c.Set(common.USER, &common.User{
+ Name: apiKey.Creator.Creator,
+ Email: apiKey.Creator.CreatorEmail,
+ })
+ return true
}