Commit f3cc21ea authored by Ikram Haq's avatar Ikram Haq
Browse files

Refactor appRegistrationPOST and appRegistrationPUT for improved readability,...

Refactor appRegistrationPOST and appRegistrationPUT for improved readability, consistency, and error handling.
parent cce416a9
Loading
Loading
Loading
Loading
+86 −88
Original line number Diff line number Diff line
@@ -659,105 +659,102 @@ func appRegistrationPOST(w http.ResponseWriter, r *http.Request) {

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")

	// Decode the request body into AppInfo struct
	// Parse request body into AppInfo struct
	var appInfo AppInfo
	err := json.NewDecoder(r.Body).Decode(&appInfo)
	if err != nil {
		log.Error(err.Error())
		errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest)
	if err := json.NewDecoder(r.Body).Decode(&appInfo); err != nil {
		log.Error("Error decoding request body:", err)
		errHandlerProblemDetails(w, "Invalid request body.", http.StatusBadRequest)
		return
	}
	log.Info("appRegistrationPOST: appInfo: ", appInfo)
	log.Info("appRegistrationPOST: Received appInfo:", appInfo)

	// Validation of mandatory parameters
	// Validate required fields
	if appInfo.AppName == "" {
		log.Error("Mandatory AppName parameter not present")
		errHandlerProblemDetails(w, "Mandatory AppName parameter not present", http.StatusBadRequest)
		log.Error("Missing mandatory parameter: AppName")
		errHandlerProblemDetails(w, "Mandatory attribute AppName is missing.", http.StatusBadRequest)
		return
	}

	if appInfo.AppInstanceId == "" {
		log.Error("Mandatory appInstanceId parameter should be present")
		errHandlerProblemDetails(w, "Mandatory attribute appInstanceId is missing in the request body.", http.StatusBadRequest)
		log.Error("Missing mandatory parameter: AppInstanceId")
		errHandlerProblemDetails(w, "Mandatory attribute AppInstanceId is missing.", http.StatusBadRequest)
		return
	}

	if !appInfo.IsInsByMec && appInfo.Endpoint == nil {
		log.Error("Shall be present when IsInsByMec is FALSE")
		errHandlerProblemDetails(w, "Endpoint shall be present when IsInsByMec is FALSE.", http.StatusBadRequest)
		log.Error("Endpoint is required when IsInsByMec is FALSE")
		errHandlerProblemDetails(w, "Endpoint is required when IsInsByMec is FALSE.", http.StatusBadRequest)
		return
	}
	// Process appProfile if present

	// Process appProfile if provided
	if appInfo.AppProfile != nil {
		// Validate appProvider, endpoint, and other fields as per mapping to EASProfile
		// Validate appProvider and other fields mapped to EASProfile
		if appInfo.AppProvider != appInfo.AppProfile.ProvId {
			log.Error("appProvider in AppInfo does not match provId in appProfile")
			errHandlerProblemDetails(w, "appProvider and provId must be consistent", http.StatusBadRequest)
			log.Error("Mismatch between appProvider in AppInfo and provId in appProfile")
			errHandlerProblemDetails(w, "appProvider and provId must match.", http.StatusBadRequest)
			return
		}

		if appInfo.AppProfile != nil {
		if !reflect.DeepEqual(getEndpointUris(appInfo.Endpoint), getProfileEndpointUris(appInfo.AppProfile.EndPt)) {
				log.Error("endpoint in AppInfo does not match endPt in appProfile")
				errHandlerProblemDetails(w, "Endpoint and endPt must be consistent", http.StatusBadRequest)
			log.Error("Mismatch between endpoint in AppInfo and endPt in appProfile")
			errHandlerProblemDetails(w, "Endpoint and endPt must match.", http.StatusBadRequest)
			return
		}
		}

		if appInfo.AppProfile.EasId == "" {
			log.Error("Mandatory easId parameter should be present")
			errHandlerProblemDetails(w, "Mandatory attribute easId is missing in the request body.", http.StatusBadRequest)
			log.Error("Missing mandatory parameter: easId")
			errHandlerProblemDetails(w, "Mandatory attribute easId is missing.", http.StatusBadRequest)
			return
		}

		if appInfo.AppName != appInfo.AppProfile.EasId {
			log.Error("AppName in AppInfo does not match EasId in appProfile")
			errHandlerProblemDetails(w, "AppName and EasId must be consistent", http.StatusBadRequest)
			log.Error("Mismatch between AppName in AppInfo and EasId in appProfile")
			errHandlerProblemDetails(w, "AppName and EasId must match.", http.StatusBadRequest)
			return
		}
		// Additional consistency checks for fields like scheds, svcArea, etc., based on appProfile attributes
		// Additional checks for attributes such as scheds, svcArea, etc., as required.
	}

	// Get App instance
	log.Info("appRegistrationPOST: appInfo.AppInstanceId: ", appInfo.AppInstanceId)
	// Retrieve App instance information
	log.Info("appRegistrationPOST: Processing AppInstanceId:", appInfo.AppInstanceId)
	appId, err := getAppInfo(appInfo.AppInstanceId)
	if err != nil {
		log.Error(err.Error())
		errHandlerProblemDetails(w, err.Error(), http.StatusNotFound)
		log.Error("Error retrieving app instance:", err)
		errHandlerProblemDetails(w, "App instance not found.", http.StatusNotFound)
		return
	}
	log.Info("appRegistrationPOST: appId: ", appId)
	log.Info("appRegistrationPOST: Retrieved appId:", appId)

	// Validate App info
	// Validate the retrieved AppInfo
	code, problemDetails, err := validateAppInfo(appId)
	if err != nil {
		log.Error(err.Error())
		log.Error("Error validating app info:", err)
		if problemDetails != "" {
			w.WriteHeader(code)
			fmt.Fprint(w, problemDetails)
		} else {
			errHandlerProblemDetails(w, err.Error(), code)
			errHandlerProblemDetails(w, "Validation error.", code)
		}
		return
	}

	// Set the application info in Redis
	// Store AppInfo in Redis
	keyName := baseKey + "appInfo:" + appInfo.AppInstanceId
	log.Info("appRegistrationPOST: keyName: ", keyName)
	log.Info("appRegistrationPOST: Storing data with key:", keyName)
	if err := rc.JSONSetEntry(keyName, ".", convertAppInfoToJson(&appInfo)); err != nil {
		log.Error("Unable to store new Registration in redis")
		errHandlerProblemDetails(w, "Unable to store new Registration in redis", http.StatusInternalServerError)
		log.Error("Failed to store registration in Redis:", err)
		errHandlerProblemDetails(w, "Server error. Could not store registration.", http.StatusInternalServerError)
		return
	}

	// Create a unique link for every subscription and concatenate subscription to it
	// Generate resource URI for the created app registration
	resourceURI := hostUrl.String() + basePath + "registrations/" + appInfo.AppInstanceId
	log.Info("appRegistrationPOST: resourceUDI: ", resourceURI)
	log.Info("appRegistrationPOST: Generated resource URI:", resourceURI)
	w.Header().Set("Location", resourceURI)

	// Prepare & send response
	// Send JSON response with status 201 Created
	jsonResponse := convertAppInfoToJson(&appInfo)
	// On successful registration, return 201 Created with the response body
	w.WriteHeader(http.StatusCreated)
	fmt.Fprint(w, jsonResponse)
}
@@ -839,85 +836,86 @@ func appRegistrationPUT(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	vars := mux.Vars(r)
	appInstanceId := vars["appInstanceId"]
	log.Info("appRegistrationPUT: appInstanceId: ", appInstanceId)
	log.Info("appRegistrationPUT: Received appInstanceId:", appInstanceId)

	// Read JSON input stream provided in the Request, and stores it in the buffer of a Decoder object
	decoder := json.NewDecoder(r.Body)
	// Decode function return strings containing the text provided in the request body
	// Decode JSON input from request body into AppInfo structure
	var appInfoPut AppInfo
	err := decoder.Decode(&appInfoPut)
	if err != nil {
		log.Error(err.Error())
		errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest)
	if err := json.NewDecoder(r.Body).Decode(&appInfoPut); err != nil {
		log.Error("Error decoding request body:", err)
		errHandlerProblemDetails(w, "Invalid request body.", http.StatusBadRequest)
		return
	}
	log.Info("appRegistrationPUT: appInfoPut: ", appInfoPut)
	log.Info("appRegistrationPUT: Parsed appInfoPut:", appInfoPut)

	// Check if the appInfo exists in Redis for the given appInstanceId
	keyName := baseKey + "appInfo:" + appInstanceId
	log.Info("appRegistrationPUT: keyName: ", keyName)
	log.Info("appRegistrationPUT: Checking existence of key:", keyName)
	jsonAppInfo, _ := rc.JSONGetEntry(keyName, ".")
	if jsonAppInfo == "" {
		log.Error("appInfo not found against the provided appInstanceId")
		errHandlerProblemDetails(w, "appInfo not found against the provided appInstanceId", http.StatusNotFound)
		log.Error("No appInfo found for provided appInstanceId")
		errHandlerProblemDetails(w, "appInfo not found for the provided appInstanceId", http.StatusNotFound)
		return
	}

	if appInfoPut.AppInstanceId != "" {
		if appInstanceId != appInfoPut.AppInstanceId {
			log.Error("appInstnaceId provided in endpoint and in request body not matching")
			errHandlerProblemDetails(w, "appInstanceId provided in endpoint and in request body not matching", http.StatusNotFound)
	// Validate appInstanceId consistency between URL and request body
	if appInfoPut.AppInstanceId != "" && appInstanceId != appInfoPut.AppInstanceId {
		log.Error("appInstanceId mismatch between endpoint and request body")
		errHandlerProblemDetails(w, "appInstanceId in endpoint and request body do not match", http.StatusBadRequest)
		return
	}
	}

	// Validate required parameters
	if appInfoPut.AppName == "" {
		log.Error("Mandatory AppName parameter not present")
		errHandlerProblemDetails(w, "Mandatory AppName parameter not present", http.StatusBadRequest)
		log.Error("Missing mandatory parameter: AppName")
		errHandlerProblemDetails(w, "Mandatory attribute AppName is missing.", http.StatusBadRequest)
		return
	}

	if !appInfoPut.IsInsByMec && appInfoPut.Endpoint == nil {
		log.Error("Shall be present when IsInsByMec is FALSE")
		errHandlerProblemDetails(w, "Shall be present when IsInsByMec is FALSE.", http.StatusBadRequest)
		log.Error("Endpoint is required when IsInsByMec is FALSE")
		errHandlerProblemDetails(w, "Endpoint is required when IsInsByMec is FALSE.", http.StatusBadRequest)
		return
	}
	// Process appProfile if present

	// Process appProfile if provided
	if appInfoPut.AppProfile != nil {
		// Validate appProvider, endpoint, and other fields as per mapping to EASProfile
		// Validate appProvider and associated fields as per EASProfile mapping
		if appInfoPut.AppProvider != appInfoPut.AppProfile.ProvId {
			log.Error("appProvider in AppInfo does not match provId in appProfile")
			errHandlerProblemDetails(w, "appProvider and provId must be consistent", http.StatusBadRequest)
			log.Error("Mismatch between appProvider in AppInfo and provId in appProfile")
			errHandlerProblemDetails(w, "appProvider and provId must match.", http.StatusBadRequest)
			return
		}

		if appInfoPut.AppProfile != nil {
		if !reflect.DeepEqual(getEndpointUris(appInfoPut.Endpoint), getProfileEndpointUris(appInfoPut.AppProfile.EndPt)) {
				log.Error("endpoint in AppInfo does not match endPt in appProfile")
				errHandlerProblemDetails(w, "Endpoint and endPt must be consistent", http.StatusBadRequest)
			log.Error("Mismatch between endpoint in AppInfo and endPt in appProfile")
			errHandlerProblemDetails(w, "Endpoint and endPt must match.", http.StatusBadRequest)
			return
		}
		}

		if appInfoPut.AppProfile.EasId == "" {
			log.Error("Mandatory easId parameter should be present")
			errHandlerProblemDetails(w, "Mandatory attribute easId is missing in the request body.", http.StatusBadRequest)
			log.Error("Missing mandatory parameter: easId")
			errHandlerProblemDetails(w, "Mandatory attribute easId is missing.", http.StatusBadRequest)
			return
		}

		if appInfoPut.AppName != appInfoPut.AppProfile.EasId {
			log.Error("AppName in AppInfo does not match EasId in appProfile")
			errHandlerProblemDetails(w, "AppName and EasId must be consistent", http.StatusBadRequest)
			log.Error("Mismatch between AppName in AppInfo and EasId in appProfile")
			errHandlerProblemDetails(w, "AppName and EasId must match.", http.StatusBadRequest)
			return
		}
		// Additional consistency checks for fields like scheds, svcArea, etc., based on appProfile attributes
		// Additional consistency checks for fields such as scheds, svcArea, etc., as required.
	}

	// Set appInstanceId in appInfoPut and store in Redis
	appInfoPut.AppInstanceId = appInstanceId

	// Store appInfo key in redis
	err = rc.JSONSetEntry(baseKey+"appInfo:"+appInstanceId, ".", convertAppInfoToJson(&appInfoPut))
	if err != nil {
		log.Error("Failed to store AppInfo in the redis DB: ", err)
	log.Info("appRegistrationPUT: Storing updated appInfo for appInstanceId:", appInstanceId)
	if err := rc.JSONSetEntry(keyName, ".", convertAppInfoToJson(&appInfoPut)); err != nil {
		log.Error("Failed to store updated AppInfo in Redis:", err)
		errHandlerProblemDetails(w, "Server error. Could not store updated appInfo.", http.StatusInternalServerError)
		return
	}

	// Respond with status 204 No Content to indicate successful update
	w.WriteHeader(http.StatusNoContent)
}