diff --git a/.gitignore b/.gitignore
index 8846f37d175c053007ac8dee5e513c8b7b2b6256..ddc9524e0603833cf17d69606bfcfffb1a0edc83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,9 @@ log/
 vendor/
 public/
 
+node_modules/
+yarn.lock
+
 # emacs/vim
 GPATH
 GRTAGS
diff --git a/backend/WebUI/api_webui.go b/backend/WebUI/api_webui.go
index 8d1b24bed123ca6f7e695d8998bc94cf4d503957..0141033486b0119b9b7a419ecbad931433a81c4d 100644
--- a/backend/WebUI/api_webui.go
+++ b/backend/WebUI/api_webui.go
@@ -1,12 +1,14 @@
 package WebUI
 
 import (
+	"context"
 	"crypto/tls"
 	"encoding/json"
 	"fmt"
 	"net/http"
 	"os"
 	"reflect"
+	"strconv"
 	"strings"
 	"time"
 
@@ -24,15 +26,17 @@ import (
 )
 
 const (
-	authSubsDataColl = "subscriptionData.authenticationData.authenticationSubscription"
-	amDataColl       = "subscriptionData.provisionedData.amData"
-	smDataColl       = "subscriptionData.provisionedData.smData"
-	smfSelDataColl   = "subscriptionData.provisionedData.smfSelectionSubscriptionData"
-	amPolicyDataColl = "policyData.ues.amData"
-	smPolicyDataColl = "policyData.ues.smData"
-	flowRuleDataColl = "policyData.ues.flowRule"
-	userDataColl     = "userData"
-	tenantDataColl   = "tenantData"
+	authSubsDataColl  = "subscriptionData.authenticationData.authenticationSubscription"
+	amDataColl        = "subscriptionData.provisionedData.amData"
+	smDataColl        = "subscriptionData.provisionedData.smData"
+	smfSelDataColl    = "subscriptionData.provisionedData.smfSelectionSubscriptionData"
+	amPolicyDataColl  = "policyData.ues.amData"
+	smPolicyDataColl  = "policyData.ues.smData"
+	flowRuleDataColl  = "policyData.ues.flowRule"
+	qosFlowDataColl   = "policyData.ues.qosFlow"
+	userDataColl      = "userData"
+	tenantDataColl    = "tenantData"
+	msisdnSupiMapColl = "subscriptionData.msisdnSupiMap"
 )
 
 var httpsClient *http.Client
@@ -46,24 +50,30 @@ func init() {
 }
 
 func mapToByte(data map[string]interface{}) (ret []byte) {
-	ret, _ = json.Marshal(data)
+	ret, err := json.Marshal(data)
+	if err != nil {
+		logger.ProcLog.Errorf("mapToByte err: %+v", err)
+	}
 	return
 }
 
 func sliceToByte(data []map[string]interface{}) (ret []byte) {
-	ret, _ = json.Marshal(data)
+	ret, err := json.Marshal(data)
+	if err != nil {
+		logger.ProcLog.Errorf("sliceToByte err: %+v", err)
+	}
 	return
 }
 
 func toBsonM(data interface{}) (ret bson.M) {
-	tmp, _ := json.Marshal(data)
-	json.Unmarshal(tmp, &ret)
-	return
-}
-
-func toBsonA(data interface{}) (ret bson.A) {
-	tmp, _ := json.Marshal(data)
-	json.Unmarshal(tmp, &ret)
+	tmp, err := json.Marshal(data)
+	if err != nil {
+		logger.ProcLog.Errorf("toBsonM err: %+v", err)
+	}
+	err = json.Unmarshal(tmp, &ret)
+	if err != nil {
+		logger.ProcLog.Errorf("toBsonM err: %+v", err)
+	}
 	return
 }
 
@@ -78,13 +88,52 @@ func UnescapeDnn(dnnKey string) string {
 func setCorsHeader(c *gin.Context) {
 	c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
 	c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
-	c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
+	c.Writer.Header().Set(
+		"Access-Control-Allow-Headers",
+		"Content-Type, Content-Length, Accept-Encoding, "+
+			"X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With",
+	)
 	c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, PATCH, DELETE")
 }
 
+func getMsisdn(gpsis interface{}) string {
+	msisdn := ""
+	gpsisReflected := reflect.ValueOf(gpsis) // use reflect to range over interface{}
+	for i := 0; i < gpsisReflected.Len(); i++ {
+		gpsi := gpsisReflected.Index(i).Interface().(string) // transform type reflect.value to string
+		if strings.HasPrefix(gpsi, "msisdn-") {              // check if gpsi contain prefix "msisdn-"
+			msisdn = gpsi[7:]
+		}
+	}
+	return msisdn
+}
+
+func msisdnToSupi(ueId string) string {
+	if strings.HasPrefix(ueId, "msisdn-") {
+		filter := bson.M{"msisdn": ueId[7:]}
+		dbResult, err := mongoapi.RestfulAPIGetOne(msisdnSupiMapColl, filter)
+		if err != nil {
+			logger.ProcLog.Errorf("GetSupibyMsisdn err: %+v", err)
+		}
+		if dbResult != nil {
+			ueId = dbResult["ueId"].(string)
+		} else {
+			// db cannot find a supi mapped to msisdn, return null string for error detection
+			logger.ProcLog.Error("msisdn not found")
+			return ""
+		}
+	}
+	return ueId
+}
+
 func sendResponseToClient(c *gin.Context, response *http.Response) {
 	var jsonData interface{}
-	json.NewDecoder(response.Body).Decode(&jsonData)
+	err := json.NewDecoder(response.Body).Decode(&jsonData)
+	if err != nil {
+		logger.ProcLog.Errorf("sendResponseToClient err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
 	c.JSON(response.StatusCode, jsonData)
 }
 
@@ -93,7 +142,9 @@ func sendResponseToClientFilterTenant(c *gin.Context, response *http.Response, t
 	filterTenantIdOnly := bson.M{"tenantId": tenantId}
 	amDataList, err := mongoapi.RestfulAPIGetMany(amDataColl, filterTenantIdOnly)
 	if err != nil {
-		logger.WebUILog.Errorf("sendResponseToClientFilterTenant err: %+v", err)
+		logger.ProcLog.Errorf("sendResponseToClientFilterTenant err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 
 	tenantCheck := func(supi string) bool {
@@ -107,7 +158,12 @@ func sendResponseToClientFilterTenant(c *gin.Context, response *http.Response, t
 
 	// Response data.
 	var jsonData interface{}
-	json.NewDecoder(response.Body).Decode(&jsonData)
+	err = json.NewDecoder(response.Body).Decode(&jsonData)
+	if err != nil {
+		logger.ProcLog.Errorf("sendResponseToClientFilterTenant err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
 
 	s := reflect.ValueOf(jsonData)
 	if s.Kind() != reflect.Slice {
@@ -135,7 +191,7 @@ func sendResponseToClientFilterTenant(c *gin.Context, response *http.Response, t
 func GetSampleJSON(c *gin.Context) {
 	setCorsHeader(c)
 
-	logger.WebUILog.Infoln("Get a JSON Example")
+	logger.ProcLog.Infoln("Get a JSON Example")
 
 	var subsData SubsData
 
@@ -345,14 +401,22 @@ func JWT(email, userId, tenantId string) string {
 	claims["email"] = email
 	claims["tenantId"] = tenantId
 
-	tokenString, _ := token.SignedString([]byte(os.Getenv("SIGNINGKEY")))
+	tokenString, err := token.SignedString([]byte(os.Getenv("SIGNINGKEY")))
+	if err != nil {
+		logger.ProcLog.Errorf("JWT err: %+v", err)
+	}
 
 	return tokenString
 }
 
-func generateHash(password string) {
-	hash, _ := bcrypt.GenerateFromPassword([]byte(password), 12)
-	logger.WebUILog.Warnln("Password hash:", hash)
+func generateHash(password string) error {
+	hash, err := bcrypt.GenerateFromPassword([]byte(password), 12)
+	if err != nil {
+		logger.ProcLog.Errorf("generateHash err: %+v", err)
+		return err
+	}
+	logger.ProcLog.Warnln("Password hash:", hash)
+	return err
 }
 
 func Login(c *gin.Context) {
@@ -361,21 +425,28 @@ func Login(c *gin.Context) {
 	login := LoginRequest{}
 	err := json.NewDecoder(c.Request.Body).Decode(&login)
 	if err != nil {
-		logger.WebUILog.Warnln("JSON decode error", err)
+		logger.ProcLog.Warnln("JSON decode error", err)
 		c.JSON(http.StatusInternalServerError, gin.H{})
 		return
 	}
 
-	generateHash(login.Password)
+	err = generateHash(login.Password)
+	if err != nil {
+		logger.ProcLog.Errorf("Login err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
 
 	filterEmail := bson.M{"email": login.Username}
 	userData, err := mongoapi.RestfulAPIGetOne(userDataColl, filterEmail)
 	if err != nil {
-		logger.WebUILog.Errorf("Login err: %+v", err)
+		logger.ProcLog.Errorf("Login err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 
 	if len(userData) == 0 {
-		logger.WebUILog.Warnln("Can't find user email", login.Username)
+		logger.ProcLog.Warnln("Can't find user email", login.Username)
 		c.JSON(http.StatusForbidden, gin.H{})
 		return
 	}
@@ -384,7 +455,7 @@ func Login(c *gin.Context) {
 
 	err = bcrypt.CompareHashAndPassword([]byte(hash), []byte(login.Password))
 	if err != nil {
-		logger.WebUILog.Warnln("Password incorrect", login.Username)
+		logger.ProcLog.Warnln("Password incorrect", login.Username)
 		c.JSON(http.StatusForbidden, gin.H{})
 		return
 	}
@@ -392,12 +463,12 @@ func Login(c *gin.Context) {
 	userId := userData["userId"].(string)
 	tenantId := userData["tenantId"].(string)
 
-	logger.WebUILog.Warnln("Login success", login.Username)
-	logger.WebUILog.Warnln("userid", userId)
-	logger.WebUILog.Warnln("tenantid", tenantId)
+	logger.ProcLog.Warnln("Login success", login.Username)
+	logger.ProcLog.Warnln("userid", userId)
+	logger.ProcLog.Warnln("tenantid", tenantId)
 
 	token := JWT(login.Username, userId, tenantId)
-	logger.WebUILog.Warnln("token", token)
+	logger.ProcLog.Warnln("token", token)
 
 	oauth := OAuth{}
 	oauth.AccessToken = token
@@ -421,7 +492,6 @@ func ParseJWT(tokenStr string) (jwt.MapClaims, error) {
 	token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
 		return []byte(os.Getenv("SIGNINGKEY")), nil
 	})
-
 	if err != nil {
 		return nil, errors.Wrap(err, "ParseJWT error")
 	}
@@ -441,7 +511,7 @@ func CheckAuth(c *gin.Context) bool {
 	}
 }
 
-// Tenat ID
+// Tenant ID
 func GetTenantId(c *gin.Context) (string, error) {
 	tokenStr := c.GetHeader("Token")
 	if tokenStr == "admin" {
@@ -449,6 +519,7 @@ func GetTenantId(c *gin.Context) (string, error) {
 	}
 	claims, err := ParseJWT(tokenStr)
 	if err != nil {
+		c.JSON(http.StatusInternalServerError, gin.H{})
 		return "", errors.Wrap(err, "GetTenantId error")
 	}
 	return claims["tenantId"].(string), nil
@@ -465,11 +536,17 @@ func GetTenants(c *gin.Context) {
 
 	tenantDataInterface, err := mongoapi.RestfulAPIGetMany(tenantDataColl, bson.M{})
 	if err != nil {
-		logger.WebUILog.Errorf("GetTenants err: %+v", err)
+		logger.ProcLog.Errorf("GetTenants err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	var tenantData []Tenant
-	json.Unmarshal(sliceToByte(tenantDataInterface), &tenantData)
-
+	err = json.Unmarshal(sliceToByte(tenantDataInterface), &tenantData)
+	if err != nil {
+		logger.ProcLog.Errorf("GetTenants err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
 	c.JSON(http.StatusOK, tenantData)
 }
 
@@ -486,7 +563,9 @@ func GetTenantByID(c *gin.Context) {
 	filterTenantIdOnly := bson.M{"tenantId": tenantId}
 	tenantDataInterface, err := mongoapi.RestfulAPIGetOne(tenantDataColl, filterTenantIdOnly)
 	if err != nil {
-		logger.WebUILog.Errorf("GetTenantByID err: %+v", err)
+		logger.ProcLog.Errorf("GetTenantByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	if len(tenantDataInterface) == 0 {
 		c.JSON(http.StatusNotFound, bson.M{})
@@ -494,8 +573,12 @@ func GetTenantByID(c *gin.Context) {
 	}
 
 	var tenantData Tenant
-	json.Unmarshal(mapToByte(tenantDataInterface), &tenantData)
-
+	err = json.Unmarshal(mapToByte(tenantDataInterface), &tenantData)
+	if err != nil {
+		logger.ProcLog.Errorf("GetTenantByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
 	c.JSON(http.StatusOK, tenantData)
 }
 
@@ -520,7 +603,9 @@ func PostTenant(c *gin.Context) {
 	tenantBsonM := toBsonM(tenantData)
 	filterTenantIdOnly := bson.M{"tenantId": tenantData.TenantId}
 	if _, err := mongoapi.RestfulAPIPost(tenantDataColl, filterTenantIdOnly, tenantBsonM); err != nil {
-		logger.WebUILog.Errorf("PostTenant err: %+v", err)
+		logger.ProcLog.Errorf("PostTenant err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 
 	c.JSON(http.StatusOK, tenantData)
@@ -539,7 +624,9 @@ func PutTenantByID(c *gin.Context) {
 	filterTenantIdOnly := bson.M{"tenantId": tenantId}
 	tenantDataInterface, err := mongoapi.RestfulAPIGetOne(tenantDataColl, filterTenantIdOnly)
 	if err != nil {
-		logger.WebUILog.Errorf("PutTenantByID err: %+v", err)
+		logger.ProcLog.Errorf("PutTenantByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	if len(tenantDataInterface) == 0 {
 		c.JSON(http.StatusNotFound, bson.M{})
@@ -556,7 +643,9 @@ func PutTenantByID(c *gin.Context) {
 	tenantBsonM := toBsonM(tenantData)
 	filterTenantIdOnly = bson.M{"tenantId": tenantId}
 	if _, err := mongoapi.RestfulAPIPost(tenantDataColl, filterTenantIdOnly, tenantBsonM); err != nil {
-		logger.WebUILog.Errorf("PutTenantByID err: %+v", err)
+		logger.ProcLog.Errorf("PutTenantByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 
 	c.JSON(http.StatusOK, gin.H{})
@@ -574,13 +663,19 @@ func DeleteTenantByID(c *gin.Context) {
 	filterTenantIdOnly := bson.M{"tenantId": tenantId}
 
 	if err := mongoapi.RestfulAPIDeleteMany(amDataColl, filterTenantIdOnly); err != nil {
-		logger.WebUILog.Errorf("DeleteTenantByID err: %+v", err)
+		logger.ProcLog.Errorf("DeleteTenantByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	if err := mongoapi.RestfulAPIDeleteMany(userDataColl, filterTenantIdOnly); err != nil {
-		logger.WebUILog.Errorf("DeleteTenantByID err: %+v", err)
+		logger.ProcLog.Errorf("DeleteTenantByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	if err := mongoapi.RestfulAPIDeleteOne(tenantDataColl, filterTenantIdOnly); err != nil {
-		logger.WebUILog.Errorf("DeleteTenantByID err: %+v", err)
+		logger.ProcLog.Errorf("DeleteTenantByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 
 	c.JSON(http.StatusOK, gin.H{})
@@ -591,7 +686,7 @@ func GetTenantById(tenantId string) map[string]interface{} {
 	filterTenantIdOnly := bson.M{"tenantId": tenantId}
 	tenantData, err := mongoapi.RestfulAPIGetOne(tenantDataColl, filterTenantIdOnly)
 	if err != nil {
-		logger.WebUILog.Errorf("GetTenantById err: %+v", err)
+		logger.ProcLog.Errorf("GetTenantById err: %+v", err)
 		return nil
 	}
 	return tenantData
@@ -615,12 +710,20 @@ func GetUsers(c *gin.Context) {
 	filterTenantIdOnly := bson.M{"tenantId": tenantId}
 	userDataInterface, err := mongoapi.RestfulAPIGetMany(userDataColl, filterTenantIdOnly)
 	if err != nil {
-		logger.WebUILog.Errorf("GetUsers err: %+v", err)
+		logger.ProcLog.Errorf("GetUsers err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 
 	var userData []User
-	json.Unmarshal(sliceToByte(userDataInterface), &userData)
-	for pos, _ := range userData {
+	err = json.Unmarshal(sliceToByte(userDataInterface), &userData)
+	if err != nil {
+		logger.ProcLog.Errorf("GetUsers err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
+
+	for pos := range userData {
 		userData[pos].EncryptedPassword = ""
 	}
 
@@ -645,7 +748,9 @@ func GetUserByID(c *gin.Context) {
 	filterUserIdOnly := bson.M{"tenantId": tenantId, "userId": userId}
 	userDataInterface, err := mongoapi.RestfulAPIGetOne(userDataColl, filterUserIdOnly)
 	if err != nil {
-		logger.WebUILog.Errorf("GetUserByID err: %+v", err)
+		logger.ProcLog.Errorf("GetUserByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	if len(userDataInterface) == 0 {
 		c.JSON(http.StatusNotFound, bson.M{})
@@ -653,7 +758,13 @@ func GetUserByID(c *gin.Context) {
 	}
 
 	var userData User
-	json.Unmarshal(mapToByte(userDataInterface), &userData)
+	err = json.Unmarshal(mapToByte(userDataInterface), &userData)
+	if err != nil {
+		logger.ProcLog.Errorf("GetUserByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
+
 	userData.EncryptedPassword = ""
 
 	c.JSON(http.StatusOK, userData)
@@ -682,23 +793,32 @@ func PostUserByID(c *gin.Context) {
 	filterEmail := bson.M{"email": userData.Email}
 	userWithEmailData, err := mongoapi.RestfulAPIGetOne(userDataColl, filterEmail)
 	if err != nil {
-		logger.WebUILog.Errorf("PostUserByID err: %+v", err)
+		logger.ProcLog.Errorf("PostUserByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	if len(userWithEmailData) != 0 {
-		logger.WebUILog.Warnln("Email already exists", userData.Email)
+		logger.ProcLog.Warnln("Email already exists", userData.Email)
 		c.JSON(http.StatusForbidden, gin.H{})
 		return
 	}
 
 	userData.TenantId = tenantId
 	userData.UserId = uuid.Must(uuid.NewRandom()).String()
-	hash, _ := bcrypt.GenerateFromPassword([]byte(userData.EncryptedPassword), 12)
+	hash, err := bcrypt.GenerateFromPassword([]byte(userData.EncryptedPassword), 12)
+	if err != nil {
+		logger.ProcLog.Errorf("PostUserByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
 	userData.EncryptedPassword = string(hash)
 
 	userBsonM := toBsonM(userData)
 	filterUserIdOnly := bson.M{"tenantId": userData.TenantId, "userId": userData.UserId}
 	if _, err := mongoapi.RestfulAPIPost(userDataColl, filterUserIdOnly, userBsonM); err != nil {
-		logger.WebUILog.Errorf("PostUserByID err: %+v", err)
+		logger.ProcLog.Errorf("PostUserByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 
 	c.JSON(http.StatusOK, userData)
@@ -728,7 +848,9 @@ func PutUserByID(c *gin.Context) {
 	filterUserIdOnly := bson.M{"tenantId": tenantId, "userId": userId}
 	userDataInterface, err := mongoapi.RestfulAPIGetOne(userDataColl, filterUserIdOnly)
 	if err != nil {
-		logger.WebUILog.Errorf("PutUserByID err: %+v", err)
+		logger.ProcLog.Errorf("PutUserByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	if len(userDataInterface) == 0 {
 		c.JSON(http.StatusNotFound, bson.M{})
@@ -736,13 +858,20 @@ func PutUserByID(c *gin.Context) {
 	}
 
 	var userData User
-	json.Unmarshal(mapToByte(userDataInterface), &userData)
+	err = json.Unmarshal(mapToByte(userDataInterface), &userData)
+	if err != nil {
+		logger.ProcLog.Errorf("PutUserByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
 
 	if newUserData.Email != "" && newUserData.Email != userData.Email {
 		filterEmail := bson.M{"email": newUserData.Email}
 		sameEmailInterface, err := mongoapi.RestfulAPIGetOne(userDataColl, filterEmail)
 		if err != nil {
-			logger.WebUILog.Errorf("PutUserByID err: %+v", err)
+			logger.ProcLog.Errorf("PutUserByID err: %+v", err)
+			c.JSON(http.StatusInternalServerError, gin.H{})
+			return
 		}
 		if len(sameEmailInterface) != 0 {
 			c.JSON(http.StatusBadRequest, bson.M{})
@@ -752,13 +881,20 @@ func PutUserByID(c *gin.Context) {
 	}
 
 	if newUserData.EncryptedPassword != "" {
-		hash, _ := bcrypt.GenerateFromPassword([]byte(newUserData.EncryptedPassword), 12)
+		hash, err := bcrypt.GenerateFromPassword([]byte(newUserData.EncryptedPassword), 12)
+		if err != nil {
+			logger.ProcLog.Errorf("PutUserByID err: %+v", err)
+			c.JSON(http.StatusInternalServerError, gin.H{})
+			return
+		}
 		userData.EncryptedPassword = string(hash)
 	}
 
 	userBsonM := toBsonM(userData)
 	if _, err := mongoapi.RestfulAPIPost(userDataColl, filterUserIdOnly, userBsonM); err != nil {
-		logger.WebUILog.Errorf("PutUserByID err: %+v", err)
+		logger.ProcLog.Errorf("PutUserByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 
 	c.JSON(http.StatusOK, userData)
@@ -781,7 +917,9 @@ func DeleteUserByID(c *gin.Context) {
 
 	filterUserIdOnly := bson.M{"tenantId": tenantId, "userId": userId}
 	if err := mongoapi.RestfulAPIDeleteOne(userDataColl, filterUserIdOnly); err != nil {
-		logger.WebUILog.Errorf("DeleteUserByID err: %+v", err)
+		logger.ProcLog.Errorf("DeleteUserByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 
 	c.JSON(http.StatusOK, gin.H{})
@@ -791,7 +929,7 @@ func DeleteUserByID(c *gin.Context) {
 func GetSubscribers(c *gin.Context) {
 	setCorsHeader(c)
 
-	logger.WebUILog.Infoln("Get All Subscribers List")
+	logger.ProcLog.Infoln("Get All Subscribers List")
 
 	tokenStr := c.GetHeader("Token")
 
@@ -801,7 +939,7 @@ func GetSubscribers(c *gin.Context) {
 		claims, err = ParseJWT(tokenStr)
 	}
 	if err != nil {
-		logger.WebUILog.Errorln(err.Error())
+		logger.ProcLog.Errorln(err.Error())
 		c.JSON(http.StatusBadRequest, gin.H{
 			"cause": "Illegal Token",
 		})
@@ -811,26 +949,37 @@ func GetSubscribers(c *gin.Context) {
 	var subsList []SubsListIE = make([]SubsListIE, 0)
 	amDataList, err := mongoapi.RestfulAPIGetMany(amDataColl, bson.M{})
 	if err != nil {
-		logger.WebUILog.Errorf("GetSubscribers err: %+v", err)
+		logger.ProcLog.Errorf("GetSubscribers err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	for _, amData := range amDataList {
 		ueId := amData["ueId"]
 		servingPlmnId := amData["servingPlmnId"]
+		msisdn := getMsisdn(amData["gpsis"])
 		tenantId := amData["tenantId"]
 
 		filterUeIdOnly := bson.M{"ueId": ueId}
 		authSubsDataInterface, err := mongoapi.RestfulAPIGetOne(authSubsDataColl, filterUeIdOnly)
 		if err != nil {
-			logger.WebUILog.Errorf("GetSubscribers err: %+v", err)
+			logger.ProcLog.Errorf("GetSubscribers err: %+v", err)
+			c.JSON(http.StatusInternalServerError, gin.H{})
+			return
 		}
 
 		var authSubsData AuthSub
-		json.Unmarshal(mapToByte(authSubsDataInterface), &authSubsData)
+		err = json.Unmarshal(mapToByte(authSubsDataInterface), &authSubsData)
+		if err != nil {
+			logger.ProcLog.Errorf("GetSubscribers err: %+v", err)
+			c.JSON(http.StatusInternalServerError, gin.H{})
+			return
+		}
 
 		if tokenStr == "admin" || tenantId == claims["tenantId"].(string) {
 			tmp := SubsListIE{
 				PlmnID: servingPlmnId.(string),
 				UeId:   ueId.(string),
+				Msisdn: msisdn,
 			}
 			subsList = append(subsList, tmp)
 		}
@@ -842,59 +991,128 @@ func GetSubscribers(c *gin.Context) {
 func GetSubscriberByID(c *gin.Context) {
 	setCorsHeader(c)
 
-	logger.WebUILog.Infoln("Get One Subscriber Data")
+	logger.ProcLog.Infoln("Get One Subscriber Data")
 
 	var subsData SubsData
 
 	ueId := c.Param("ueId")
+	ueId = msisdnToSupi(ueId)
 	servingPlmnId := c.Param("servingPlmnId")
-
+	// checking whether msisdn is successfully transformed to supi or not
+	if ueId == "" {
+		logger.ProcLog.Errorf("GetSubscriberByID err: msisdn does not exists")
+		c.JSON(http.StatusNotFound, gin.H{
+			"cause": "msisdn does not exists",
+		})
+		return
+	}
 	filterUeIdOnly := bson.M{"ueId": ueId}
 	filter := bson.M{"ueId": ueId, "servingPlmnId": servingPlmnId}
 
 	authSubsDataInterface, err := mongoapi.RestfulAPIGetOne(authSubsDataColl, filterUeIdOnly)
 	if err != nil {
-		logger.WebUILog.Errorf("GetSubscriberByID err: %+v", err)
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	amDataDataInterface, err := mongoapi.RestfulAPIGetOne(amDataColl, filter)
 	if err != nil {
-		logger.WebUILog.Errorf("GetSubscriberByID err: %+v", err)
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	smDataDataInterface, err := mongoapi.RestfulAPIGetMany(smDataColl, filter)
 	if err != nil {
-		logger.WebUILog.Errorf("GetSubscriberByID err: %+v", err)
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	smfSelDataInterface, err := mongoapi.RestfulAPIGetOne(smfSelDataColl, filter)
 	if err != nil {
-		logger.WebUILog.Errorf("GetSubscriberByID err: %+v", err)
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	amPolicyDataInterface, err := mongoapi.RestfulAPIGetOne(amPolicyDataColl, filterUeIdOnly)
 	if err != nil {
-		logger.WebUILog.Errorf("GetSubscriberByID err: %+v", err)
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	smPolicyDataInterface, err := mongoapi.RestfulAPIGetOne(smPolicyDataColl, filterUeIdOnly)
 	if err != nil {
-		logger.WebUILog.Errorf("GetSubscriberByID err: %+v", err)
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	flowRuleDataInterface, err := mongoapi.RestfulAPIGetMany(flowRuleDataColl, filter)
 	if err != nil {
-		logger.WebUILog.Errorf("GetSubscriberByID err: %+v", err)
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
+	qosFlowInterface, err := mongoapi.RestfulAPIGetMany(qosFlowDataColl, filter)
+	if err != nil {
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 
 	var authSubsData models.AuthenticationSubscription
-	json.Unmarshal(mapToByte(authSubsDataInterface), &authSubsData)
+	if err := json.Unmarshal(mapToByte(authSubsDataInterface), &authSubsData); err != nil {
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
 	var amDataData models.AccessAndMobilitySubscriptionData
-	json.Unmarshal(mapToByte(amDataDataInterface), &amDataData)
+	if err := json.Unmarshal(mapToByte(amDataDataInterface), &amDataData); err != nil {
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
 	var smDataData []models.SessionManagementSubscriptionData
-	json.Unmarshal(sliceToByte(smDataDataInterface), &smDataData)
+	if err := json.Unmarshal(sliceToByte(smDataDataInterface), &smDataData); err != nil {
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
 	var smfSelData models.SmfSelectionSubscriptionData
-	json.Unmarshal(mapToByte(smfSelDataInterface), &smfSelData)
+	if err := json.Unmarshal(mapToByte(smfSelDataInterface), &smfSelData); err != nil {
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
 	var amPolicyData models.AmPolicyData
-	json.Unmarshal(mapToByte(amPolicyDataInterface), &amPolicyData)
+	if err := json.Unmarshal(mapToByte(amPolicyDataInterface), &amPolicyData); err != nil {
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
 	var smPolicyData models.SmPolicyData
-	json.Unmarshal(mapToByte(smPolicyDataInterface), &smPolicyData)
+	if err := json.Unmarshal(mapToByte(smPolicyDataInterface), &smPolicyData); err != nil {
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
 	var flowRules []FlowRule
-	json.Unmarshal(sliceToByte(flowRuleDataInterface), &flowRules)
+	if err := json.Unmarshal(sliceToByte(flowRuleDataInterface), &flowRules); err != nil {
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
+	var qosFlows []QosFlow
+	if err := json.Unmarshal(sliceToByte(qosFlowInterface), &qosFlows); err != nil {
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
+	}
+
+	if flowRules == nil {
+		flowRules = make([]FlowRule, 0)
+	}
+	if qosFlows == nil {
+		qosFlows = make([]QosFlow, 0)
+	}
 
 	for key, SnssaiData := range smPolicyData.SmPolicySnssaiData {
 		tmpSmPolicyDnnData := make(map[string]models.SmPolicyDnnData)
@@ -916,15 +1134,27 @@ func GetSubscriberByID(c *gin.Context) {
 		AmPolicyData:                      amPolicyData,
 		SmPolicyData:                      smPolicyData,
 		FlowRules:                         flowRules,
+		QosFlows:                          qosFlows,
 	}
 
 	c.JSON(http.StatusOK, subsData)
 }
 
 // Post subscriber by IMSI(ueId) and PlmnID(servingPlmnId)
+// PostSubscriberByID godoc
+// @Summary     CreateSubscriberByID
+// @Description Create subscriber by IMSI(ueId) and PlmnID(servingPlmnId)
+// @Accept       json
+// @Produce      json
+// @Param ueId path string true "imsi"
+// @Param servingPlmnId path string true "servingPlmnId"
+// @Param subdata body SubsData true "sub data"
+// @Success      201 "Create subscription success"
+// @Failure 400 {object} HTTPError "JSON format incorrect"
+// @Router  /subscriber/{ueId}/{servingPlmnId}/{userNumber} [post]
 func PostSubscriberByID(c *gin.Context) {
 	setCorsHeader(c)
-	logger.WebUILog.Infoln("Post One Subscriber Data")
+	logger.ProcLog.Infoln("Post One Subscriber Data")
 
 	var claims jwt.MapClaims = nil
 	var err error = nil
@@ -934,7 +1164,7 @@ func PostSubscriberByID(c *gin.Context) {
 		claims, err = ParseJWT(tokenStr)
 	}
 	if err != nil {
-		logger.WebUILog.Errorln(err.Error())
+		logger.ProcLog.Errorln(err.Error())
 		c.JSON(http.StatusBadRequest, gin.H{
 			"cause": "Illegal Token",
 		})
@@ -942,205 +1172,295 @@ func PostSubscriberByID(c *gin.Context) {
 	}
 
 	var subsData SubsData
-	if err := c.ShouldBindJSON(&subsData); err != nil {
-		logger.WebUILog.Errorf("PostSubscriberByID err: %v", err)
+	err = c.ShouldBindJSON(&subsData)
+	if err != nil {
+		logger.ProcLog.Errorf("PostSubscriberByID err: %v", err)
 		c.JSON(http.StatusBadRequest, gin.H{
 			"cause": "JSON format incorrect",
 		})
 		return
 	}
-
-	ueId := c.Param("ueId")
+	ueId := strings.Split(c.Param("ueId"), "-")[1]
 	servingPlmnId := c.Param("servingPlmnId")
+	userNumber := c.Param("userNumber")
+	if userNumber == "" {
+		userNumber = "1"
+	}
+	userNumberTemp, err := strconv.Atoi(userNumber)
+	if err != nil {
+		logger.ProcLog.Errorf("PostSubscriberByID err: %+v", err)
+		c.JSON(http.StatusBadRequest, gin.H{
+			"cause": "userNumber format incorrect",
+		})
+		return
+	}
+	msisdn := getMsisdn(toBsonM(subsData.AccessAndMobilitySubscriptionData)["gpsis"])
+	msisdnTemp := 0
+	if msisdn != "" {
+		msisdnTemp, err = strconv.Atoi(msisdn)
+		if err != nil {
+			logger.ProcLog.Errorf("PostSubscriberByID err: %+v", err)
+			c.JSON(http.StatusBadRequest, gin.H{
+				"cause": "msisdn format incorrect",
+			})
+			return
+		}
+	}
 
-	filterUeIdOnly := bson.M{"ueId": ueId}
-	filter := bson.M{"ueId": ueId, "servingPlmnId": servingPlmnId}
+	ueIdTemp, err := strconv.Atoi(ueId)
+	if err != nil {
+		logger.ProcLog.Errorf("PostSubscriberByID err: %+v", err)
+		c.JSON(http.StatusBadRequest, gin.H{
+			"cause": "ueId format incorrect",
+		})
+		return
+	}
 
-	// Lookup same UE ID of other tenant's subscription.
-	if claims != nil {
-		authSubsDataInterface, err := mongoapi.RestfulAPIGetOne(authSubsDataColl, filterUeIdOnly)
-		if err != nil {
-			logger.WebUILog.Errorf("PostSubscriberByID err: %+v", err)
+	for i := 0; i < userNumberTemp; i++ {
+		ueId = fmt.Sprintf("imsi-%015d", ueIdTemp)
+		if msisdnTemp != 0 {
+			if !validate(ueId, msisdn) {
+				logger.ProcLog.Errorf("duplicate msisdn: %v", msisdn)
+				c.JSON(http.StatusBadRequest, gin.H{
+					"cause": "duplicate msisdn",
+				})
+				return
+			}
+			msisdnTemp += 1
 		}
-		if len(authSubsDataInterface) > 0 {
-			if authSubsDataInterface["tenantId"].(string) != claims["tenantId"].(string) {
-				c.JSON(http.StatusUnprocessableEntity, gin.H{})
+		ueIdTemp += 1
+
+		subsData.AccessAndMobilitySubscriptionData.Gpsis[0] = "msisdn-" + msisdn
+		// create a msisdn-supi map
+		logger.ProcLog.Infof("PostSubscriberByID msisdn: %+v", msisdn)
+		msisdnSupiMapOperation(ueId, msisdn, "post")
+		filterUeIdOnly := bson.M{"ueId": ueId}
+
+		// Lookup same UE ID of other tenant's subscription.
+		if claims != nil {
+			authSubsDataInterface, err := mongoapi.RestfulAPIGetOne(authSubsDataColl, filterUeIdOnly)
+			if err != nil {
+				logger.ProcLog.Errorf("PostSubscriberByID err: %+v", err)
+				c.JSON(http.StatusInternalServerError, gin.H{})
 				return
 			}
+			if len(authSubsDataInterface) > 0 {
+				if authSubsDataInterface["tenantId"].(string) != claims["tenantId"].(string) {
+					c.JSON(http.StatusUnprocessableEntity, gin.H{})
+					return
+				}
+			}
 		}
+		dbOperation(ueId, servingPlmnId, "post", &subsData, claims)
 	}
+	c.JSON(http.StatusCreated, gin.H{})
+}
 
-	authSubsBsonM := toBsonM(subsData.AuthenticationSubscription)
-	authSubsBsonM["ueId"] = ueId
-	if claims != nil {
-		authSubsBsonM["tenantId"] = claims["tenantId"].(string)
+func validate(supi string, msisdn string) bool {
+	filter := bson.M{"msisdn": msisdn}
+	msisdnSupiMap, err := mongoapi.RestfulAPIGetOne(msisdnSupiMapColl, filter)
+	if err != nil {
+		logger.ProcLog.Errorf("GetSubscriberByID err: %+v", err)
 	}
-	amDataBsonM := toBsonM(subsData.AccessAndMobilitySubscriptionData)
-	amDataBsonM["ueId"] = ueId
-	amDataBsonM["servingPlmnId"] = servingPlmnId
-	if claims != nil {
-		amDataBsonM["tenantId"] = claims["tenantId"].(string)
+	if msisdnSupiMap != nil && msisdnSupiMap["ueId"] != supi {
+		return false
+	} else {
+		return true
 	}
+}
 
-	smDatasBsonA := make([]interface{}, 0, len(subsData.SessionManagementSubscriptionData))
-	for _, smSubsData := range subsData.SessionManagementSubscriptionData {
-		smDataBsonM := toBsonM(smSubsData)
-		smDataBsonM["ueId"] = ueId
-		smDataBsonM["servingPlmnId"] = servingPlmnId
-		smDatasBsonA = append(smDatasBsonA, smDataBsonM)
-	}
+func msisdnSupiMapOperation(supi string, msisdn string, method string) {
+	filter := bson.M{"ueId": supi}
+	data := bson.M{"ueId": supi, "msisdn": msisdn}
 
-	for key, SnssaiData := range subsData.SmPolicyData.SmPolicySnssaiData {
-		tmpSmPolicyDnnData := make(map[string]models.SmPolicyDnnData)
-		for dnnKey, dnn := range SnssaiData.SmPolicyDnnData {
-			escapedDnn := EscapeDnn(dnnKey)
-			tmpSmPolicyDnnData[escapedDnn] = dnn
+	if method == "put" || method == "post" {
+		if msisdn != "" {
+			if _, err := mongoapi.RestfulAPIPutOne(msisdnSupiMapColl, filter, data); err != nil {
+				logger.ProcLog.Errorf("PutMsisdnSupiMap err: %+v", err)
+			}
+		} else {
+			// delete
+			if err := mongoapi.RestfulAPIDeleteOne(msisdnSupiMapColl, filter); err != nil {
+				logger.ProcLog.Errorf("DeleteMsisdnSupiMap err: %+v", err)
+			}
 		}
-		SnssaiData.SmPolicyDnnData = tmpSmPolicyDnnData
-		subsData.SmPolicyData.SmPolicySnssaiData[key] = SnssaiData
 	}
+}
 
-	smfSelSubsBsonM := toBsonM(subsData.SmfSelectionSubscriptionData)
-	smfSelSubsBsonM["ueId"] = ueId
-	smfSelSubsBsonM["servingPlmnId"] = servingPlmnId
-	amPolicyDataBsonM := toBsonM(subsData.AmPolicyData)
-	amPolicyDataBsonM["ueId"] = ueId
-	smPolicyDataBsonM := toBsonM(subsData.SmPolicyData)
-	smPolicyDataBsonM["ueId"] = ueId
+func dbOperation(ueId string, servingPlmnId string, method string, subsData *SubsData, claims jwt.MapClaims) {
+	filterUeIdOnly := bson.M{"ueId": ueId}
+	filter := bson.M{"ueId": ueId, "servingPlmnId": servingPlmnId}
 
-	flowRulesBsonA := make([]interface{}, 0, len(subsData.FlowRules))
-	for _, flowRule := range subsData.FlowRules {
-		flowRuleBsonM := toBsonM(flowRule)
-		flowRuleBsonM["ueId"] = ueId
-		flowRuleBsonM["servingPlmnId"] = servingPlmnId
-		flowRulesBsonA = append(flowRulesBsonA, flowRuleBsonM)
+	// Replace all data with new one
+	if method == "put" {
+		if err := mongoapi.RestfulAPIDeleteMany(flowRuleDataColl, filter); err != nil {
+			logger.ProcLog.Errorf("PutSubscriberByID err: %+v", err)
+		}
+		if err := mongoapi.RestfulAPIDeleteMany(qosFlowDataColl, filter); err != nil {
+			logger.ProcLog.Errorf("PutSubscriberByID err: %+v", err)
+		}
+	} else if method == "delete" {
+		if err := mongoapi.RestfulAPIDeleteOne(authSubsDataColl, filterUeIdOnly); err != nil {
+			logger.ProcLog.Errorf("DeleteSubscriberByID err: %+v", err)
+		}
+		if err := mongoapi.RestfulAPIDeleteOne(amDataColl, filter); err != nil {
+			logger.ProcLog.Errorf("DeleteSubscriberByID err: %+v", err)
+		}
+		if err := mongoapi.RestfulAPIDeleteMany(smDataColl, filter); err != nil {
+			logger.ProcLog.Errorf("DeleteSubscriberByID err: %+v", err)
+		}
+		if err := mongoapi.RestfulAPIDeleteMany(flowRuleDataColl, filter); err != nil {
+			logger.ProcLog.Errorf("DeleteSubscriberByID err: %+v", err)
+		}
+		if err := mongoapi.RestfulAPIDeleteOne(smfSelDataColl, filter); err != nil {
+			logger.ProcLog.Errorf("DeleteSubscriberByID err: %+v", err)
+		}
+		if err := mongoapi.RestfulAPIDeleteOne(amPolicyDataColl, filterUeIdOnly); err != nil {
+			logger.ProcLog.Errorf("DeleteSubscriberByID err: %+v", err)
+		}
+		if err := mongoapi.RestfulAPIDeleteOne(smPolicyDataColl, filterUeIdOnly); err != nil {
+			logger.ProcLog.Errorf("DeleteSubscriberByID err: %+v", err)
+		}
+		if err := mongoapi.RestfulAPIDeleteMany(qosFlowDataColl, filter); err != nil {
+			logger.ProcLog.Errorf("DeleteSubscriberByID err: %+v", err)
+		}
+		if err := mongoapi.RestfulAPIDeleteOne(msisdnSupiMapColl, filterUeIdOnly); err != nil {
+			logger.ProcLog.Errorf("DeleteMsisdnSupiMap err: %+v", err)
+		}
 	}
+	if method == "post" || method == "put" {
+		authSubsBsonM := toBsonM(subsData.AuthenticationSubscription)
+		authSubsBsonM["ueId"] = ueId
+		if claims != nil {
+			authSubsBsonM["tenantId"] = claims["tenantId"].(string)
+		}
+		amDataBsonM := toBsonM(subsData.AccessAndMobilitySubscriptionData)
+		amDataBsonM["ueId"] = ueId
+		amDataBsonM["servingPlmnId"] = servingPlmnId
+		if claims != nil {
+			amDataBsonM["tenantId"] = claims["tenantId"].(string)
+		}
 
-	if _, err := mongoapi.RestfulAPIPost(authSubsDataColl, filterUeIdOnly, authSubsBsonM); err != nil {
-		logger.WebUILog.Errorf("PostSubscriberByID err: %+v", err)
-	}
-	if _, err := mongoapi.RestfulAPIPost(amDataColl, filter, amDataBsonM); err != nil {
-		logger.WebUILog.Errorf("PostSubscriberByID err: %+v", err)
-	}
-	if err := mongoapi.RestfulAPIPostMany(smDataColl, filter, smDatasBsonA); err != nil {
-		logger.WebUILog.Errorf("PostSubscriberByID err: %+v", err)
-	}
-	if _, err := mongoapi.RestfulAPIPost(smfSelDataColl, filter, smfSelSubsBsonM); err != nil {
-		logger.WebUILog.Errorf("PostSubscriberByID err: %+v", err)
-	}
-	if _, err := mongoapi.RestfulAPIPost(amPolicyDataColl, filterUeIdOnly, amPolicyDataBsonM); err != nil {
-		logger.WebUILog.Errorf("PostSubscriberByID err: %+v", err)
-	}
-	if _, err := mongoapi.RestfulAPIPost(smPolicyDataColl, filterUeIdOnly, smPolicyDataBsonM); err != nil {
-		logger.WebUILog.Errorf("PostSubscriberByID err: %+v", err)
-	}
-	if err := mongoapi.RestfulAPIPostMany(flowRuleDataColl, filter, flowRulesBsonA); err != nil {
-		logger.WebUILog.Errorf("PostSubscriberByID err: %+v", err)
-	}
+		// Replace all data with new one
+		if err := mongoapi.RestfulAPIDeleteMany(smDataColl, filter); err != nil {
+			logger.ProcLog.Errorf("PutSubscriberByID err: %+v", err)
+		}
+		for _, data := range subsData.SessionManagementSubscriptionData {
+			smDataBsonM := toBsonM(data)
+			smDataBsonM["ueId"] = ueId
+			smDataBsonM["servingPlmnId"] = servingPlmnId
+			filterSmData := bson.M{"ueId": ueId, "servingPlmnId": servingPlmnId, "snssai": data.SingleNssai}
+			if _, err := mongoapi.RestfulAPIPutOne(smDataColl, filterSmData, smDataBsonM); err != nil {
+				logger.ProcLog.Errorf("PutSubscriberByID err: %+v", err)
+			}
+		}
 
-	c.JSON(http.StatusCreated, gin.H{})
+		for key, SnssaiData := range subsData.SmPolicyData.SmPolicySnssaiData {
+			tmpSmPolicyDnnData := make(map[string]models.SmPolicyDnnData)
+			for dnnKey, dnn := range SnssaiData.SmPolicyDnnData {
+				escapedDnn := EscapeDnn(dnnKey)
+				tmpSmPolicyDnnData[escapedDnn] = dnn
+			}
+			SnssaiData.SmPolicyDnnData = tmpSmPolicyDnnData
+			subsData.SmPolicyData.SmPolicySnssaiData[key] = SnssaiData
+		}
+
+		smfSelSubsBsonM := toBsonM(subsData.SmfSelectionSubscriptionData)
+		smfSelSubsBsonM["ueId"] = ueId
+		smfSelSubsBsonM["servingPlmnId"] = servingPlmnId
+		amPolicyDataBsonM := toBsonM(subsData.AmPolicyData)
+		amPolicyDataBsonM["ueId"] = ueId
+		smPolicyDataBsonM := toBsonM(subsData.SmPolicyData)
+		smPolicyDataBsonM["ueId"] = ueId
+
+		if len(subsData.FlowRules) == 0 {
+			logger.ProcLog.Infoln("No Flow Rule")
+		} else {
+			flowRulesBsonA := make([]interface{}, 0, len(subsData.FlowRules))
+			for _, flowRule := range subsData.FlowRules {
+				flowRuleBsonM := toBsonM(flowRule)
+				flowRuleBsonM["ueId"] = ueId
+				flowRuleBsonM["servingPlmnId"] = servingPlmnId
+				flowRulesBsonA = append(flowRulesBsonA, flowRuleBsonM)
+			}
+			if err := mongoapi.RestfulAPIPostMany(flowRuleDataColl, filter, flowRulesBsonA); err != nil {
+				logger.ProcLog.Errorf("PutSubscriberByID err: %+v", err)
+			}
+		}
+
+		if len(subsData.QosFlows) == 0 {
+			logger.ProcLog.Infoln("No QoS Flow")
+		} else {
+			qosFlowBsonA := make([]interface{}, 0, len(subsData.QosFlows))
+			for _, qosFlow := range subsData.QosFlows {
+				qosFlowBsonM := toBsonM(qosFlow)
+				qosFlowBsonM["ueId"] = ueId
+				qosFlowBsonM["servingPlmnId"] = servingPlmnId
+				qosFlowBsonA = append(qosFlowBsonA, qosFlowBsonM)
+			}
+			if err := mongoapi.RestfulAPIPostMany(qosFlowDataColl, filter, qosFlowBsonA); err != nil {
+				logger.ProcLog.Errorf("PostSubscriberByID err: %+v", err)
+			}
+		}
+
+		if _, err := mongoapi.RestfulAPIPutOne(authSubsDataColl, filterUeIdOnly, authSubsBsonM); err != nil {
+			logger.ProcLog.Errorf("PutSubscriberByID err: %+v", err)
+		}
+		if _, err := mongoapi.RestfulAPIPutOne(amDataColl, filter, amDataBsonM); err != nil {
+			logger.ProcLog.Errorf("PutSubscriberByID err: %+v", err)
+		}
+		if _, err := mongoapi.RestfulAPIPutOne(smfSelDataColl, filter, smfSelSubsBsonM); err != nil {
+			logger.ProcLog.Errorf("PutSubscriberByID err: %+v", err)
+		}
+		if _, err := mongoapi.RestfulAPIPutOne(amPolicyDataColl, filterUeIdOnly, amPolicyDataBsonM); err != nil {
+			logger.ProcLog.Errorf("PutSubscriberByID err: %+v", err)
+		}
+		if _, err := mongoapi.RestfulAPIPutOne(smPolicyDataColl, filterUeIdOnly, smPolicyDataBsonM); err != nil {
+			logger.ProcLog.Errorf("PutSubscriberByID err: %+v", err)
+		}
+	}
 }
 
 // Put subscriber by IMSI(ueId) and PlmnID(servingPlmnId)
 func PutSubscriberByID(c *gin.Context) {
 	setCorsHeader(c)
-	logger.WebUILog.Infoln("Put One Subscriber Data")
-
+	logger.ProcLog.Infoln("Put One Subscriber Data")
 	var subsData SubsData
 	if err := c.ShouldBindJSON(&subsData); err != nil {
-		logger.WebUILog.Errorf("PutSubscriberByID err: %v", err)
+		logger.ProcLog.Errorf("PutSubscriberByID err: %v", err)
 		c.JSON(http.StatusBadRequest, gin.H{
 			"cause": "JSON format incorrect",
 		})
 		return
 	}
-
 	ueId := c.Param("ueId")
 	servingPlmnId := c.Param("servingPlmnId")
-
-	filterUeIdOnly := bson.M{"ueId": ueId}
-	filter := bson.M{"ueId": ueId, "servingPlmnId": servingPlmnId}
-
-	authSubsBsonM := toBsonM(subsData.AuthenticationSubscription)
-	authSubsBsonM["ueId"] = ueId
-	amDataBsonM := toBsonM(subsData.AccessAndMobilitySubscriptionData)
-	amDataBsonM["ueId"] = ueId
-	amDataBsonM["servingPlmnId"] = servingPlmnId
-
-	// Replace all data with new one
-	if err := mongoapi.RestfulAPIDeleteMany(smDataColl, filter); err != nil {
-		logger.WebUILog.Errorf("PutSubscriberByID err: %+v", err)
-	}
-	for _, data := range subsData.SessionManagementSubscriptionData {
-		smDataBsonM := toBsonM(data)
-		smDataBsonM["ueId"] = ueId
-		smDataBsonM["servingPlmnId"] = servingPlmnId
-		filterSmData := bson.M{"ueId": ueId, "servingPlmnId": servingPlmnId, "snssai": data.SingleNssai}
-		if _, err := mongoapi.RestfulAPIPutOne(smDataColl, filterSmData, smDataBsonM); err != nil {
-			logger.WebUILog.Errorf("PutSubscriberByID err: %+v", err)
-		}
-	}
-
-	for key, SnssaiData := range subsData.SmPolicyData.SmPolicySnssaiData {
-		tmpSmPolicyDnnData := make(map[string]models.SmPolicyDnnData)
-		for dnnKey, dnn := range SnssaiData.SmPolicyDnnData {
-			escapedDnn := EscapeDnn(dnnKey)
-			tmpSmPolicyDnnData[escapedDnn] = dnn
-		}
-		SnssaiData.SmPolicyDnnData = tmpSmPolicyDnnData
-		subsData.SmPolicyData.SmPolicySnssaiData[key] = SnssaiData
-	}
-
-	smfSelSubsBsonM := toBsonM(subsData.SmfSelectionSubscriptionData)
-	smfSelSubsBsonM["ueId"] = ueId
-	smfSelSubsBsonM["servingPlmnId"] = servingPlmnId
-	amPolicyDataBsonM := toBsonM(subsData.AmPolicyData)
-	amPolicyDataBsonM["ueId"] = ueId
-	smPolicyDataBsonM := toBsonM(subsData.SmPolicyData)
-	smPolicyDataBsonM["ueId"] = ueId
-
-	flowRulesBsonA := make([]interface{}, 0, len(subsData.FlowRules))
-	for _, flowRule := range subsData.FlowRules {
-		flowRuleBsonM := toBsonM(flowRule)
-		flowRuleBsonM["ueId"] = ueId
-		flowRuleBsonM["servingPlmnId"] = servingPlmnId
-		flowRulesBsonA = append(flowRulesBsonA, flowRuleBsonM)
-	}
-	// Replace all data with new one
-	if err := mongoapi.RestfulAPIDeleteMany(flowRuleDataColl, filter); err != nil {
-		logger.WebUILog.Errorf("PutSubscriberByID err: %+v", err)
-	}
-	if err := mongoapi.RestfulAPIPostMany(flowRuleDataColl, filter, flowRulesBsonA); err != nil {
-		logger.WebUILog.Errorf("PutSubscriberByID err: %+v", err)
+	// modify a msisdn-supi map
+	msisdn := getMsisdn(toBsonM(subsData.AccessAndMobilitySubscriptionData)["gpsis"])
+	if !validate(ueId, msisdn) {
+		logger.ProcLog.Errorf("duplicate msisdn: %v", msisdn)
+		c.JSON(http.StatusBadRequest, gin.H{
+			"cause": "duplicate msisdn",
+		})
+		return
 	}
 
-	if _, err := mongoapi.RestfulAPIPutOne(authSubsDataColl, filterUeIdOnly, authSubsBsonM); err != nil {
-		logger.WebUILog.Errorf("PutSubscriberByID err: %+v", err)
-	}
-	if _, err := mongoapi.RestfulAPIPutOne(amDataColl, filter, amDataBsonM); err != nil {
-		logger.WebUILog.Errorf("PutSubscriberByID err: %+v", err)
-	}
-	if _, err := mongoapi.RestfulAPIPutOne(smfSelDataColl, filter, smfSelSubsBsonM); err != nil {
-		logger.WebUILog.Errorf("PutSubscriberByID err: %+v", err)
-	}
-	if _, err := mongoapi.RestfulAPIPutOne(amPolicyDataColl, filterUeIdOnly, amPolicyDataBsonM); err != nil {
-		logger.WebUILog.Errorf("PutSubscriberByID err: %+v", err)
-	}
-	if _, err := mongoapi.RestfulAPIPutOne(smPolicyDataColl, filterUeIdOnly, smPolicyDataBsonM); err != nil {
-		logger.WebUILog.Errorf("PutSubscriberByID err: %+v", err)
-	}
+	logger.ProcLog.Infof("PutSubscriberByID msisdn: %+v", msisdn)
+	msisdnSupiMapOperation(ueId, msisdn, "put")
 
+	var claims jwt.MapClaims = nil
+	dbOperation(ueId, servingPlmnId, "put", &subsData, claims)
 	c.JSON(http.StatusNoContent, gin.H{})
 }
 
 // Patch subscriber by IMSI(ueId) and PlmnID(servingPlmnId)
 func PatchSubscriberByID(c *gin.Context) {
 	setCorsHeader(c)
-	logger.WebUILog.Infoln("Patch One Subscriber Data")
+	logger.ProcLog.Infoln("Patch One Subscriber Data")
 
 	var subsData SubsData
 	if err := c.ShouldBindJSON(&subsData); err != nil {
-		logger.WebUILog.Errorf("PatchSubscriberByID err: %v", err)
+		logger.ProcLog.Errorf("PatchSubscriberByID err: %v", err)
 		c.JSON(http.StatusBadRequest, gin.H{
 			"cause": "JSON format incorrect",
 		})
@@ -1148,8 +1468,16 @@ func PatchSubscriberByID(c *gin.Context) {
 	}
 
 	ueId := c.Param("ueId")
+	ueId = msisdnToSupi(ueId)
 	servingPlmnId := c.Param("servingPlmnId")
-
+	// checking whether msisdn is successfully transformed to supi or not
+	if ueId == "" {
+		logger.ProcLog.Errorf("PatchSubscriberByID err: msisdn does not exists")
+		c.JSON(http.StatusNotFound, gin.H{
+			"cause": "msisdn does not exists",
+		})
+		return
+	}
 	filterUeIdOnly := bson.M{"ueId": ueId}
 	filter := bson.M{"ueId": ueId, "servingPlmnId": servingPlmnId}
 
@@ -1161,7 +1489,9 @@ func PatchSubscriberByID(c *gin.Context) {
 
 	// Replace all data with new one
 	if err := mongoapi.RestfulAPIDeleteMany(smDataColl, filter); err != nil {
-		logger.WebUILog.Errorf("PatchSubscriberByID err: %+v", err)
+		logger.ProcLog.Errorf("PatchSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	for _, data := range subsData.SessionManagementSubscriptionData {
 		smDataBsonM := toBsonM(data)
@@ -1169,18 +1499,10 @@ func PatchSubscriberByID(c *gin.Context) {
 		smDataBsonM["servingPlmnId"] = servingPlmnId
 		filterSmData := bson.M{"ueId": ueId, "servingPlmnId": servingPlmnId, "snssai": data.SingleNssai}
 		if err := mongoapi.RestfulAPIMergePatch(smDataColl, filterSmData, smDataBsonM); err != nil {
-			logger.WebUILog.Errorf("PatchSubscriberByID err: %+v", err)
-		}
-	}
-
-	for key, SnssaiData := range subsData.SmPolicyData.SmPolicySnssaiData {
-		tmpSmPolicyDnnData := make(map[string]models.SmPolicyDnnData)
-		for dnnKey, dnn := range SnssaiData.SmPolicyDnnData {
-			escapedDnn := EscapeDnn(dnnKey)
-			tmpSmPolicyDnnData[escapedDnn] = dnn
+			logger.ProcLog.Errorf("PatchSubscriberByID err: %+v", err)
+			c.JSON(http.StatusInternalServerError, gin.H{})
+			return
 		}
-		SnssaiData.SmPolicyDnnData = tmpSmPolicyDnnData
-		subsData.SmPolicyData.SmPolicySnssaiData[key] = SnssaiData
 	}
 
 	smfSelSubsBsonM := toBsonM(subsData.SmfSelectionSubscriptionData)
@@ -1192,19 +1514,29 @@ func PatchSubscriberByID(c *gin.Context) {
 	smPolicyDataBsonM["ueId"] = ueId
 
 	if err := mongoapi.RestfulAPIMergePatch(authSubsDataColl, filterUeIdOnly, authSubsBsonM); err != nil {
-		logger.WebUILog.Errorf("PatchSubscriberByID err: %+v", err)
+		logger.ProcLog.Errorf("PatchSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	if err := mongoapi.RestfulAPIMergePatch(amDataColl, filter, amDataBsonM); err != nil {
-		logger.WebUILog.Errorf("PatchSubscriberByID err: %+v", err)
+		logger.ProcLog.Errorf("PatchSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	if err := mongoapi.RestfulAPIMergePatch(smfSelDataColl, filter, smfSelSubsBsonM); err != nil {
-		logger.WebUILog.Errorf("PatchSubscriberByID err: %+v", err)
+		logger.ProcLog.Errorf("PatchSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	if err := mongoapi.RestfulAPIMergePatch(amPolicyDataColl, filterUeIdOnly, amPolicyDataBsonM); err != nil {
-		logger.WebUILog.Errorf("PatchSubscriberByID err: %+v", err)
+		logger.ProcLog.Errorf("PatchSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 	if err := mongoapi.RestfulAPIMergePatch(smPolicyDataColl, filterUeIdOnly, smPolicyDataBsonM); err != nil {
-		logger.WebUILog.Errorf("PatchSubscriberByID err: %+v", err)
+		logger.ProcLog.Errorf("PatchSubscriberByID err: %+v", err)
+		c.JSON(http.StatusInternalServerError, gin.H{})
+		return
 	}
 
 	c.JSON(http.StatusNoContent, gin.H{})
@@ -1213,45 +1545,29 @@ func PatchSubscriberByID(c *gin.Context) {
 // Delete subscriber by IMSI(ueId) and PlmnID(servingPlmnId)
 func DeleteSubscriberByID(c *gin.Context) {
 	setCorsHeader(c)
-	logger.WebUILog.Infoln("Delete One Subscriber Data")
-
+	logger.ProcLog.Infoln("Delete One Subscriber Data")
 	ueId := c.Param("ueId")
+	ueId = msisdnToSupi(ueId)
 	servingPlmnId := c.Param("servingPlmnId")
-
-	filterUeIdOnly := bson.M{"ueId": ueId}
-	filter := bson.M{"ueId": ueId, "servingPlmnId": servingPlmnId}
-
-	if err := mongoapi.RestfulAPIDeleteOne(authSubsDataColl, filterUeIdOnly); err != nil {
-		logger.WebUILog.Errorf("DeleteSubscriberByID err: %+v", err)
-	}
-	if err := mongoapi.RestfulAPIDeleteOne(amDataColl, filter); err != nil {
-		logger.WebUILog.Errorf("DeleteSubscriberByID err: %+v", err)
-	}
-	if err := mongoapi.RestfulAPIDeleteMany(smDataColl, filter); err != nil {
-		logger.WebUILog.Errorf("DeleteSubscriberByID err: %+v", err)
-	}
-	if err := mongoapi.RestfulAPIDeleteMany(flowRuleDataColl, filter); err != nil {
-		logger.WebUILog.Errorf("DeleteSubscriberByID err: %+v", err)
-	}
-	if err := mongoapi.RestfulAPIDeleteOne(smfSelDataColl, filter); err != nil {
-		logger.WebUILog.Errorf("DeleteSubscriberByID err: %+v", err)
-	}
-	if err := mongoapi.RestfulAPIDeleteOne(amPolicyDataColl, filterUeIdOnly); err != nil {
-		logger.WebUILog.Errorf("DeleteSubscriberByID err: %+v", err)
-	}
-	if err := mongoapi.RestfulAPIDeleteOne(smPolicyDataColl, filterUeIdOnly); err != nil {
-		logger.WebUILog.Errorf("DeleteSubscriberByID err: %+v", err)
+	// checking whether msisdn is successfully transformed to supi or not
+	if ueId == "" {
+		logger.ProcLog.Errorf("DeleteSubscriberByID err: msisdn does not exists")
+		c.JSON(http.StatusNotFound, gin.H{
+			"cause": "msisdn does not exists",
+		})
+		return
 	}
-
+	var claims jwt.MapClaims = nil
+	dbOperation(ueId, servingPlmnId, "delete", nil, claims)
 	c.JSON(http.StatusNoContent, gin.H{})
 }
 
 func GetRegisteredUEContext(c *gin.Context) {
 	setCorsHeader(c)
 
-	logger.WebUILog.Infoln("Get Registered UE Context")
+	logger.ProcLog.Infoln("Get Registered UE Context")
 
-	webuiSelf := webui_context.WEBUI_Self()
+	webuiSelf := webui_context.GetSelf()
 	webuiSelf.UpdateNfProfiles()
 
 	supi, supiExists := c.Params.Get("supi")
@@ -1266,17 +1582,28 @@ func GetRegisteredUEContext(c *gin.Context) {
 			requestUri = fmt.Sprintf("%s/namf-oam/v1/registered-ue-context", amfUris[0])
 		}
 
-		resp, err := httpsClient.Get(requestUri)
+		req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, requestUri, nil)
+		if err != nil {
+			logger.ProcLog.Error(err)
+			c.JSON(http.StatusInternalServerError, gin.H{})
+			return
+		}
+		resp, err := httpsClient.Do(req)
 		if err != nil {
-			logger.WebUILog.Error(err)
+			logger.ProcLog.Error(err)
 			c.JSON(http.StatusInternalServerError, gin.H{})
 			return
 		}
+		defer func() {
+			if closeErr := resp.Body.Close(); closeErr != nil {
+				logger.ProcLog.Error(closeErr)
+			}
+		}()
 
 		// Filter by tenant.
 		tenantId, err := GetTenantId(c)
 		if err != nil {
-			logger.WebUILog.Errorln(err.Error())
+			logger.ProcLog.Errorln(err.Error())
 			c.JSON(http.StatusBadRequest, gin.H{
 				"cause": "Illegal Token",
 			})
@@ -1298,9 +1625,9 @@ func GetRegisteredUEContext(c *gin.Context) {
 func GetUEPDUSessionInfo(c *gin.Context) {
 	setCorsHeader(c)
 
-	logger.WebUILog.Infoln("Get UE PDU Session Info")
+	logger.ProcLog.Infoln("Get UE PDU Session Info")
 
-	webuiSelf := webui_context.WEBUI_Self()
+	webuiSelf := webui_context.GetSelf()
 	webuiSelf.UpdateNfProfiles()
 
 	smContextRef, smContextRefExists := c.Params.Get("smContextRef")
@@ -1312,12 +1639,23 @@ func GetUEPDUSessionInfo(c *gin.Context) {
 	// TODO: support fetching data from multiple SMF
 	if smfUris := webuiSelf.GetOamUris(models.NfType_SMF); smfUris != nil {
 		requestUri := fmt.Sprintf("%s/nsmf-oam/v1/ue-pdu-session-info/%s", smfUris[0], smContextRef)
-		resp, err := httpsClient.Get(requestUri)
+		req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, requestUri, nil)
 		if err != nil {
-			logger.WebUILog.Error(err)
+			logger.ProcLog.Error(err)
 			c.JSON(http.StatusInternalServerError, gin.H{})
 			return
 		}
+		resp, err := httpsClient.Do(req)
+		if err != nil {
+			logger.ProcLog.Error(err)
+			c.JSON(http.StatusInternalServerError, gin.H{})
+			return
+		}
+		defer func() {
+			if closeErr := resp.Body.Close(); closeErr != nil {
+				logger.ProcLog.Error(closeErr)
+			}
+		}()
 
 		sendResponseToClient(c, resp)
 	} else {
diff --git a/backend/WebUI/model_flow_rule.go b/backend/WebUI/model_flow_rule.go
index e16bd44e4f6a75376db752934b4c8778b28300bf..e6fa7d6c2a77051a1661a19a8e658f0615323670 100644
--- a/backend/WebUI/model_flow_rule.go
+++ b/backend/WebUI/model_flow_rule.go
@@ -1,12 +1,9 @@
 package WebUI
 
 type FlowRule struct {
-	Filter string `json:"filter,omitempty" yaml:"filter" bson:"filter" mapstructure:"filter"`
-	Snssai string `json:"snssai,omitempty" yaml:"snssai" bson:"snssai" mapstructure:"snssai"`
-	Dnn    string `json:"dnn,omitempty" yaml:"v" bson:"dnn" mapstructure:"dnn"`
-	Var5QI int    `json:"5qi,omitempty" yaml:"5qi" bson:"5qi" mapstructure:"5qi"`
-	MBRUL  string `json:"mbrUL,omitempty" yaml:"mbrUL" bson:"mbrUL" mapstructure:"mbrUL"`
-	MBRDL  string `json:"mbrDL,omitempty" yaml:"mbrDL" bson:"mbrDL" mapstructure:"mbrDL"`
-	GBRUL  string `json:"gbrUL,omitempty" yaml:"gbrUL" bson:"gbrUL" mapstructure:"gbrUL"`
-	GBRDL  string `json:"gbrDL,omitempty" yaml:"gbrDL" bson:"gbrDL" mapstructure:"gbrDL"`
+	Filter     string `json:"filter,omitempty" yaml:"filter" bson:"filter" mapstructure:"filter"`
+	Precedence int    `json:"precedence,omitempty" yaml:"precedence" bson:"precedence" mapstructure:"precedence"`
+	Snssai     string `json:"snssai,omitempty" yaml:"snssai" bson:"snssai" mapstructure:"snssai"`
+	Dnn        string `json:"dnn,omitempty" yaml:"dnn" bson:"dnn" mapstructure:"dnn"`
+	QFI        int    `json:"qfi,omitempty" yaml:"qfi" bson:"qfi" mapstructure:"qfi"`
 }
diff --git a/backend/WebUI/model_qos_flow.go b/backend/WebUI/model_qos_flow.go
new file mode 100644
index 0000000000000000000000000000000000000000..648cc41709608879886e5fdb693e5230b2cfa712
--- /dev/null
+++ b/backend/WebUI/model_qos_flow.go
@@ -0,0 +1,12 @@
+package WebUI
+
+type QosFlow struct {
+	Snssai string `json:"snssai" yaml:"snssai" bson:"snssai" mapstructure:"snssai"`
+	Dnn    string `json:"dnn" yaml:"dnn" bson:"dnn" mapstructure:"dnn"`
+	QFI    uint8  `json:"qfi" yaml:"qfi" bson:"qfi" mapstructure:"qfi"`
+	Var5QI int    `json:"5qi" yaml:"5qi" bson:"5qi" mapstructure:"5qi"`
+	MBRUL  string `json:"mbrUL,omitempty" yaml:"mbrUL" bson:"mbrUL" mapstructure:"mbrUL"`
+	MBRDL  string `json:"mbrDL,omitempty" yaml:"mbrDL" bson:"mbrDL" mapstructure:"mbrDL"`
+	GBRUL  string `json:"gbrUL,omitempty" yaml:"gbrUL" bson:"gbrUL" mapstructure:"gbrUL"`
+	GBRDL  string `json:"gbrDL,omitempty" yaml:"gbrDL" bson:"gbrDL" mapstructure:"gbrDL"`
+}
diff --git a/backend/WebUI/model_subs_data.go b/backend/WebUI/model_subs_data.go
index 0a41309fbb3625797b1446768b66f2f56a96960f..3efde2ad0a4a0944a28f0b7f00d7beda50aef57b 100644
--- a/backend/WebUI/model_subs_data.go
+++ b/backend/WebUI/model_subs_data.go
@@ -14,4 +14,5 @@ type SubsData struct {
 	AmPolicyData                      models.AmPolicyData                        `json:"AmPolicyData"`
 	SmPolicyData                      models.SmPolicyData                        `json:"SmPolicyData"`
 	FlowRules                         []FlowRule                                 `json:"FlowRules"`
+	QosFlows                          []QosFlow                                  `json:"QosFlows"`
 }
diff --git a/backend/WebUI/model_subs_list_ie.go b/backend/WebUI/model_subs_list_ie.go
index b4f3000ca252aced57945c8db0c1d2a0f1ff867e..5fd51c3bb15e82ae6ab2f7f4e82a39220e204872 100644
--- a/backend/WebUI/model_subs_list_ie.go
+++ b/backend/WebUI/model_subs_list_ie.go
@@ -3,4 +3,5 @@ package WebUI
 type SubsListIE struct {
 	PlmnID string `json:"plmnID"`
 	UeId   string `json:"ueId"`
+	Msisdn string `json:"msisdn"`
 }
diff --git a/backend/WebUI/routers.go b/backend/WebUI/routers.go
index 226b0a36d755a30676ec0d95964db2a796438f48..a3ab212c515f80cdbe812dfac337d5e263bdbc6c 100644
--- a/backend/WebUI/routers.go
+++ b/backend/WebUI/routers.go
@@ -165,6 +165,13 @@ var routes = Routes{
 		PostSubscriberByID,
 	},
 
+	{
+		"PostMultiSubscriber",
+		http.MethodPost,
+		"/subscriber/:ueId/:servingPlmnId/:userNumber",
+		PostSubscriberByID,
+	},
+
 	{
 		"PutSubscriberByID",
 		http.MethodPut,
diff --git a/backend/factory/config.go b/backend/factory/config.go
index 8ddbe2124dc845e8df3eb2bc71b0a1bc7f193149..5de44c58c72380099cbcb343bd233d535c52f649 100644
--- a/backend/factory/config.go
+++ b/backend/factory/config.go
@@ -7,32 +7,145 @@
 package factory
 
 import (
-	logger_util "github.com/free5gc/util/logger"
+	"fmt"
+	"sync"
+
+	"github.com/asaskevich/govalidator"
+
+	"github.com/free5gc/webconsole/backend/logger"
+)
+
+const (
+	WebuiDefaultTLSKeyLogPath  = "./log/webuisslkey.log"
+	WebuiDefaultCertPemPath    = "./cert/webui.pem"
+	WebuiDefaultPrivateKeyPath = "./cert/webui.key"
+	WebuiDefaultConfigPath     = "./config/webuicfg.yaml"
 )
 
 type Config struct {
-	Info          *Info               `yaml:"info"`
-	Configuration *Configuration      `yaml:"configuration"`
-	Logger        *logger_util.Logger `yaml:"logger"`
+	Info          *Info          `yaml:"info" valid:"required"`
+	Configuration *Configuration `yaml:"configuration" valid:"required"`
+	Logger        *Logger        `yaml:"logger" valid:"required"`
+	sync.RWMutex
+}
+
+func (c *Config) Validate() (bool, error) {
+	result, err := govalidator.ValidateStruct(c)
+	return result, appendInvalid(err)
 }
 
 type Info struct {
-	Version     string `yaml:"version,omitempty"`
-	Description string `yaml:"description,omitempty"`
+	Version     string `yaml:"version,omitempty" valid:"required,in(1.0.1)"`
+	Description string `yaml:"description,omitempty" valid:"type(string)"`
 }
 
 type Configuration struct {
-	WebServer *WebServer `yaml:"WebServer,omitempty"`
-	Mongodb   *Mongodb   `yaml:"mongodb"`
+	WebServer *WebServer `yaml:"webServer,omitempty" valid:"optional"`
+	Mongodb   *Mongodb   `yaml:"mongodb" valid:"required"`
+}
+
+type Logger struct {
+	Enable       bool   `yaml:"enable" valid:"type(bool)"`
+	Level        string `yaml:"level" valid:"required,in(trace|debug|info|warn|error|fatal|panic)"`
+	ReportCaller bool   `yaml:"reportCaller" valid:"type(bool)"`
 }
 
 type WebServer struct {
-	Scheme string `yaml:"scheme"`
-	IP     string `yaml:"ipv4Address"`
-	PORT   string `yaml:"port"`
+	Scheme string `yaml:"scheme" valid:"required"`
+	IP     string `yaml:"ipv4Address" valid:"required"`
+	PORT   string `yaml:"port" valid:"required"`
 }
 
 type Mongodb struct {
-	Name string `yaml:"name"`
-	Url  string `yaml:"url"`
+	Name string `yaml:"name" valid:"required"`
+	Url  string `yaml:"url"  valid:"required"`
+}
+
+func appendInvalid(err error) error {
+	var errs govalidator.Errors
+
+	if err == nil {
+		return nil
+	}
+
+	es := err.(govalidator.Errors).Errors()
+	for _, e := range es {
+		errs = append(errs, fmt.Errorf("invalid %w", e))
+	}
+
+	return error(errs)
+}
+
+func (c *Config) SetLogEnable(enable bool) {
+	c.Lock()
+	defer c.Unlock()
+
+	if c.Logger == nil {
+		logger.CfgLog.Warnf("Logger should not be nil")
+		c.Logger = &Logger{
+			Enable: enable,
+			Level:  "info",
+		}
+	} else {
+		c.Logger.Enable = enable
+	}
+}
+
+func (c *Config) SetLogLevel(level string) {
+	c.Lock()
+	defer c.Unlock()
+
+	if c.Logger == nil {
+		logger.CfgLog.Warnf("Logger should not be nil")
+		c.Logger = &Logger{
+			Level: level,
+		}
+	} else {
+		c.Logger.Level = level
+	}
+}
+
+func (c *Config) SetLogReportCaller(reportCaller bool) {
+	c.Lock()
+	defer c.Unlock()
+
+	if c.Logger == nil {
+		logger.CfgLog.Warnf("Logger should not be nil")
+		c.Logger = &Logger{
+			Level:        "info",
+			ReportCaller: reportCaller,
+		}
+	} else {
+		c.Logger.ReportCaller = reportCaller
+	}
+}
+
+func (c *Config) GetLogEnable() bool {
+	c.RLock()
+	defer c.RUnlock()
+	if c.Logger == nil {
+		logger.CfgLog.Warnf("Logger should not be nil")
+		return false
+	}
+	return c.Logger.Enable
+}
+
+func (c *Config) GetLogLevel() string {
+	c.RLock()
+	defer c.RUnlock()
+	if c.Logger == nil {
+		logger.CfgLog.Warnf("Logger should not be nil")
+		return "info"
+	}
+	return c.Logger.Level
+}
+
+func (c *Config) GetLogReportCaller() bool {
+	c.RLock()
+	defer c.RUnlock()
+	if c.Logger == nil {
+		logger.CfgLog.Warnf("Logger should not be nil")
+		return false
+	}
+	return c.Logger.ReportCaller
 }
diff --git a/backend/factory/factory.go b/backend/factory/factory.go
index 205206fe6a1f6e44e6a794bee9918b2dee35a48c..57726b37ae83456f701ca4958e8c6bbcb72a396a 100644
--- a/backend/factory/factory.go
+++ b/backend/factory/factory.go
@@ -8,22 +8,45 @@ import (
 	"fmt"
 	"io/ioutil"
 
+	"github.com/asaskevich/govalidator"
 	"gopkg.in/yaml.v2"
+
+	"github.com/free5gc/webconsole/backend/logger"
 )
 
-var WebUIConfig Config
+var WebuiConfig *Config
 
 // TODO: Support configuration update from REST api
-func InitConfigFactory(f string) error {
+func InitConfigFactory(f string, cfg *Config) error {
+	if f == "" {
+		// Use default config path
+		f = WebuiDefaultConfigPath
+	}
 	if content, err := ioutil.ReadFile(f); err != nil {
-		return fmt.Errorf("[Configuration] %+v", err)
+		return fmt.Errorf("[Factory] %+v", err)
 	} else {
-		WebUIConfig = Config{}
-
-		if yamlErr := yaml.Unmarshal(content, &WebUIConfig); yamlErr != nil {
-			return fmt.Errorf("[Configuration] %+v", yamlErr)
+		logger.CfgLog.Infof("Read config from [%s]", f)
+		if yamlErr := yaml.Unmarshal(content, &cfg); yamlErr != nil {
+			return fmt.Errorf("[Factory] %+v", yamlErr)
 		}
 	}
 
 	return nil
 }
+
+func ReadConfig(cfgPath string) (*Config, error) {
+	cfg := &Config{}
+	if err := InitConfigFactory(cfgPath, cfg); err != nil {
+		return nil, fmt.Errorf("ReadConfig [%s] Error: %+v", cfgPath, err)
+	}
+	if _, err := cfg.Validate(); err != nil {
+		validErrs := err.(govalidator.Errors).Errors()
+		for _, validErr := range validErrs {
+			logger.CfgLog.Errorf("%+v", validErr)
+		}
+		logger.CfgLog.Errorf("[-- PLEASE REFER TO SAMPLE CONFIG FILE COMMENTS --]")
+		return nil, fmt.Errorf("Config validate Error")
+	}
+
+	return cfg, nil
+}
diff --git a/backend/logger/logger.go b/backend/logger/logger.go
index db51f6d14002face17c0216620436584e18c996c..e7b8a08949b3ed6c4255158eede72a3e87cbeb2d 100644
--- a/backend/logger/logger.go
+++ b/backend/logger/logger.go
@@ -1,73 +1,33 @@
 package logger
 
 import (
-	"os"
-	"time"
-
-	formatter "github.com/antonfisher/nested-logrus-formatter"
 	"github.com/sirupsen/logrus"
 
 	logger_util "github.com/free5gc/util/logger"
 )
 
 var (
-	log        *logrus.Logger
-	AppLog     *logrus.Entry
-	InitLog    *logrus.Entry
-	WebUILog   *logrus.Entry
-	ContextLog *logrus.Entry
-	GinLog     *logrus.Entry
+	Log     *logrus.Logger
+	NfLog   *logrus.Entry
+	MainLog *logrus.Entry
+	InitLog *logrus.Entry
+	ProcLog *logrus.Entry
+	CtxLog  *logrus.Entry
+	CfgLog  *logrus.Entry
+	GinLog  *logrus.Entry
 )
 
 func init() {
-	log = logrus.New()
-	log.SetReportCaller(false)
-
-	log.Formatter = &formatter.Formatter{
-		TimestampFormat: time.RFC3339Nano,
-		TrimMessages:    true,
-		NoFieldsSpace:   true,
-		HideKeys:        true,
-		FieldsOrder:     []string{"component", "category"},
+	fieldsOrder := []string{
+		logger_util.FieldNF,
+		logger_util.FieldCategory,
 	}
-
-	AppLog = log.WithFields(logrus.Fields{"component": "WebUI", "category": "App"})
-	InitLog = log.WithFields(logrus.Fields{"component": "WebUI", "category": "Init"})
-	WebUILog = log.WithFields(logrus.Fields{"component": "WebUI", "category": "WebUI"})
-	ContextLog = log.WithFields(logrus.Fields{"component": "WebUI", "category": "Context"})
-	GinLog = log.WithFields(logrus.Fields{"component": "WebUI", "category": "GIN"})
-}
-
-func LogFileHook(logNfPath string, log5gcPath string) error {
-	if fullPath, err := logger_util.CreateFree5gcLogFile(log5gcPath); err == nil {
-		if fullPath != "" {
-			free5gcLogHook, hookErr := logger_util.NewFileHook(fullPath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0o666)
-			if hookErr != nil {
-				return hookErr
-			}
-			log.Hooks.Add(free5gcLogHook)
-		}
-	} else {
-		return err
-	}
-
-	if fullPath, err := logger_util.CreateNfLogFile(logNfPath, "webconsole.log"); err == nil {
-		selfLogHook, hookErr := logger_util.NewFileHook(fullPath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0o666)
-		if hookErr != nil {
-			return hookErr
-		}
-		log.Hooks.Add(selfLogHook)
-	} else {
-		return err
-	}
-
-	return nil
-}
-
-func SetLogLevel(level logrus.Level) {
-	log.SetLevel(level)
-}
-
-func SetReportCaller(enable bool) {
-	log.SetReportCaller(enable)
+	Log = logger_util.New(fieldsOrder)
+	NfLog = Log.WithField(logger_util.FieldNF, "WEBUI")
+	MainLog = NfLog.WithField(logger_util.FieldCategory, "Main")
+	InitLog = NfLog.WithField(logger_util.FieldCategory, "Init")
+	ProcLog = NfLog.WithField(logger_util.FieldCategory, "Proc")
+	CtxLog = NfLog.WithField(logger_util.FieldCategory, "CTX")
+	CfgLog = NfLog.WithField(logger_util.FieldCategory, "CFG")
+	GinLog = NfLog.WithField(logger_util.FieldCategory, "GIN")
 }
diff --git a/backend/webui_context/context.go b/backend/webui_context/context.go
index 00036ac7bb97fb2b942c757dc9d62fe13f492f47..37aa6346a6785d0d06797fd3bff9f094620d08f1 100644
--- a/backend/webui_context/context.go
+++ b/backend/webui_context/context.go
@@ -9,7 +9,7 @@ import (
 	"github.com/free5gc/webconsole/backend/logger"
 )
 
-var webuiContext = WEBUIContext{}
+var webuiContext WEBUIContext
 
 type WEBUIContext struct {
 	NFProfiles     []models.NfProfile
@@ -22,18 +22,15 @@ type NfOamInstance struct {
 	Uri    string
 }
 
-func init() {
-}
-
 func (context *WEBUIContext) UpdateNfProfiles() {
 	nfProfilesRaw, err := mongoapi.RestfulAPIGetMany("NfProfile", nil)
 	if err != nil {
-		logger.ContextLog.Error(err)
+		logger.CtxLog.Error(err)
 		return
 	}
 	var nfProfiles []models.NfProfile
 	if err := timedecode.Decode(nfProfilesRaw, &nfProfiles); err != nil {
-		logger.ContextLog.Error(err)
+		logger.CtxLog.Error(err)
 		return
 	}
 
@@ -105,7 +102,7 @@ func (context *WEBUIContext) GetOamUris(targetNfType models.NfType) (uris []stri
 	return
 }
 
-func WEBUI_Self() *WEBUIContext {
+func GetSelf() *WEBUIContext {
 	return &webuiContext
 }
 
diff --git a/backend/webui_service/webui_init.go b/backend/webui_service/webui_init.go
index a69527e97f29bb870df94b2b1455f3ec10f1bda8..ce498ed6389e64268c5238f0029e9cc3fe9acc70 100644
--- a/backend/webui_service/webui_init.go
+++ b/backend/webui_service/webui_init.go
@@ -1,16 +1,11 @@
 package webui_service
 
 import (
-	"bufio"
-	"fmt"
-	"os/exec"
-	"path/filepath"
-	"runtime/debug"
-	"sync"
+	"io/ioutil"
+	"os"
 
 	"github.com/gin-contrib/cors"
 	"github.com/sirupsen/logrus"
-	"github.com/urfave/cli"
 
 	"github.com/free5gc/util/mongoapi"
 	"github.com/free5gc/webconsole/backend/WebUI"
@@ -19,118 +14,70 @@ import (
 	"github.com/free5gc/webconsole/backend/webui_context"
 )
 
-type WEBUI struct{}
-
-type (
-	// Commands information.
-	Commands struct {
-		config string
-		public string
-	}
-)
-
-var commands Commands
-
-var cliCmd = []cli.Flag{
-	cli.StringFlag{
-		Name:  "public, p",
-		Usage: "Load public path from `FOLDER`",
-	},
-	cli.StringFlag{
-		Name:  "config, c",
-		Usage: "Load configuration from `FILE`",
-	},
-	cli.StringFlag{
-		Name:  "log, l",
-		Usage: "Output NF log to `FILE`",
-	},
-	cli.StringFlag{
-		Name:  "log5gc, lc",
-		Usage: "Output free5gc log to `FILE`",
-	},
+type WebuiApp struct {
+	cfg      *factory.Config
+	webuiCtx *webui_context.WEBUIContext
 }
 
-var initLog *logrus.Entry
+func NewApp(cfg *factory.Config) (*WebuiApp, error) {
+	webui := &WebuiApp{cfg: cfg}
+	webui.SetLogEnable(cfg.GetLogEnable())
+	webui.SetLogLevel(cfg.GetLogLevel())
+	webui.SetReportCaller(cfg.GetLogReportCaller())
 
-func (*WEBUI) GetCliCmd() (flags []cli.Flag) {
-	return cliCmd
+	webui.webuiCtx = webui_context.GetSelf()
+	return webui, nil
 }
 
-func (webui *WEBUI) Initialize(c *cli.Context) error {
-	commands = Commands{
-		config: c.String("config"),
-		public: c.String("public"),
+func (a *WebuiApp) SetLogEnable(enable bool) {
+	logger.MainLog.Infof("Log enable is set to [%v]", enable)
+	if enable && logger.Log.Out == os.Stderr {
+		return
+	} else if !enable && logger.Log.Out == ioutil.Discard {
+		return
 	}
-
-	initLog = logger.InitLog
-
-	if commands.config != "" {
-		if err := factory.InitConfigFactory(commands.config); err != nil {
-			return err
-		}
+	a.cfg.SetLogEnable(enable)
+	if enable {
+		logger.Log.SetOutput(os.Stderr)
 	} else {
-		if err := factory.InitConfigFactory("./config/webuicfg.yaml"); err != nil {
-			return err
-		}
-	}
-
-	if commands.public != "" {
-		PublicPath = filepath.Clean(commands.public)
+		logger.Log.SetOutput(ioutil.Discard)
 	}
-
-	webui.setLogLevel()
-
-	return nil
 }
 
-func (webui *WEBUI) setLogLevel() {
-	if factory.WebUIConfig.Logger == nil {
-		initLog.Warnln("Webconsole config without log level setting!!!")
+func (a *WebuiApp) SetLogLevel(level string) {
+	lvl, err := logrus.ParseLevel(level)
+	if err != nil {
+		logger.MainLog.Warnf("Log level [%s] is invalid", level)
 		return
 	}
-
-	if factory.WebUIConfig.Logger.WEBUI != nil {
-		if factory.WebUIConfig.Logger.WEBUI.DebugLevel != "" {
-			if level, err := logrus.ParseLevel(factory.WebUIConfig.Logger.WEBUI.DebugLevel); err != nil {
-				initLog.Warnf("WebUI Log level [%s] is invalid, set to [info] level",
-					factory.WebUIConfig.Logger.WEBUI.DebugLevel)
-				logger.SetLogLevel(logrus.InfoLevel)
-			} else {
-				initLog.Infof("WebUI Log level is set to [%s] level", level)
-				logger.SetLogLevel(level)
-			}
-		} else {
-			initLog.Warnln("WebUI Log level not set. Default set to [info] level")
-			logger.SetLogLevel(logrus.InfoLevel)
-		}
-		logger.SetReportCaller(factory.WebUIConfig.Logger.WEBUI.ReportCaller)
+	logger.MainLog.Infof("Log level is set to [%s]", level)
+	if lvl == logger.Log.GetLevel() {
+		return
 	}
+	a.cfg.SetLogLevel(level)
+	logger.Log.SetLevel(lvl)
 }
 
-func (webui *WEBUI) FilterCli(c *cli.Context) (args []string) {
-	for _, flag := range webui.GetCliCmd() {
-		name := flag.GetName()
-		value := fmt.Sprint(c.Generic(name))
-		if value == "" {
-			continue
-		}
-
-		args = append(args, "--"+name, value)
+func (a *WebuiApp) SetReportCaller(reportCaller bool) {
+	logger.MainLog.Infof("Report Caller is set to [%v]", reportCaller)
+	if reportCaller == logger.Log.ReportCaller {
+		return
 	}
-	return args
+	a.cfg.SetLogReportCaller(reportCaller)
+	logger.Log.SetReportCaller(reportCaller)
 }
 
-func (webui *WEBUI) Start() {
+func (a *WebuiApp) Start(tlsKeyLogPath string) {
 	// get config file info from WebUIConfig
-	mongodb := factory.WebUIConfig.Configuration.Mongodb
+	mongodb := factory.WebuiConfig.Configuration.Mongodb
 
 	// Connect to MongoDB
 	if err := mongoapi.SetMongoDB(mongodb.Name, mongodb.Url); err != nil {
-		initLog.Errorf("Server start err: %+v", err)
+		logger.InitLog.Errorf("Server start err: %+v", err)
 		return
 	}
 
-	initLog.Infoln("Server started")
+	logger.InitLog.Infoln("Server started")
 
 	router := WebUI.NewRouter()
 
@@ -146,79 +93,10 @@ func (webui *WEBUI) Start() {
 		MaxAge:           86400,
 	}))
 
-	self := webui_context.WEBUI_Self()
+	self := webui_context.GetSelf()
 	self.UpdateNfProfiles()
 
 	router.NoRoute(ReturnPublic())
 
-	initLog.Infoln(router.Run(":5000"))
-}
-
-func (webui *WEBUI) Exec(c *cli.Context) error {
-	initLog.Traceln("args:", c.String("webuicfg"))
-	args := webui.FilterCli(c)
-	initLog.Traceln("filter: ", args)
-	command := exec.Command("./webui", args...)
-
-	if err := webui.Initialize(c); err != nil {
-		return err
-	}
-
-	stdout, err := command.StdoutPipe()
-	if err != nil {
-		initLog.Fatalln(err)
-	}
-	wg := sync.WaitGroup{}
-	wg.Add(3)
-	go func() {
-		defer func() {
-			if p := recover(); p != nil {
-				// Print stack for panic to log. Fatalf() will let program exit.
-				logger.InitLog.Fatalf("panic: %v\n%s", p, string(debug.Stack()))
-			}
-		}()
-
-		in := bufio.NewScanner(stdout)
-		for in.Scan() {
-			fmt.Println(in.Text())
-		}
-		wg.Done()
-	}()
-
-	stderr, err := command.StderrPipe()
-	if err != nil {
-		initLog.Fatalln(err)
-	}
-	go func() {
-		defer func() {
-			if p := recover(); p != nil {
-				// Print stack for panic to log. Fatalf() will let program exit.
-				logger.InitLog.Fatalf("panic: %v\n%s", p, string(debug.Stack()))
-			}
-		}()
-
-		in := bufio.NewScanner(stderr)
-		for in.Scan() {
-			fmt.Println(in.Text())
-		}
-		wg.Done()
-	}()
-
-	go func() {
-		defer func() {
-			if p := recover(); p != nil {
-				// Print stack for panic to log. Fatalf() will let program exit.
-				logger.InitLog.Fatalf("panic: %v\n%s", p, string(debug.Stack()))
-			}
-		}()
-
-		if errCmd := command.Start(); errCmd != nil {
-			fmt.Println("command.Start Fails!")
-		}
-		wg.Done()
-	}()
-
-	wg.Wait()
-
-	return err
+	logger.InitLog.Infoln(router.Run(":5000"))
 }
diff --git a/config/webuicfg.yaml b/config/webuicfg.yaml
index f837ab769f3a6330a93db10cbfb308eddb411efa..ed7aff3453dd8dcbf04cca071e3569062208d1cf 100644
--- a/config/webuicfg.yaml
+++ b/config/webuicfg.yaml
@@ -1,5 +1,5 @@
 info:
-  version: 1.0.0
+  version: 1.0.1
   description: WebUI initial local configuration
 
 configuration:
@@ -7,10 +7,7 @@ configuration:
     name: free5gc # name of the mongodb
     url: mongodb://localhost:27017 # a valid URL of the mongodb
 
-# the kind of log output
-# debugLevel: how detailed to output, value: trace, debug, info, warn, error, fatal, panic
-# ReportCaller: enable the caller report or not, value: true or false
-logger:
-  WEBUI:
-    debugLevel: info
-    ReportCaller: false
+logger: # log output setting
+  enable: true # true or false
+  level: info # how detailed to output, value: trace, debug, info, warn, error, fatal, panic
+  reportCaller: false # enable the caller report or not, value: true or false
diff --git a/frontend/package.json b/frontend/package.json
index 451b419e05ddd118cf3c24c59df1c6f661ad5dcf..37f556ae00501f4c445a00d9770bc6c90b0475a1 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -4,6 +4,7 @@
   "private": true,
   "homepage": "",
   "dependencies": {
+    "@fortawesome/fontawesome-free": "^5.15.2",
     "autoprefixer": "7.1.2",
     "axios": "latest",
     "babel-core": "6.26.3",
@@ -12,6 +13,7 @@
     "babel-loader": "7.1.1",
     "babel-preset-react-app": "^3.0.2",
     "babel-runtime": "6.26.0",
+    "bootstrap": "~3.3.6",
     "case-sensitive-paths-webpack-plugin": "2.4.0",
     "chalk": "1.1.3",
     "classnames": "^2.2.5",
@@ -60,7 +62,7 @@
     "whatwg-fetch": "2.0.3"
   },
   "devDependencies": {
-    "sass": "^1.50.0",
+    "sass": "1.51.0",
     "sass-loader": "^7.0.1",
     "webpack-dev-server": "2.9.7",
     "ws": "3.3.2"
diff --git a/frontend/public/index.html b/frontend/public/index.html
index d038b4d1de3816ac14c7e7f8ad59e0b284135ebd..3182307da6088dd57d268050b61c2a99cab3a874 100644
--- a/frontend/public/index.html
+++ b/frontend/public/index.html
@@ -4,10 +4,6 @@
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
     <meta name="theme-color" content="#000000">
-    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
-    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
-    <link href="https://fonts.googleapis.com/css?family=Open+Sans:100,400,600,700" rel="stylesheet">
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-fork-ribbon-css/0.2.0/gh-fork-ribbon.min.css" />
 
     <!--
       manifest.json provides metadata used when your web app is added to the
@@ -37,7 +33,6 @@
     <div style="margin: 14px; font-size: 18px; float: left;">
       Loading...
     </div>
-
-    <script src="https://unpkg.com/react-jsonschema-form/dist/react-jsonschema-form.js"></script>
+    
   </body>
 </html>
diff --git a/frontend/src/components/FormInputs/Radio.js b/frontend/src/components/FormInputs/Radio.js
index c7b7b70589b0f8c3180a8508a4c9393b022bb582..2fa265196bf081cb16cccc4428007bfa1012887a 100644
--- a/frontend/src/components/FormInputs/Radio.js
+++ b/frontend/src/components/FormInputs/Radio.js
@@ -6,8 +6,8 @@ import checkImage from 'assets/images/radio-2.svg';
 
 class Radio extends Component {
 
-  componentWillReceiveProps(props) {
-    console.log(props);
+  static getDerivedStateFromProps(nextProps, prevState){
+    console.log(nextProps);
   }
 
   render() {
diff --git a/frontend/src/index.js b/frontend/src/index.js
index fb721aa90f5fa93d65b69bbd1a2ed8aa89924efa..024a09521611c57af32da10f9016076c7cc05f3e 100644
--- a/frontend/src/index.js
+++ b/frontend/src/index.js
@@ -1,11 +1,18 @@
 import React from 'react';
 import ReactDOM from 'react-dom';
-import registerServiceWorker from './registerServiceWorker';
+import {Provider} from 'react-redux';
 import {HashRouter} from 'react-router-dom';
-import './assets/styles/base.scss';
+
 import App from './pages/App';
 import configureStore from './config/configureStore';
-import {Provider} from 'react-redux';
+import registerServiceWorker from './registerServiceWorker';
+
+// dependency CSS
+import 'bootstrap/dist/css/bootstrap.min.css';
+import '@fortawesome/fontawesome-free/css/all.min.css';
+
+import './assets/styles/base.scss';
+
 
 export const store = configureStore();
 const rootElement = document.getElementById('root');
diff --git a/frontend/src/metadata/index.js b/frontend/src/metadata/index.js
index 30f50b4ed0d357504be0f710b7983149b19d5610..55cebc99f793db4761648455765af8d22064f238 100644
--- a/frontend/src/metadata/index.js
+++ b/frontend/src/metadata/index.js
@@ -5,343 +5,356 @@
 //  userModalSchema
 
 let subModalSchema = {
-    // title: "A registration form",
-    // "description": "A simple form example.",
-    type: "object",
-    required: [
-      "userNumber",
-      "plmnID",
-      "ueId",
-      "authenticationMethod",
-      "K",
-      "OPOPcSelect",
-      "OPOPc",
-      "SQN",
-    ],
-    properties: {
-      userNumber: {
-        type: "integer",
-        title: "Subscriber data number (auto-increased with SUPI)",
-        default: 1,
-        maximum: 100000,
-        minimum: 1
-      },
-      plmnID: {
-        type: "string",
-        title: "PLMN ID",
-        pattern: "^[0-9]{5,6}$",
-        default: "20893",
-      },
-      ueId: {
-        type: "string",
-        title: "SUPI (IMSI)",
-        pattern: "^[0-9]{10,15}$",
-        default: "208930000000003",
-      },
-      authenticationMethod: {
-        type: "string",
-        title: "Authentication Method",
-        default: "5G_AKA",
-        enum: ["5G_AKA", "EAP_AKA_PRIME"],
-      },
-      K: {
-        type: "string",
-        title: "K",
-        pattern: "^[A-Fa-f0-9]{32}$",
-        default: "8baf473f2f8fd09487cccbd7097c6862",
-      },
-      OPOPcSelect: {
-        type: "string",
-        title: "Operator Code Type",
-        enum: ["OP", "OPc"],
-        default: "OPc",
-      },
-      OPOPc: {
-        type: "string",
-        title: "Operator Code Value",
-        pattern: "^[A-Fa-f0-9]{32}$",
-        default: "8e27b6af0e692e750f32667a3b14605d",
-      },
-      SQN: {
-        type: "string",
-        title: "SQN",
-        pattern: "^[A-Fa-f0-9]{1,12}$",
-        default: "16f3b3f70fc2",
-      },
-      sliceConfigurations: {
-        type: "array",
-        title: "S-NSSAI Configuration",
-        items: { $ref: "#/definitions/SliceConfiguration" },
-        default: [
-          {
-            snssai: {
-              "sst": 1,
-              "sd": "010203",
-              "isDefault": true,
-            },
-            dnnConfigurations: [
-              {
-                dnn: "internet",
-                uplinkAmbr: "200 Mbps",
-                downlinkAmbr: "100 Mbps",
-                "5qi": 9,
-              },
-              {
-                dnn: "internet2",
-                uplinkAmbr: "200 Mbps",
-                downlinkAmbr: "100 Mbps",
-                "5qi": 9,
-              }
-            ]
+  // title: "A registration form",
+  // "description": "A simple form example.",
+  type: "object",
+  required: [
+    "userNumber",
+    "plmnID",
+    "ueId",
+    "authenticationMethod",
+    "K",
+    "OPOPcSelect",
+    "OPOPc",
+    "AMF",
+    "SQN",
+  ],
+  properties: {
+    userNumber: {
+      type: "integer",
+      title: "Subscriber data number (auto-increased with SUPI)",
+      default: 1,
+      maximum: 100000,
+      minimum: 1
+    },
+    plmnID: {
+      type: "string",
+      title: "PLMN ID",
+      pattern: "^[0-9]{5,6}$",
+      default: "20893",
+    },
+    ueId: {
+      type: "string",
+      title: "SUPI (IMSI)",
+      pattern: "^[0-9]{10,15}$",
+      default: "208930000000003",
+    },
+    msisdn: {
+      type: "string",
+      title: "MSISDN",
+      pattern: "^$|^[0-9]{5,15}$",
+      default: ""
+    },
+    authenticationMethod: {
+      type: "string",
+      title: "Authentication Method",
+      default: "5G_AKA",
+      enum: ["5G_AKA", "EAP_AKA_PRIME"],
+    },
+    K: {
+      type: "string",
+      title: "K",
+      pattern: "^[A-Fa-f0-9]{32}$",
+      default: "8baf473f2f8fd09487cccbd7097c6862",
+    },
+    OPOPcSelect: {
+      type: "string",
+      title: "Operator Code Type",
+      enum: ["OP", "OPc"],
+      default: "OPc",
+    },
+    OPOPc: {
+      type: "string",
+      title: "Operator Code Value",
+      pattern: "^[A-Fa-f0-9]{32}$",
+      default: "8e27b6af0e692e750f32667a3b14605d",
+    },
+    AMF: {
+      type: "string",
+      title: "Authentication Management Field (AMF)",
+      pattern: "^[A-Fa-f0-9]{4}$",
+      default: "8000",
+    },
+    SQN: {
+      type: "string",
+      title: "SQN",
+      pattern: "^[A-Fa-f0-9]{1,12}$",
+      default: "16f3b3f70fc2",
+    },
+    sliceConfigurations: {
+      type: "array",
+      title: "S-NSSAI Configuration",
+      items: { $ref: "#/definitions/SliceConfiguration" },
+      default: [
+        {
+          snssai: {
+            "sst": 1,
+            "sd": "010203",
+            "isDefault": true,
           },
-          {
-            snssai: {
-              "sst": 1,
-              "sd": "112233",
-              "isDefault": true,
+          dnnConfigurations: [
+            {
+              dnn: "internet",
+              uplinkAmbr: "200 Mbps",
+              downlinkAmbr: "100 Mbps",
+              "5qi": 9,
             },
-            dnnConfigurations: [
-              {
-                dnn: "internet",
-                uplinkAmbr: "200 Mbps",
-                downlinkAmbr: "100 Mbps",
-                "5qi": 9,
-              },
-              {
-                dnn: "internet2",
-                uplinkAmbr: "200 Mbps",
-                downlinkAmbr: "100 Mbps",
-                "5qi": 9,
-              }
-            ]
+            {
+              dnn: "internet2",
+              uplinkAmbr: "200 Mbps",
+              downlinkAmbr: "100 Mbps",
+              "5qi": 9,
+            }
+          ]
+        },
+        {
+          snssai: {
+            "sst": 1,
+            "sd": "112233",
+            "isDefault": true,
           },
-        ],
-      },
+          dnnConfigurations: [
+            {
+              dnn: "internet",
+              uplinkAmbr: "200 Mbps",
+              downlinkAmbr: "100 Mbps",
+              "5qi": 9,
+            },
+            {
+              dnn: "internet2",
+              uplinkAmbr: "200 Mbps",
+              downlinkAmbr: "100 Mbps",
+              "5qi": 9,
+            }
+          ]
+        },
+      ],
     },
-    definitions: {
-      Snssai: {
-        type: "object",
-        required: ["sst", "sd"],
-        properties: {
-          sst: {
-            type: "integer",
-            title: "SST",
-            minimum: 0,
-            maximum: 255,
-          },
-          sd: {
-            type: "string",
-            title: "SD",
-            pattern: "^[A-Fa-f0-9]{6}$",
-          },
-          isDefault: {
-            type: "boolean",
-            title: "Default S-NSSAI",
-            default: false,
-          },
+  },
+  definitions: {
+    Snssai: {
+      type: "object",
+      required: ["sst", "sd"],
+      properties: {
+        sst: {
+          type: "integer",
+          title: "SST",
+          minimum: 0,
+          maximum: 255,
+        },
+        sd: {
+          type: "string",
+          title: "SD",
+          pattern: "^[A-Fa-f0-9]{6}$",
+        },
+        isDefault: {
+          type: "boolean",
+          title: "Default S-NSSAI",
+          default: false,
         },
       },
-      SliceConfiguration: {
-        type: "object",
-        properties: {
-          snssai: {
-            $ref: "#/definitions/Snssai"
-          },
-          dnnConfigurations: {
-            type: "array",
-            title: "DNN Configurations",
-            items: { $ref: "#/definitions/DnnConfiguration" },
-          }
+    },
+    SliceConfiguration: {
+      type: "object",
+      properties: {
+        snssai: {
+          $ref: "#/definitions/Snssai"
+        },
+        dnnConfigurations: {
+          type: "array",
+          title: "DNN Configurations",
+          items: { $ref: "#/definitions/DnnConfiguration" },
         }
-      },
-      DnnConfiguration: {
-        type: "object",
-        required: ["dnn", "uplinkAmbr", "downlinkAmbr"],
-        properties: {
-          dnn: {
-            type: "string",
-            title: "Data Network Name"
-          },
-          uplinkAmbr: {
-            $ref: "#/definitions/bitRate",
-            title: "Uplink AMBR",
-            default: "1000 Kbps"
-          },
-          downlinkAmbr: {
-            $ref: "#/definitions/bitRate",
-            title: "Downlink AMBR",
-            default: "1000 Kbps"
-          },
-          "5qi": {
-            type: "integer",
-            minimum: 0,
-            maximum: 255,
-            title: "Default 5QI"
-          },       
-          flowRules: {
-            type: "array",
-            items: { $ref: "#/definitions/FlowInformation" },
-            maxItems: 1,
-            title: "Flow Rules"
-          },
-          upSecurityChk: {
-            "type": "boolean",
-            title: "UP Security",
-            "default": false
-          },
+      }
+    },
+    DnnConfiguration: {
+      type: "object",
+      required: ["dnn", "uplinkAmbr", "downlinkAmbr"],
+      properties: {
+        dnn: {
+          type: "string",
+          title: "Data Network Name"
         },
-        "dependencies": {
-          upSecurityChk: {
-            "oneOf": [
-              {
-                "properties": {
-                  upSecurityChk: {
-                    "enum": [false]
-                  }
-                },
-              },
-              {
-                "properties": {
-                  upSecurityChk: {
-                    "enum": [true]
-                  },
-                  upIntegrity: {
-                    type: "string",
-                    title: "Integrity of UP Security",
-                    enum: ["NOT_NEEDED", "PREFERRED", "REQUIRED"],
-                  },
-                  upConfidentiality: {
-                    type: "string",
-                    title: "Confidentiality of UP Security",
-                    enum: ["NOT_NEEDED", "PREFERRED", "REQUIRED"],
-                  },
-                },
-                "required": [
-                  "upIntegrity",
-                  "upConfidentiality"
-                ]
-              }
-            ]
-          }
+        uplinkAmbr: {
+          $ref: "#/definitions/bitRate",
+          title: "Uplink AMBR",
+          default: "1000 Kbps"
+        },
+        downlinkAmbr: {
+          $ref: "#/definitions/bitRate",
+          title: "Downlink AMBR",
+          default: "1000 Kbps"
+        },
+        "5qi": {
+          type: "integer",
+          minimum: 0,
+          maximum: 255,
+          title: "Default 5QI"
+        },
+        flowRules: {
+          type: "array",
+          items: { $ref: "#/definitions/FlowInformation" },
+          maxItems: 1,
+          title: "Flow Rules"
+        },
+        upSecurityChk: {
+          "type": "boolean",
+          title: "UP Security",
+          "default": false
         },
       },
-      FlowInformation: {
-        type: "object",
-        properties: {
-          filter: {
-            $ref: "#/definitions/IPFilter",
-            title: "IP Filter"
-          },
-          "5qi": {
-            type: "integer",
-            minimum: 0,
-            maximum: 255,
-            title: "5QI"
-          },
-          gbrUL: {
-            $ref: "#/definitions/bitRate",
-            title: "Uplink GBR",
-          },
-          gbrDL: {
-            $ref: "#/definitions/bitRate",
-            title: "Downlink GBR",
-          },
-          mbrUL: {
-            $ref: "#/definitions/bitRate",
-            title: "Uplink MBR",
-          },
-          mbrDL: {
-            $ref: "#/definitions/bitRate",
-            title: "Downlink MBR",
-          },
+      "dependencies": {
+        upSecurityChk: {
+          "oneOf": [
+            {
+              "properties": {
+                upSecurityChk: {
+                  "enum": [false]
+                }
+              },
+            },
+            {
+              "properties": {
+                upSecurityChk: {
+                  "enum": [true]
+                },
+                upIntegrity: {
+                  type: "string",
+                  title: "Integrity of UP Security",
+                  enum: ["NOT_NEEDED", "PREFERRED", "REQUIRED"],
+                },
+                upConfidentiality: {
+                  type: "string",
+                  title: "Confidentiality of UP Security",
+                  enum: ["NOT_NEEDED", "PREFERRED", "REQUIRED"],
+                },
+              },
+              "required": [
+                "upIntegrity",
+                "upConfidentiality"
+              ]
+            }
+          ]
         }
       },
-      IPFilter: {
-        type: "string",
-      },
-      bitRate: {
-        type: "string",
-        pattern: "^[0-9]+(\\.[0-9]+)? (bps|Kbps|Mbps|Gbps|Tbps)$"
-      },
     },
-  };
+    FlowInformation: {
+      type: "object",
+      properties: {
+        filter: {
+          $ref: "#/definitions/IPFilter",
+          title: "IP Filter"
+        },
+        "5qi": {
+          type: "integer",
+          minimum: 0,
+          maximum: 255,
+          title: "5QI"
+        },
+        gbrUL: {
+          $ref: "#/definitions/bitRate",
+          title: "Uplink GBR",
+        },
+        gbrDL: {
+          $ref: "#/definitions/bitRate",
+          title: "Downlink GBR",
+        },
+        mbrUL: {
+          $ref: "#/definitions/bitRate",
+          title: "Uplink MBR",
+        },
+        mbrDL: {
+          $ref: "#/definitions/bitRate",
+          title: "Downlink MBR",
+        },
+      }
+    },
+    IPFilter: {
+      type: "string",
+    },
+    bitRate: {
+      type: "string",
+      pattern: "^[0-9]+(\\.[0-9]+)? (bps|Kbps|Mbps|Gbps|Tbps)$"
+    },
+  },
+};
 
-  let subModaluiSchema = {
-    OPOPcSelect: {
-      "ui:widget": "select",
+let subModaluiSchema = {
+  OPOPcSelect: {
+    "ui:widget": "select",
+  },
+  authenticationMethod: {
+    "ui:widget": "select",
+  },
+  SliceConfiurations: {
+    "ui:options": {
+      "orderable": false
     },
-    authenticationMethod: {
-      "ui:widget": "select",
+    "isDefault": {
+      "ui:widget": "radio",
     },
-    SliceConfiurations: {
+    "dnnConfigurations": {
       "ui:options": {
         "orderable": false
       },
-      "isDefault": {
-        "ui:widget": "radio",
-      },
-      "dnnConfigurations": {
+      "flowRules": {
         "ui:options": {
           "orderable": false
         },
-        "flowRules": {
-          "ui:options": {
-            "orderable": false
-          },
-        }
       }
     }
-  };
+  }
+};
 
 let tenantSchema = {
-    // title: "A registration form",
-    // "description": "A simple form example.",
-    type: "object",
-    required: [
-      "tenantName",
-    ],
-    properties: {
-      tenantId: {
-        type: "string",
-        title: "Tenant ID",
-        pattern: "^[0-9a-zA-Z-]*$",
-        default: "",
-        readOnly: true,
-      },
-      tenantName: {
-        type: "string",
-        title: "Tenant Name",
-        default: "",
-      },
+  // title: "A registration form",
+  // "description": "A simple form example.",
+  type: "object",
+  required: [
+    "tenantName",
+  ],
+  properties: {
+    tenantId: {
+      type: "string",
+      title: "Tenant ID",
+      pattern: "^[0-9a-zA-Z-]*$",
+      default: "",
+      readOnly: true,
+    },
+    tenantName: {
+      type: "string",
+      title: "Tenant Name",
+      default: "",
     },
-  };
+  },
+};
 
 let userModalSchema = {
-    // title: "A registration form",
-    // "description": "A simple form example.",
-    type: "object",
-    required: [
-      "email",
-    ],
-    properties: {
-      userId: {
-        type: "string",
-        title: "User ID",
-        pattern: "^[0-9a-zA-Z-]*$",
-        default: "",
-        readOnly: true,
-      },
-      email: {
-        type: "string",
-        title: "User Email",
-        default: "",
-      },
-      password: {
-        type: "string",
-        title: "Password",
-        default: "",
-      },
+  // title: "A registration form",
+  // "description": "A simple form example.",
+  type: "object",
+  required: [
+    "email",
+  ],
+  properties: {
+    userId: {
+      type: "string",
+      title: "User ID",
+      pattern: "^[0-9a-zA-Z-]*$",
+      default: "",
+      readOnly: true,
+    },
+    email: {
+      type: "string",
+      title: "User Email",
+      default: "",
+    },
+    password: {
+      type: "string",
+      title: "Password",
+      default: "",
     },
-  };
+  },
+};
 
-export { subModalSchema, subModaluiSchema, tenantSchema, userModalSchema};
\ No newline at end of file
+export { subModalSchema, subModaluiSchema, tenantSchema, userModalSchema };
diff --git a/frontend/src/models/Subscriber.js b/frontend/src/models/Subscriber.js
index 863128ad6ba1260637c94118f587edf99c2c877e..648ecd2ca73d33dd3c4c210e7e8754fd83ebbf67 100644
--- a/frontend/src/models/Subscriber.js
+++ b/frontend/src/models/Subscriber.js
@@ -2,9 +2,11 @@
 export default class Subscriber {
   id = '';
   plmn = '';
+  msisdn = '';
 
-  constructor(id, plmn) {
+  constructor(id, plmn, msisdn) {
     this.id = id;
     this.plmn = plmn;
-  }
+    this.msisdn = msisdn;
+  };
 }
diff --git a/frontend/src/pages/Subscribers/SubscriberOverview.js b/frontend/src/pages/Subscribers/SubscriberOverview.js
index d21afa6a3dafc5785e2d5e30b01d60bb7aa2c6bd..826e09043d1bcbb809819b3ab8ee74b0c214c318 100644
--- a/frontend/src/pages/Subscribers/SubscriberOverview.js
+++ b/frontend/src/pages/Subscribers/SubscriberOverview.js
@@ -29,28 +29,44 @@ class SubscriberOverview extends Component {
    */
   async openEditSubscriber(subscriberId, plmn) {
     const subscriber = await ApiHelper.fetchSubscriberById(subscriberId, plmn);
-
+    let origiData = subscriber;
+    if (subscriber.FlowRules !== undefined && subscriber.FlowRules !== null) {
+      subscriber.FlowRules.forEach(FlowRule => {
+        let i = 0;
+        subscriber.QosFlows.forEach(QosFlow => {
+          if (QosFlow.snssai === FlowRule.snssai &&
+            QosFlow.dnn === FlowRule.dnn &&
+            QosFlow["5qi"] === FlowRule.qfi) {
+            if (origiData.QosFlows[i].flowRules === undefined) {
+              origiData.QosFlows[i].flowRules = [];
+            }
+            origiData.QosFlows[i].flowRules.push(Object.assign({ precedence: FlowRule.precedence, filter: FlowRule.filter }))
+          }
+          i++;
+        })
+      });
+    }
+    delete origiData.FlowRules;
     this.setState({
       subscriberModalOpen: true,
-      subscriberModalData: subscriber,
+      subscriberModalData: origiData,
     });
   }
 
   async addSubscriber(subscriberData) {
     this.setState({ subscriberModalOpen: false });
     let userNumber = subscriberData["userNumber"];
-    delete subscriberData["userNumber"];
-    let imsiLength = subscriberData["ueId"].length - 5
-    let imsi = subscriberData["ueId"].substr(5, imsiLength);
-    for(let i = 0; i < userNumber; i++){
-      let newImsi = (Number(imsi) + i).toString();
-      newImsi = newImsi.padStart(imsiLength, '0')
-      subscriberData["ueId"] = `imsi-${newImsi}`;
-      if (!await ApiHelper.createSubscriber(subscriberData)) {
+
+    if (!await ApiHelper.createSubscriber(subscriberData)) {
+      if (userNumber > 1) {
+        alert("Error creating new multiple subscribers when create user");
+      }
+      else if (userNumber === 1) {
         alert("Error creating new subscriber when create user");
       }
-      ApiHelper.fetchSubscribers().then();
     }
+    delete subscriberData["userNumber"];
+    ApiHelper.fetchSubscribers().then();
   }
 
   /**
@@ -99,7 +115,8 @@ class SubscriberOverview extends Component {
                   <thead>
                     <tr>
                       <th style={{ width: 80 }}>PLMN</th>
-                      <th colSpan={2}>UE ID</th>
+                      <th>UE ID</th>
+                      <th>MSISDN</th>
                     </tr>
                   </thead>
                   <tbody>
@@ -107,10 +124,11 @@ class SubscriberOverview extends Component {
                       <tr key={subscriber.id}>
                         <td>{subscriber.plmn}</td>
                         <td>{subscriber.id}</td>
+                        <td>{subscriber.msisdn}</td>
                         <td style={{ textAlign: 'center' }}>
                           <Button variant="danger" onClick={this.deleteSubscriber.bind(this, subscriber)}>Delete</Button>
-                         &nbsp;&nbsp;&nbsp;&nbsp;
-                        <Button variant="info" onClick={this.openEditSubscriber.bind(this, subscriber.id, subscriber.plmn)}>Modify</Button>
+                          &nbsp;&nbsp;&nbsp;&nbsp;
+                          <Button variant="info" onClick={this.openEditSubscriber.bind(this, subscriber.id, subscriber.plmn)}>Modify</Button>
                         </td>
                       </tr>
                     ))}
diff --git a/frontend/src/pages/Subscribers/components/SubscriberModal.js b/frontend/src/pages/Subscribers/components/SubscriberModal.js
index 1738f4844ba58c247df1b267e022843037c4f9dc..f74e04284a3709abf46fc4faae37c0b1c9965d8b 100644
--- a/frontend/src/pages/Subscribers/components/SubscriberModal.js
+++ b/frontend/src/pages/Subscribers/components/SubscriberModal.js
@@ -1,5 +1,5 @@
 import React, { Component } from 'react';
-import {subModalSchema, subModaluiSchema} from '../../../metadata/index'
+import { subModalSchema, subModaluiSchema } from '../../../metadata/index'
 import { Modal } from "react-bootstrap";
 import Form from "react-jsonschema-form";
 import PropTypes from 'prop-types';
@@ -7,35 +7,35 @@ import _ from 'lodash';
 
 let snssaiToString = (snssai) => snssai.sst.toString(16).padStart(2, '0').toUpperCase() + snssai.sd
 
-function dnnConfigurationFromSliceConfiguration(dnnConfig){
-  if (dnnConfig.upSecurityChk === true) {
-    return {
-      "sscModes": {
-        "defaultSscMode": "SSC_MODE_1",
-        "allowedSscModes": ["SSC_MODE_2", "SSC_MODE_3"]
-      },
-      "pduSessionTypes": {
-        "defaultSessionType": "IPV4",
-        "allowedSessionTypes": ["IPV4"]
-      },
-      "sessionAmbr": {
-        "uplink": dnnConfig.uplinkAmbr,
-        "downlink": dnnConfig.downlinkAmbr
-      },
-      "5gQosProfile": {
-        "5qi": dnnConfig["5qi"],
-        "arp": {
-          "priorityLevel": 8
-        },
-        "priorityLevel": 8
-      },
-      "upSecurity": {
-        "upIntegr": dnnConfig.upIntegrity,
-        "upConfid": dnnConfig.upConfidentiality
+function validate(formData, errors) {
+  let item = formData["sliceConfigurations"]
+  item.map(i => {
+    i.dnnConfigurations.map(d => {
+      var qfiList = new Set([]);
+      if (d.qosFlows) {
+        d.qosFlows.map(q => {
+          if (qfiList.has(q["5qi"])) {
+            errors.sliceConfigurations.addError(`The QoS Flow (qfi = ${q["5qi"]}) is already exist.`);
+          } else {
+            qfiList.add(q["5qi"]);
+          }
+          if (q["5qi"] >= 5 && (q.gbrUL || q.gbrDL)) {
+            errors.sliceConfigurations.addError(`${q["5qi"]} is non-GBR 5QI.\nthus, gbr related parameters won’t be applied.`);
+          }
+          return 0;
+        })
       }
-    }
-  }
-  return {
+      return 0;
+    })
+    return 0;
+  })
+  return errors;
+}
+
+
+
+function dnnConfigurationFromSliceConfiguration(dnnConfig) {
+  let obj = {
     "sscModes": {
       "defaultSscMode": "SSC_MODE_1",
       "allowedSscModes": ["SSC_MODE_2", "SSC_MODE_3"]
@@ -56,6 +56,22 @@ function dnnConfigurationFromSliceConfiguration(dnnConfig){
       "priorityLevel": 8
     }
   }
+
+  if (dnnConfig.upSecurityChk === true) {
+    obj["upSecurity"] = {
+      "upIntegr": dnnConfig.upIntegrity,
+      "upConfid": dnnConfig.upConfidentiality
+    }
+  }
+
+  if (dnnConfig.staticIP !== undefined && dnnConfig.staticIP.length !== 0) {
+    obj["staticIpAddress"] = [
+      {
+        "ipv4Addr": dnnConfig.staticIP
+      }
+    ]
+  }
+  return obj
 }
 
 function smDatasFromSliceConfiguration(sliceConfiguration) {
@@ -75,13 +91,33 @@ function smDatasFromSliceConfiguration(sliceConfiguration) {
   })
 }
 
+function qosFlowsFromSliceConfiguration(sliceConfigurations) {
+  var qosFlows = [];
+  sliceConfigurations.forEach(slice => {
+    slice.dnnConfigurations.forEach(dnn => {
+      if (dnn.qosFlows !== undefined) {
+        dnn.qosFlows.forEach(qosFlow => {
+          qosFlows.push(
+            Object.assign({ snssai: snssaiToString(slice.snssai), dnn: dnn.dnn, qfi: qosFlow["5qi"] },
+              qosFlow))
+        })
+      }
+    })
+  })
+  return qosFlows
+}
+
 function flowRulesFromSliceConfiguration(sliceConfigurations) {
   var flowRules = []
   sliceConfigurations.forEach(slice => {
     slice.dnnConfigurations.forEach(dnn => {
-      if (dnn.flowRules !== undefined) {
-        dnn.flowRules.forEach(flowRule => {
-          flowRules.push(Object.assign({ snssai: snssaiToString(slice.snssai), dnn: dnn.dnn }, flowRule))
+      if (dnn.qosFlows !== undefined) {
+        dnn.qosFlows.forEach(qosFlow => {
+          if (qosFlow.flowRules !== undefined) {
+            qosFlow.flowRules.forEach(flowRule => {
+              flowRules.push(Object.assign({ snssai: snssaiToString(slice.snssai), dnn: dnn.dnn, qfi: qosFlow["5qi"] }, flowRule))
+            })
+          }
         })
       }
     })
@@ -119,29 +155,42 @@ function sliceConfigurationsFromSubscriber(subscriber) {
   sliceConfigurations.forEach(sliceConf => {
     const dnnConfigs = sessionManagementSubscriptionData.find(data => data.singleNssai.sst === sliceConf.snssai.sst && data.singleNssai.sd === sliceConf.snssai.sd).dnnConfigurations;
     sliceConf.dnnConfigurations = Object.keys(dnnConfigs).map(dnn => {
-      let flowRules = [];
-      const flowRulesData = subscriber["FlowRules"];
-      if(flowRulesData && flowRulesData.length !== 0) {
-        flowRules = flowRulesData
-        .filter(rule => rule.snssai === snssaiToString(sliceConf.snssai) && dnn === rule.dnn)
-        .map(rule => {
-          return {
-            filter: rule.filter,
-            "5qi": rule["5qi"],
-            gbrUL: rule.gbrUL,
-            gbrDL: rule.gbrDL,
-            mbrUL: rule.mbrUL,
-            mbrDL: rule.mbrDL  
-          }
-        })
+
+      let qosFlows = [];
+      const qosFlowsData = subscriber["QosFlows"];
+      if (qosFlowsData && qosFlowsData.length !== 0) {
+        qosFlows = qosFlowsData
+          .filter(rule => rule.snssai === snssaiToString(sliceConf.snssai) && dnn === rule.dnn)
+          .map(rule => {
+            return {
+              "5qi": rule["5qi"],
+              gbrUL: rule.gbrUL,
+              gbrDL: rule.gbrDL,
+              mbrUL: rule.mbrUL,
+              mbrDL: rule.mbrDL,
+              flowRules: rule.flowRules
+            }
+          })
       }
-      if (dnnConfigs[dnn].upSecurity){
+
+
+
+
+      let staticIps = "";
+      const staticIpAddress = dnnConfigs[dnn].staticIpAddress
+      if (staticIpAddress && staticIpAddress.length !== 0) {
+        staticIps += staticIpAddress.reduce((total, element) => {
+          return total + element["ipv4Addr"]
+        }, "")
+      }
+      if (dnnConfigs[dnn].upSecurity) {
         return {
           dnn: dnn,
+          staticIP: staticIps,
           uplinkAmbr: dnnConfigs[dnn].sessionAmbr.uplink,
           downlinkAmbr: dnnConfigs[dnn].sessionAmbr.downlink,
           "5qi": dnnConfigs[dnn]["5gQosProfile"]["5qi"],
-          flowRules: flowRules,
+          qosFlows: qosFlows,
           upSecurityChk: true,
           upIntegrity: dnnConfigs[dnn].upSecurity.upIntegr,
           upConfidentiality: dnnConfigs[dnn].upSecurity.upConfid
@@ -149,10 +198,11 @@ function sliceConfigurationsFromSubscriber(subscriber) {
       }
       return {
         dnn: dnn,
+        staticIP: staticIps,
         uplinkAmbr: dnnConfigs[dnn].sessionAmbr.uplink,
         downlinkAmbr: dnnConfigs[dnn].sessionAmbr.downlink,
         "5qi": dnnConfigs[dnn]["5gQosProfile"]["5qi"],
-        flowRules: flowRules
+        qosFlows: qosFlows
       };
     });
   });
@@ -186,10 +236,12 @@ class SubscriberModal extends Component {
       if (this.props.subscriber) {
         const subscriber = this.props.subscriber;
         const isOp = subscriber['AuthenticationSubscription']["milenage"]["op"]["opValue"] !== "";
-
+        //get the index of msisdn in gpsis
+        let msisdnId = subscriber['AccessAndMobilitySubscriptionData']["gpsis"].findIndex(gpsi => gpsi.includes("msisdn-"));
         let formData = {
           plmnID: subscriber['plmnID'],
           ueId: subscriber['ueId'].replace("imsi-", ""),
+          msisdn: msisdnId === -1 ? null : subscriber['AccessAndMobilitySubscriptionData']["gpsis"][msisdnId].replace("msisdn-", ""),
           authenticationMethod: subscriber['AuthenticationSubscription']["authenticationMethod"],
           K: subscriber['AuthenticationSubscription']["permanentKey"]["permanentKeyValue"],
           OPOPcSelect: isOp ? "OP" : "OPc",
@@ -199,6 +251,7 @@ class SubscriberModal extends Component {
           sliceConfigurations: sliceConfigurationsFromSubscriber(subscriber),
         };
 
+
         this.updateFormData(formData).then();
       }
     }
@@ -248,7 +301,7 @@ class SubscriberModal extends Component {
       "plmnID": formData["plmnID"], // Change required
       "ueId": "imsi-" + formData["ueId"], // Change required
       "AuthenticationSubscription": {
-        "authenticationManagementField": "8000",
+        "authenticationManagementField": formData["AMF"],
         "authenticationMethod": formData["authenticationMethod"], // "5G_AKA", "EAP_AKA_PRIME"
         "milenage": {
           "op": {
@@ -271,7 +324,7 @@ class SubscriberModal extends Component {
       },
       "AccessAndMobilitySubscriptionData": {
         "gpsis": [
-          "msisdn-0900000000"
+          formData["msisdn"] === undefined ? null : "msisdn-" + formData["msisdn"]
         ],
         "nssai": {
           "defaultSingleNssais": _(formData["sliceConfigurations"])
@@ -292,7 +345,7 @@ class SubscriberModal extends Component {
           _.map(formData["sliceConfigurations"], slice => [snssaiToString(slice.snssai),
           {
             "dnnInfos": _.map(slice.dnnConfigurations, dnnCofig => {
-              return {"dnn": dnnCofig.dnn}
+              return { "dnn": dnnCofig.dnn }
             })
           }]))
       },
@@ -319,10 +372,10 @@ class SubscriberModal extends Component {
             )
           }]))
       },
-      "FlowRules": flowRulesFromSliceConfiguration(formData["sliceConfigurations"])
+      "FlowRules": flowRulesFromSliceConfiguration(formData["sliceConfigurations"]),
+      "QosFlows": qosFlowsFromSliceConfiguration(formData["sliceConfigurations"]),
     };
-
-    if(this.state.editMode) {
+    if (this.state.editMode) {
       this.props.onModify(subscriberData);
     } else {
       this.props.onSubmit(subscriberData);
@@ -347,6 +400,7 @@ class SubscriberModal extends Component {
             <Form schema={this.schema}
               uiSchema={this.uiSchema}
               formData={this.state.formData}
+              validate={validate}
               onChange={this.onChange.bind(this)}
               onSubmit={this.onSubmitClick.bind(this)} />
           }
diff --git a/frontend/src/pages/Tasks/TasksOverview.js b/frontend/src/pages/Tasks/TasksOverview.js
index ae4ad388cd58b5f25a391d952c821925eefb8126..abc9040f65e6e38d48a96342c9024843bfeae154 100644
--- a/frontend/src/pages/Tasks/TasksOverview.js
+++ b/frontend/src/pages/Tasks/TasksOverview.js
@@ -13,7 +13,7 @@ class TasksOverview extends Component {
     this.targetDownloaded = false;
   }
 
-  componentWillMount() {
+  componentDidMount() {
     this.refreshEnabled = true;
     this.updateTasksTable().then();
   }
@@ -22,8 +22,8 @@ class TasksOverview extends Component {
     this.refreshEnabled = false;
   }
 
-  componentWillReceiveProps(nextProps) {
-    let urlParams = queryString.parse(this.props.location.search);
+  static getDerivedStateFromProps(nextProps, prevState){
+    let urlParams = queryString.parse(nextProps.location.search);
 
     if (urlParams['target'] !== undefined) {
       let dashedUuid = AppUtils.dashUuid(urlParams['target']);
diff --git a/frontend/src/util/ApiHelper.js b/frontend/src/util/ApiHelper.js
index b1a0a4b43f57ef1c7f2f1a3793ff4cd006502582..44b83d22c3f8a0ee0219e143775d897a1f9f1ab7 100644
--- a/frontend/src/util/ApiHelper.js
+++ b/frontend/src/util/ApiHelper.js
@@ -1,5 +1,5 @@
 import Http from './Http';
-import {store} from '../index';
+import { store } from '../index';
 import subscriberActions from "../redux/actions/subscriberActions";
 import Subscriber from "../models/Subscriber";
 import tenantActions from "../redux/actions/tenantActions";
@@ -17,7 +17,7 @@ class ApiHelper {
       axios.defaults.headers.common['Token'] = user.accessToken;
       let response = await Http.get('subscriber');
       if (response.status === 200 && response.data) {
-        const subscribers = response.data.map(val => new Subscriber(val['ueId'], val['plmnID']));
+        const subscribers = response.data.map(val => new Subscriber(val['ueId'], val['plmnID'], val['msisdn']));
         store.dispatch(subscriberActions.setSubscribers(subscribers));
         return true;
       }
@@ -44,7 +44,7 @@ class ApiHelper {
       let user = LocalStorageHelper.getUserInfo();
       axios.defaults.headers.common['Token'] = user.accessToken;
       let response = await Http.post(
-        `subscriber/${subscriberData["ueId"]}/${subscriberData["plmnID"]}`, subscriberData);
+        `subscriber/${subscriberData["ueId"]}/${subscriberData["plmnID"]}/${subscriberData["userNumber"]}`, subscriberData);
       if (response.status === 201)
         return true;
     } catch (error) {
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index 600a44c95ed9a80b3ffa91fea92634197bfe0494..628941f381026d4760135fcea36cf8bed71687e9 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -130,6 +130,11 @@
     "@babel/helper-validator-identifier" "^7.16.7"
     to-fast-properties "^2.0.0"
 
+"@fortawesome/fontawesome-free@^5.15.2":
+  version "5.15.2"
+  resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.2.tgz#218cd7276ab4f9ab57cc3d2efa2697e6a579f25d"
+  integrity sha512-7l/AX41m609L/EXI9EKH3Vs3v0iA8tKlIOGtw+kgcoanI7p+e4I4GYLqW3UXWiTnjSFymKSmTTPKYrivzbxxqA==
+
 "@jridgewell/gen-mapping@^0.3.0":
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz#cf92a983c83466b8c0ce9124fadeaf09f7c66ea9"
@@ -1487,6 +1492,11 @@ boolbase@~1.0.0:
   resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
   integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
 
+bootstrap@~3.3.6:
+  version "3.3.7"
+  resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-3.3.7.tgz#5a389394549f23330875a3b150656574f8a9eb71"
+  integrity sha1-WjiTlFSfIzMIdaOxUGVldPip63E=
+
 boxen@^1.2.1:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
@@ -5784,12 +5794,12 @@ lodash.uniq@^4.5.0:
   resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
   integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
 
-"lodash@>=3.5 <5", lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.14, lodash@^4.17.3, lodash@^4.2.1, lodash@^4.3.0:
+"lodash@>=3.5 <5", lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.14, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.1, lodash@^4.3.0:
   version "4.17.15"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
   integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
 
-lodash@^4.17.15, lodash@^4.17.4:
+lodash@^4.17.15:
   version "4.17.21"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
   integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -8191,7 +8201,7 @@ sass-loader@^7.0.1:
     pify "^4.0.1"
     semver "^6.3.0"
 
-sass@^1.50.0:
+sass@1.51.0:
   version "1.51.0"
   resolved "https://registry.yarnpkg.com/sass/-/sass-1.51.0.tgz#25ea36cf819581fe1fe8329e8c3a4eaaf70d2845"
   integrity sha512-haGdpTgywJTvHC2b91GSq+clTKGbtkkZmVAb82jZQN/wTy6qs8DdFm2lhEQbEwrY0QDRgSQ3xDurqM977C3noA==
diff --git a/go.mod b/go.mod
index 85a5477d66525b7006f441d4f358a39c1cc1d1ed..9f4553cda911510d40bf6830b87276631f9dac3f 100644
--- a/go.mod
+++ b/go.mod
@@ -1,11 +1,11 @@
 module github.com/free5gc/webconsole
 
-go 1.14
+go 1.17
 
 require (
-	github.com/antonfisher/nested-logrus-formatter v1.3.1
-	github.com/free5gc/openapi v1.0.4
-	github.com/free5gc/util v1.0.3
+	github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
+	github.com/free5gc/openapi v1.0.6
+	github.com/free5gc/util v1.0.5-0.20230306071612-a52909216bd2
 	github.com/gin-contrib/cors v1.3.1
 	github.com/gin-gonic/gin v1.7.7
 	github.com/golang-jwt/jwt v3.2.1+incompatible
@@ -17,3 +17,38 @@ require (
 	golang.org/x/crypto v0.1.0
 	gopkg.in/yaml.v2 v2.4.0
 )
+
+require (
+	github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
+	github.com/evanphx/json-patch v0.5.2 // indirect
+	github.com/gin-contrib/sse v0.1.0 // indirect
+	github.com/go-playground/locales v0.13.0 // indirect
+	github.com/go-playground/universal-translator v0.17.0 // indirect
+	github.com/go-playground/validator/v10 v10.4.1 // indirect
+	github.com/go-stack/stack v1.8.0 // indirect
+	github.com/golang/protobuf v1.5.2 // indirect
+	github.com/golang/snappy v0.0.1 // indirect
+	github.com/google/go-cmp v0.5.6 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/klauspost/compress v1.13.6 // indirect
+	github.com/kr/pretty v0.2.0 // indirect
+	github.com/leodido/go-urn v1.2.0 // indirect
+	github.com/mattn/go-isatty v0.0.14 // indirect
+	github.com/mitchellh/mapstructure v1.4.2 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/russross/blackfriday/v2 v2.1.0 // indirect
+	github.com/tim-ywliu/nested-logrus-formatter v1.3.2 // indirect
+	github.com/ugorji/go/codec v1.1.7 // indirect
+	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
+	github.com/xdg-go/scram v1.0.2 // indirect
+	github.com/xdg-go/stringprep v1.0.2 // indirect
+	github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
+	golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
+	golang.org/x/sys v0.5.0 // indirect
+	golang.org/x/text v0.7.0 // indirect
+	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
+	google.golang.org/protobuf v1.27.1 // indirect
+	gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/go.sum b/go.sum
index b08c8e558633530e2fd0ddc7ccc6cc7e43f2bc41..bd8cb9244a54f305d31535c7ab4c7d1d10e58715 100644
--- a/go.sum
+++ b/go.sum
@@ -34,8 +34,6 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/antonfisher/nested-logrus-formatter v1.3.1 h1:NFJIr+pzwv5QLHTPyKz9UMEoHck02Q9L0FP13b/xSbQ=
-github.com/antonfisher/nested-logrus-formatter v1.3.1/go.mod h1:6WTfyWFkBc9+zyBaKIqRrg/KwMqBbodBjgbHjDz7zjA=
 github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
 github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -44,8 +42,9 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
+github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -55,16 +54,15 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/evanphx/json-patch v0.5.2 h1:xVCHIVMUu1wtM/VkR9jVZ45N3FhZfYMMYGorLCR8P3k=
 github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
-github.com/free5gc/openapi v1.0.4 h1:bC6oqXy8Z+3e532xLMFmrTHvdyv4sNGDPezQSslw5gQ=
-github.com/free5gc/openapi v1.0.4/go.mod h1:KRCnnp0GeK0Bl4gnrX79cQAidKXNENf8VRdG0y9R0Fc=
-github.com/free5gc/util v1.0.3 h1:or/gqHCAi3j2YKd+nzViRnc/tl1tuuJAYxCao6IbOAU=
-github.com/free5gc/util v1.0.3/go.mod h1:DL1Dnryh//Ps5B+hfXbhU1R07fVfrmPs4uuTO4g9yTg=
+github.com/free5gc/openapi v1.0.6 h1:ytRjU/YZRI8UhKKyfajXSyGB6s1YDFkJ1weeAGJ8LXw=
+github.com/free5gc/openapi v1.0.6/go.mod h1:iw/N0E+FlX44EEx24IBi2EdZW8v+bkj3ETWPGnlK9DI=
+github.com/free5gc/util v1.0.5-0.20230306071612-a52909216bd2 h1:FG8KlJ46Epscj3F9XBAKuDGJD9kSKJdstCL9fttjUjE=
+github.com/free5gc/util v1.0.5-0.20230306071612-a52909216bd2/go.mod h1:fgV0hXf5arxAWs8D9LfrrfNByZ1IDCWYlgBzncy5GtE=
 github.com/gin-contrib/cors v1.3.1 h1:doAsuITavI4IOcd0Y19U4B+O0dNWihRyX//nn4sEmgA=
 github.com/gin-contrib/cors v1.3.1/go.mod h1:jjEJ4268OPZUcU7k9Pm653S7lXUGcqMADzFA61xsmDk=
 github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
 github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
 github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
-github.com/gin-gonic/gin v1.7.3/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
 github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
 github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@@ -107,8 +105,10 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
 github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
 github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
 github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
-github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
 github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@@ -120,8 +120,10 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
 github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -145,8 +147,9 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
 github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
 github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
 github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
@@ -154,8 +157,9 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
 github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
-github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
+github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@@ -163,14 +167,18 @@ github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdA
 github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
 github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
 github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
-github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
+github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
 github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
+github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
+github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
 github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -179,9 +187,9 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
+github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
 github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
@@ -198,8 +206,11 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/tim-ywliu/nested-logrus-formatter v1.3.2 h1:jugNJ2/CNCI79SxOJCOhwUHeN3O7/7/bj+ZRGOFlCSw=
+github.com/tim-ywliu/nested-logrus-formatter v1.3.2/go.mod h1:oGPmcxZB65j9Wo7mCnQKSrKEJtVDqyjD666SGmyStXI=
 github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
 github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
+github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
 github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
 github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
 github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU=
@@ -290,9 +301,9 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
 golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
+golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -308,6 +319,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -338,26 +351,28 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
 golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
 golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -481,11 +496,15 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
-google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
+google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
 gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
@@ -494,8 +513,9 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/server.go b/server.go
index 51ebabd2861776c0e79a5855ca8f8da388a768a3..4289a98e6d14f783b61d8df61b91585669b09888 100644
--- a/server.go
+++ b/server.go
@@ -1,50 +1,94 @@
 package main
 
 import (
-	"fmt"
 	"os"
+	"path/filepath"
+	"runtime/debug"
 
 	"github.com/urfave/cli"
 
+	logger_util "github.com/free5gc/util/logger"
 	"github.com/free5gc/util/version"
+	"github.com/free5gc/webconsole/backend/factory"
 	"github.com/free5gc/webconsole/backend/logger"
 	"github.com/free5gc/webconsole/backend/webui_service"
 )
 
-var WEBUI = &webui_service.WEBUI{}
+var WEBUI *webui_service.WebuiApp
 
 func main() {
+	defer func() {
+		if p := recover(); p != nil {
+			// Print stack for panic to log. Fatalf() will let program exit.
+			logger.MainLog.Fatalf("panic: %v\n%s", p, string(debug.Stack()))
+		}
+	}()
 	app := cli.NewApp()
 	app.Name = "webui"
 	app.Usage = "free5GC Web Console"
 	app.Action = action
-	app.Flags = WEBUI.GetCliCmd()
+	app.Flags = []cli.Flag{
+		cli.StringFlag{
+			Name:  "config, c",
+			Usage: "Load configuration from `FILE`",
+		},
+		cli.StringSliceFlag{
+			Name:  "log, l",
+			Usage: "Output NF log to `FILE`",
+		},
+	}
 	if err := app.Run(os.Args); err != nil {
-		logger.AppLog.Errorf("Web Console Run error: %v", err)
+		logger.MainLog.Errorf("WEBUI Run error: %v\n", err)
 	}
 }
 
-func action(c *cli.Context) error {
-	if err := initLogFile(c.String("log"), c.String("log5gc")); err != nil {
-		logger.AppLog.Errorf("%+v", err)
+func action(cliCtx *cli.Context) error {
+	tlsKeyLogPath, err := initLogFile(cliCtx.StringSlice("log"))
+	if err != nil {
 		return err
 	}
 
-	if err := WEBUI.Initialize(c); err != nil {
-		return fmt.Errorf("Failed to initialize !! %+v", err)
+	logger.MainLog.Infoln("WEBUI version: ", version.GetVersion())
+
+	cfg, err := factory.ReadConfig(cliCtx.String("config"))
+	if err != nil {
+		return err
 	}
+	factory.WebuiConfig = cfg
 
-	logger.AppLog.Infoln(c.App.Name)
-	logger.AppLog.Infoln("webconsole version: ", version.GetVersion())
+	webui, err := webui_service.NewApp(cfg)
+	if err != nil {
+		return err
+	}
+	WEBUI = webui
 
-	WEBUI.Start()
+	webui.Start(tlsKeyLogPath)
 
 	return nil
 }
 
-func initLogFile(logNfPath, log5gcPath string) error {
-	if err := logger.LogFileHook(logNfPath, log5gcPath); err != nil {
-		return err
+func initLogFile(logNfPath []string) (string, error) {
+	logTlsKeyPath := ""
+
+	for _, path := range logNfPath {
+		if err := logger_util.LogFileHook(logger.Log, path); err != nil {
+			return "", err
+		}
+		if logTlsKeyPath != "" {
+			continue
+		}
+
+		nfDir, _ := filepath.Split(path)
+		tmpDir := filepath.Join(nfDir, "key")
+		if err := os.MkdirAll(tmpDir, 0o775); err != nil {
+			logger.InitLog.Errorf("Make directory %s failed: %+v", tmpDir, err)
+
+			return "", err
+		}
+
+		_, name := filepath.Split(factory.WebuiDefaultTLSKeyLogPath)
+		logTlsKeyPath = filepath.Join(tmpDir, name)
 	}
-	return nil
+
+	return logTlsKeyPath, nil
 }