- Updated environment configuration to unify frontend for mail and drive under a single service. - Revised README to reflect changes in frontend setup and routing for the unified application. - Introduced new API documentation endpoints for better accessibility of API specifications. - Enhanced drive and mail services with improved handling of file uploads and metadata enrichment. - Implemented new API token management features, including creation, listing, and revocation of tokens. - Added tests for new functionalities in drive and mail services to ensure reliability and correctness.
66 lines
2.3 KiB
Go
66 lines
2.3 KiB
Go
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/ultisuite/ulti-backend/internal/api/apiresponse"
|
|
"github.com/ultisuite/ulti-backend/internal/apitokens"
|
|
)
|
|
|
|
func EnforceApiTokenPolicy() func(http.Handler) http.Handler {
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
auth := ApiTokenFromContext(r.Context())
|
|
if auth == nil {
|
|
next.ServeHTTP(w, r)
|
|
return
|
|
}
|
|
|
|
if strings.HasPrefix(r.URL.Path, "/api/v1/search") {
|
|
reqs := apitokens.SearchRequirements(r.URL.Query().Get("types"))
|
|
for _, req := range reqs {
|
|
if !apitokens.AllowsRequirement(auth, req) {
|
|
apiresponse.WriteError(w, r, http.StatusForbidden, apiresponse.CodeAuthForbidden, "insufficient api token permission", nil)
|
|
return
|
|
}
|
|
}
|
|
accountID := apitokens.ExtractMailAccountID(r.URL.Path, r.URL.Query().Get("account_id"))
|
|
if accountID != "" && !apitokens.AllowsMailAccount(auth, accountID) {
|
|
apiresponse.WriteError(w, r, http.StatusForbidden, apiresponse.CodeAuthForbidden, "mail account out of token scope", nil)
|
|
return
|
|
}
|
|
next.ServeHTTP(w, r)
|
|
return
|
|
}
|
|
|
|
req, ok := apitokens.RequirementForRequest(r.Method, r.URL.Path, r.URL.Query().Get("types"))
|
|
if !ok {
|
|
apiresponse.WriteError(w, r, http.StatusForbidden, apiresponse.CodeAuthForbidden, "route not allowed for api token", nil)
|
|
return
|
|
}
|
|
if !apitokens.AllowsRequirement(auth, req) {
|
|
apiresponse.WriteError(w, r, http.StatusForbidden, apiresponse.CodeAuthForbidden, "insufficient api token permission", nil)
|
|
return
|
|
}
|
|
|
|
switch req.ScopeHint {
|
|
case apitokens.ScopeMailAccountQuery, apitokens.ScopeMailAccountPath:
|
|
accountID := apitokens.ExtractMailAccountID(r.URL.Path, r.URL.Query().Get("account_id"))
|
|
if accountID != "" && !apitokens.AllowsMailAccount(auth, accountID) {
|
|
apiresponse.WriteError(w, r, http.StatusForbidden, apiresponse.CodeAuthForbidden, "mail account out of token scope", nil)
|
|
return
|
|
}
|
|
case apitokens.ScopeDrivePathFromURL:
|
|
drivePath := apitokens.ExtractDrivePathFromURL(r.URL.Path)
|
|
if drivePath != "" && !apitokens.AllowsDrivePath(auth, drivePath) {
|
|
apiresponse.WriteError(w, r, http.StatusForbidden, apiresponse.CodeAuthForbidden, "drive path out of token scope", nil)
|
|
return
|
|
}
|
|
}
|
|
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|
|
}
|