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:44 UTC
(incubator-devlake) branch lw-fix-open-api created (now 92fef05f9)
This is an automated email from the ASF dual-hosted git repository.
lynwee pushed a change to branch lw-fix-open-api
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
at 92fef05f9 refactor(middlewares): add `CheckAuthorizationHeader`
This branch includes the following new commits:
new 92fef05f9 refactor(middlewares): add `CheckAuthorizationHeader`
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(incubator-devlake) 01/01: refactor(middlewares): add `CheckAuthorizationHeader`
Posted by ly...@apache.org.
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
}