chore: establish local platform baseline
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
package httpapi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"data-terminal-cloud/internal/identity"
|
||||
)
|
||||
|
||||
func BearerAuth(verifier identity.TokenVerifier, next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
||||
rawToken, ok := bearerToken(request.Header.Get("Authorization"))
|
||||
if !ok {
|
||||
writer.Header().Set("WWW-Authenticate", "Bearer")
|
||||
WriteError(writer, request, http.StatusUnauthorized, "AUTHENTICATION_REQUIRED", "请先登录后再访问")
|
||||
return
|
||||
}
|
||||
principal, err := verifier.Verify(request.Context(), rawToken)
|
||||
if err != nil {
|
||||
writer.Header().Set("WWW-Authenticate", `Bearer error="invalid_token"`)
|
||||
WriteError(writer, request, http.StatusUnauthorized, "AUTHENTICATION_INVALID", "登录凭证无效或已经过期")
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(writer, request.WithContext(identity.WithPrincipal(request.Context(), principal)))
|
||||
})
|
||||
}
|
||||
|
||||
func CurrentUserHandler(repository *identity.Repository) http.Handler {
|
||||
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
||||
writer.Header().Set("Cache-Control", "no-store")
|
||||
principal, ok := identity.PrincipalFromContext(request.Context())
|
||||
if !ok {
|
||||
WriteError(writer, request, http.StatusUnauthorized, "AUTHENTICATION_REQUIRED", "请先登录后再访问")
|
||||
return
|
||||
}
|
||||
currentUser, err := repository.CurrentUser(request.Context(), principal)
|
||||
switch {
|
||||
case errors.Is(err, identity.ErrAccountNotFound):
|
||||
WriteError(writer, request, http.StatusForbidden, "RESOURCE_ACCESS_DENIED", "当前账号无权访问该资源")
|
||||
case err != nil:
|
||||
WriteError(writer, request, http.StatusInternalServerError, "INTERNAL_ERROR", "服务暂时不可用")
|
||||
default:
|
||||
WriteJSON(writer, request, http.StatusOK, currentUser)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func bearerToken(header string) (string, bool) {
|
||||
parts := strings.Fields(header)
|
||||
if len(parts) != 2 || !strings.EqualFold(parts[0], "Bearer") || strings.TrimSpace(parts[1]) == "" {
|
||||
return "", false
|
||||
}
|
||||
return parts[1], true
|
||||
}
|
||||
Reference in New Issue
Block a user