routebuilder_fasthttp.go 10.43 KiB
//  +build fasthttp
package routebuildermdl
import (
	"context"
	"coresls/servers/coresls/app/modules/constantmdl"
	"strings"
	"github.com/pquerna/ffjson/ffjson"
	routing "github.com/qiangxue/fasthttp-routing"
	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/statemdl"
	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/authmdl/jwtmdl"
	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/authmdl/roleenforcemdl"
	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/errormdl"
	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/loggermdl"
	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/servicebuildermdl"
	version "github.com/hashicorp/go-version"
	"github.com/tidwall/gjson"
// Init routing init
func Init(o, r, c *routing.RouteGroup, JWTKey string) {
	o.Post("/mql/state", statemdl.StateHandler)
	o.Post("/mql", OpenHandler)
	r.Post("/mql", RestrictedHandler)
	c.Post("/mql", RoleBasedHandler)
	o.Post("/heavymql", HeavyOpenHandler)
	r.Post("/heavymql", HeavyRestrictedHandler)
	c.Post("/heavymql", HeavyRoleBasedHandler)
	jwtmdl.GlobalJWTKey = JWTKey
func commonHandler(c *routing.Context, isRestricted, isRoleBased, heavyDataActivity bool, principalObj servicebuildermdl.Principal) error {
	serviceHeader := string(c.Request.Header.Peek("Service-Header"))
	services := strings.Split(serviceHeader, ",")
	versionError := appVersioning(c)
	if versionError != nil {
		_, err := c.WriteString(versionError.Error())
		c.SetStatusCode(417)
		return err
	responseMap := make(map[string]responseData)
	var reqBody []byte
	reqBody = c.Request.Body()
	requestBody := gjson.ParseBytes(reqBody)
	for i := 0; i < len(services); i++ {
		responseDataObj := responseData{}
		service := services[i]
		result, ab, isCompressed, errorCode, err := executeService(service, []byte(requestBody.Get(service).String()), isRestricted, isRoleBased, heavyDataActivity, principalObj)
		if errormdl.CheckErr1(err) != nil {
			if ab == nil {
				responseDataObj.ErrorCode = errorCode
				responseDataObj.Error = err.Error()
			} else {
				responseDataObj.Error = ab.GetErrorData()
				if responseDataObj.Error == nil {
					responseDataObj.Error = err.Error()
				errorCode := ab.GetErrorCode()
				if errorCode == 0 {
					errorCode = errormdl.EXPECTATIONFAILED
				responseDataObj.ErrorCode = errorCode
				if ab.TransactionEnable {
					loggermdl.LogError("transaction enabled rollback")
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
var err error // database transaction rollback if transaction is enabled switch ab.DatabaseType { case constantmdl.MYSQL: if ab.TXN != nil { loggermdl.LogError("MYSQL Transaction Rollbacked") err = ab.TXN.Rollback() if err != nil { responseDataObj.Error = err.Error() responseDataObj.ErrorCode = errormdl.MYSQLERROR } } case constantmdl.SQLSERVER: if ab.SQLServerTXN != nil { loggermdl.LogError("SQLSERVER Transaction Rollbacked") err = ab.SQLServerTXN.Rollback() if err != nil { responseDataObj.Error = err.Error() responseDataObj.ErrorCode = errormdl.MYSQLERROR } } case constantmdl.GraphDB: if ab.GraphDbTXN != nil { loggermdl.LogError("GRAPHDB Transaction Rollbacked") err = ab.GraphDbTXN.Discard(context.TODO()) if err != nil { responseDataObj.Error = err.Error() responseDataObj.ErrorCode = errormdl.GRAPHDBERROR } } default: loggermdl.LogError("Invalid database type while rollback transaction") } } } } else { if ab != nil { if ab.TransactionEnable { var err error switch ab.DatabaseType { case constantmdl.MYSQL: if ab.TXN != nil { loggermdl.LogError("MYSQL Transaction Commit") err = ab.TXN.Commit() if err != nil { responseDataObj.Error = err.Error() responseDataObj.ErrorCode = errormdl.MYSQLERROR } else { responseDataObj.Result = result responseDataObj.ErrorCode = errormdl.NOERROR } } case constantmdl.SQLSERVER: if ab.SQLServerTXN != nil { loggermdl.LogError("SQLSERVER Transaction Commit") err = ab.SQLServerTXN.Commit() if err != nil { responseDataObj.Error = err.Error() responseDataObj.ErrorCode = errormdl.SQLSERVERERROR } else { responseDataObj.Result = result
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
responseDataObj.ErrorCode = errormdl.NOERROR } } case constantmdl.GraphDB: if ab.SQLServerTXN != nil { loggermdl.LogError("GRAPHDB Transaction Commit") err = ab.GraphDbTXN.Commit(context.TODO()) if err != nil { responseDataObj.Error = err.Error() responseDataObj.ErrorCode = errormdl.GRAPHDBERROR } else { responseDataObj.Result = result responseDataObj.ErrorCode = errormdl.NOERROR } } default: loggermdl.LogError("Invalid database type while commit transaction") } } else { responseDataObj.Result = result responseDataObj.ErrorCode = errormdl.NOERROR } } else { responseDataObj.Result = result responseDataObj.ErrorCode = errormdl.NOERROR } } responseDataObj.IsCompressed = isCompressed responseDataObj = formatResponse(ab, responseDataObj) responseMap[service] = responseDataObj // Token extraction // if ab != nil { // token, ok := ab.GetDataString("MQLToken") // if !ok { // token = string(c.Request.Header.Peek("Authorization")) // token = strings.TrimPrefix(token, "Bearer") // token = strings.TrimSpace(token) // c.Response.Header.Set("Authorization", token) // } // c.Response.Header.Set("Authorization", token) // } else { // token := string(c.Request.Header.Peek("Authorization")) // token = strings.TrimPrefix(token, "Bearer") // token = strings.TrimSpace(token) // c.Response.Header.Set("Authorization", token) // } if ab != nil { token, ok := ab.GetDataString("MQLToken") if ok { c.Response.Header.Set("Authorization", token) } } } ba, _ := ffjson.Marshal(responseMap) _, err := c.Write(ba) c.SetStatusCode(200) return err } // OpenHandler for /o func OpenHandler(c *routing.Context) error { c.Response.Header.Set("content-type", "application/json") principal := servicebuildermdl.Principal{} principal.ClientIP = c.RemoteIP().String() commonHandler(c, false, false, false, principal)
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
return nil } // RestrictedHandler for /r func RestrictedHandler(c *routing.Context) error { c.Response.Header.Set("content-type", "application/json") pricipalObj, extractError := extractPricipalObject(c) if extractError != nil { loggermdl.LogError(extractError) _, err := c.WriteString(extractError.Error()) c.SetStatusCode(412) return err } pricipalObj.ClientIP = c.RemoteIP().String() commonHandler(c, true, false, false, pricipalObj) return nil } // RoleBasedHandler for /r/c func RoleBasedHandler(c *routing.Context) error { c.Response.Header.Set("content-type", "application/json") pricipalObj, extractError := extractPricipalObject(c) if extractError != nil { loggermdl.LogError(extractError) _, err := c.WriteString(extractError.Error()) c.SetStatusCode(412) return err } pricipalObj.ClientIP = c.RemoteIP().String() commonHandler(c, true, true, false, pricipalObj) return nil } // HeavyOpenHandler for /o func HeavyOpenHandler(c *routing.Context) error { c.Response.Header.Set("content-type", "application/json") principal := servicebuildermdl.Principal{} principal.ClientIP = c.RemoteIP().String() commonHandler(c, false, false, true, principal) return nil } // HeavyRestrictedHandler for /r func HeavyRestrictedHandler(c *routing.Context) error { c.Response.Header.Set("content-type", "application/json") pricipalObj, extractError := extractPricipalObject(c) if extractError != nil { loggermdl.LogError(extractError) _, err := c.WriteString(extractError.Error()) c.SetStatusCode(412) return err } pricipalObj.ClientIP = c.RemoteIP().String() commonHandler(c, true, false, true, pricipalObj) return nil } // HeavyRoleBasedHandler for /r/c func HeavyRoleBasedHandler(c *routing.Context) error { c.Response.Header.Set("content-type", "application/json") pricipalObj, extractError := extractPricipalObject(c) if extractError != nil { loggermdl.LogError(extractError) _, err := c.WriteString(extractError.Error()) c.SetStatusCode(412) return err } pricipalObj.ClientIP = c.RemoteIP().String() commonHandler(c, true, true, true, pricipalObj)
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
return nil } func appVersioning(c *routing.Context) error { if isAppVersionEnabled { appVersion := string(c.Request.Header.Peek("app-version")) if appVersion == "" { return errormdl.Wrap("No App version Found in request header") } ver, err := version.NewVersion(appVersion) if errormdl.CheckErr(err) != nil { return errormdl.CheckErr(err) } if isStrictMode { if !ver.Equal(applicationVersion) { return errormdl.Wrap("Application version mismatched") } } else { if ver.GreaterThan(applicationVersion) { return errormdl.Wrap("Server Version is outdated") } if ver.LessThan(minimumSupportedVersion) { return errormdl.Wrap("Client Version is outdated") } } } return nil } func extractPricipalObject(c *routing.Context) (servicebuildermdl.Principal, error) { principal := servicebuildermdl.Principal{} if jwtmdl.GlobalJWTKey == "" { return principal, errormdl.Wrap("No Global JWT key found") } claim, decodeError := jwtmdl.DecodeToken(&c.Request) if errormdl.CheckErr(decodeError) != nil { // loggermdl.LogError(decodeError) return principal, errormdl.CheckErr(decodeError) } groups, grperr := roleenforcemdl.GetGroupNames(claim, "groups") if errormdl.CheckErr(grperr) != nil { loggermdl.LogError(grperr) return principal, errormdl.CheckErr(grperr) } userID, _ := claim["userId"].(string) // if !ok { // loggermdl.LogError("Unable to parse UserID from JWT Token") // return principal, errormdl.Wrap("Unable to parse UserID from JWT Token") // } if len(userID) < 2 { loggermdl.LogError("UserID length is less than 2") return principal, errormdl.Wrap("UserID length is less than 2") } rawMetadata, ok := claim["metadata"] if ok { metadata, ok := rawMetadata.(string) if !ok { loggermdl.LogError("Unable to parse metadata from JWT Token") return principal, errormdl.Wrap("Unable to parse metadata from JWT Token") } principal.Metadata = metadata } principal.Groups = groups principal.UserID = userID principal.Token = string(c.Request.Header.Peek("Authorization")) return principal, nil
351352
}