diff --git a/go-apps/meep-ams/server/ams.go b/go-apps/meep-ams/server/ams.go index e6e04c7dd1c58803ba6f9c4d67c85b63ca9437e9..fd9d98c8f4a0f929dac88e10e3cce942a3016e3b 100644 --- a/go-apps/meep-ams/server/ams.go +++ b/go-apps/meep-ams/server/ams.go @@ -148,6 +148,19 @@ func notImplemented(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotImplemented) } +type RegisterationInfoList struct { + Registrations []RegistrationInfo + Filters *FilterParameters +} + +type FilterParameters struct { + filter string + all_fields string + fields string + exclude_fields string + exclude_default string +} + // Init - App Mobility Service initialization func Init() (err error) { @@ -1205,8 +1218,10 @@ func subscriptionLinkListSubscriptionsGet(w http.ResponseWriter, r *http.Request u, _ := url.Parse(r.URL.String()) q := u.Query() validQueryParams := []string{"subscriptionType"} - if !validateQueryParams(q, validQueryParams) { - w.WriteHeader(http.StatusBadRequest) + err := validateQueryParams(q, validQueryParams) + if err != nil { + + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) return } @@ -1475,18 +1490,46 @@ func appMobilityServiceByIdDELETE(w http.ResponseWriter, r *http.Request) { func appMobilityServiceGET(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=UTF-8") + // Validate query parameters + u, _ := url.Parse(r.URL.String()) + q := u.Query() + validParams := []string{"filter", "All_fields", "Fields", "Exclude_fields", "Exclude_default"} + err := validateQueryParams(q, validParams) + if err != nil { + print("Query Parameter error") + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } + + // Parse query parameters + filters := q.Get("filter") + allFields := q.Get("all_fields") + // field := q["fields"] + // excludeFields := q["exclude_fields"] + // excludeDefault := q.Get("exclude_default") + + regInfoList := &RegisterationInfoList{ + Filters: &FilterParameters{ + filter: filters, + all_fields: allFields, + }, + Registrations: make([]RegistrationInfo, 0), + } + // Get all AMS Registration Info - regInfoList := make([]RegistrationInfo, 0) + //regInfoList := make([]RegistrationInfo, 0) key := baseKey + "svc:*:info" - err := rc.ForEachJSONEntry(key, populateRegInfoList, ®InfoList) + + err = rc.ForEachJSONEntry(key, populateRegInfoList, regInfoList) + if err != nil { log.Error(err.Error()) errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) return } - // Send response - jsonResponse, err := json.Marshal(regInfoList) + // Prepare & send response + jsonResponse, err := json.Marshal(regInfoList.Registrations) if err != nil { log.Error(err.Error()) errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) @@ -1498,21 +1541,275 @@ func appMobilityServiceGET(w http.ResponseWriter, r *http.Request) { } func populateRegInfoList(key string, jsonEntry string, response interface{}) error { - regInfoList := response.(*[]RegistrationInfo) - if regInfoList == nil { - return errors.New("Response not defined") + data := response.(*RegisterationInfoList) + if data == nil { + return errors.New("response not defined") } // Retrieve registration info from DB var regInfo RegistrationInfo err := json.Unmarshal([]byte(jsonEntry), ®Info) + println("keysss", key) if err != nil { return err } - *regInfoList = append(*regInfoList, regInfo) + + // Filter services + if data.Filters != nil { + + if data.Filters.filter != "" { + + filterField := data.Filters.filter + // Split filterField into operator, attribute, and value + filterField = strings.Trim(filterField, "()") + filterParts := strings.SplitN(filterField, ",", 3) + if len(filterParts) != 3 { + return nil + } + operator := filterParts[0] + attribute := filterParts[1] + value := filterParts[2] + + // Apply filters based on attribute + switch attribute { + case "appMobilityServiceId": + if !applyStringFilter(operator, regInfo.AppMobilityServiceId, value) { + return nil + } + + case "serviceConsumerId.appInstanceId": + if !applyStringFilter(operator, regInfo.ServiceConsumerId.AppInstanceId, value) { + return nil + } + + case "serviceConsumerId.mepId": + if !applyStringFilter(operator, regInfo.ServiceConsumerId.MepId, value) { + return nil + } + + case "deviceInformation.associateId": + matched := false + for _, deviceInfo := range regInfo.DeviceInformation { + if applyStringFilter(operator, deviceInfo.AssociateId.Value, value) { + matched = true + break + } + } + if !matched { + return nil + } + + // case "deviceInformation.contextTransferState": + // matched := false + // for _, deviceInfo := range regInfo.DeviceInformation { + // if applyEnumFilter(operator, string(deviceInfo.ContextTransferState.val), value) { + // matched = true + // break + // } + // } + // if !matched { + // return fmt.Errorf("filter mismatch: deviceInformation.contextTransferState") + // } + + case "expiryTime": + expiryTime, err := strconv.ParseUint(value, 10, 32) + if err != nil { + return nil + } + if !applyNumericFilter(operator, uint32(regInfo.ExpiryTime), uint32(expiryTime)) { + return nil + } + + default: + return nil + } + + } + + } + data.Registrations = append(data.Registrations, regInfo) return nil } +// Helper functions for applying filters +func applyStringFilter(operator, fieldValue, filterValue string) bool { + switch operator { + case "eq": + return fieldValue == filterValue + case "neq": + return fieldValue != filterValue + case "cont": + return strings.Contains(fieldValue, filterValue) + case "ncont": + return !strings.Contains(fieldValue, filterValue) + case "in": + values := strings.Split(filterValue, ",") + for _, v := range values { + if fieldValue == v { + return true + } + } + return false + case "nin": + values := strings.Split(filterValue, ",") + for _, v := range values { + if fieldValue == v { + return false + } + } + return true + case "gt": + return fieldValue > filterValue + case "gte": + return fieldValue >= filterValue + case "lt": + return fieldValue < filterValue + case "lte": + return fieldValue <= filterValue + default: + return false + } +} + +func applyEnumFilter(operator, fieldValue, filterValue string) bool { + return applyStringFilter(operator, fieldValue, filterValue) +} + +func applyNumericFilter(operator string, fieldValue, filterValue uint32) bool { + switch operator { + case "eq": + return fieldValue == filterValue + case "neq": + return fieldValue != filterValue + case "gt": + return fieldValue > filterValue + case "gte": + return fieldValue >= filterValue + case "lt": + return fieldValue < filterValue + case "lte": + return fieldValue <= filterValue + default: + return false + } +} + +// Original +// func populateRegInfoList(key string, jsonEntry string, response interface{}) error { +// data := response.(*RegisterationInfoList) +// if data == nil { +// return errors.New("response not defined") +// } + +// // Retrieve registration info from DB +// var regInfo RegistrationInfo +// err := json.Unmarshal([]byte(jsonEntry), ®Info) +// println("keysss", key) +// if err == nil { +// return err +// } + +// // Filter services +// if data.Filters != nil { + +// if data.Filters.filter != "" { +// filterField := data.Filters.filter +// if regInfo.AppMobilityServiceId == "" || (filterField != regInfo.AppMobilityServiceId) { +// return nil +// } +// } + +// } + +// data.Registrations = append(data.Registrations, regInfo) +// return nil +// } + +// filterRegistrationInfo applies filtering based on the provided filters. +// func filterRegistrationInfo(regInfoList []RegistrationInfo, filters []string) []RegistrationInfo { +// var filteredList []RegistrationInfo + +// for _, regInfo := range regInfoList { +// match := true + +// // Iterate over filters to apply them one by one +// for _, filter := range filters { +// filterParts := strings.Split(filter, ":") +// if len(filterParts) != 2 { +// // Invalid filter format (e.g., "key:value") +// continue +// } +// key := filterParts[0] +// value := filterParts[1] + +// // Apply filter based on key-value pairs +// switch key { +// case "appMobilityServiceId": +// if regInfo.AppMobilityServiceId != value { +// match = false +// } +// case "appInstanceId": +// if regInfo.ServiceConsumerId.AppInstanceId != value { +// match = false +// } +// case "mepId": +// if regInfo.ServiceConsumerId.MepId != value { +// match = false +// } +// case "associateId": +// // Check if any device has the associateId value +// found := false +// for _, device := range regInfo.DeviceInformation { +// if device.AssociateId == value { +// found = true +// break +// } +// } +// if !found { +// match = false +// } +// case "expiryTime": +// expiryTime, err := strconv.Atoi(value) +// if err != nil || regInfo.ExpiryTime != uint32(expiryTime) { +// match = false +// } +// default: +// // If filter key is not recognized, skip it +// continue +// } + +// // If any filter condition doesn't match, we stop checking further +// if !match { +// break +// } +// } + +// // If all filters matched, add to the result list +// if match { +// filteredList = append(filteredList, regInfo) +// } +// } + +// return filteredList +// } + +// func populateRegInfoList(key string, jsonEntry string, response interface{}) error { +// regInfoList := response.(*[]RegistrationInfo) +// if regInfoList == nil { +// return errors.New("Response not defined") +// } + +// // Retrieve registration info from DB +// var regInfo RegistrationInfo +// err := json.Unmarshal([]byte(jsonEntry), ®Info) +// if err != nil { +// return err +// } + +// *regInfoList = append(*regInfoList, regInfo) +// return nil +// } + func cleanUp() { log.Info("Terminate all") @@ -2324,21 +2621,22 @@ func delTrackedDevInfo(svcId string, address string) error { return nil } -func validateQueryParams(params url.Values, validParamList []string) bool { +func validateQueryParams(params url.Values, validParams []string) error { for param := range params { found := false - for _, validParam := range validParamList { + for _, validParam := range validParams { if param == validParam { found = true break } } if !found { - log.Error("Invalid query param: ", param) - return false + err := errors.New("Invalid query param: " + param) + log.Error(err.Error()) + return err } } - return true + return nil } func validateQueryParamValue(val string, validValues []string) bool {