diff --git a/.gitignore b/.gitignore
index 8846f37d..ddc9524e 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 8d1b24be..01410334 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 e16bd44e..e6fa7d6c 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 00000000..648cc417
--- /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 0a41309f..3efde2ad 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 b4f3000c..5fd51c3b 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 226b0a36..a3ab212c 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 8ddbe212..5de44c58 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 205206fe..57726b37 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 db51f6d1..e7b8a089 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 00036ac7..37aa6346 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 a69527e9..ce498ed6 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 f837ab76..ed7aff34 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 451b419e..37f556ae 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 d038b4d1..3182307d 100644
--- a/frontend/public/index.html
+++ b/frontend/public/index.html
@@ -4,10 +4,6 @@
-
-
-
-