package handle import ( "bytes" "encoding/json" "io" "net/http" "strconv" "strings" "be.ems/lib/dborm" "github.com/gorilla/mux" g "github.com/gosnmp/gosnmp" "be.ems/lib/global" "be.ems/lib/log" "be.ems/lib/oauth" "be.ems/lib/services" "be.ems/lib/session" "be.ems/restagent/config" ) var TodoList []stTodo type stTodo struct { No string Item string Value string } type ErrorOAuthResponse struct { Error map[string]interface{} } type FailOAuthResponse struct { Error struct { ErrorCode string ErrorInfo string } } type ApiResponse struct { ResultCode string ResultMessage interface{} } var globalSession = session.NewSessManager("restagent") func init() { conf := config.GetYamlConfig() // Default is a pointer to a GoSNMP struct that contains sensible defaults // eg port 161, community public, etc g.Default.Target = conf.NE.Addr g.Default.Port = conf.NE.Port err := g.Default.Connect() if err != nil { log.Fatalf("Connect() err: %v", err) } //defer g.Default.Conn.Close() } /* func IsValidOAuthInfo(oAuthBody OAuthBody) bool { log.Debug("IsValidOAuthInfo processing... ") conf := config.GetYamlConfig() for _, o := range conf.Auth { if oAuthBody.GrantType == o.Type && oAuthBody.UserName == o.User && oAuthBody.Value == o.Password { return true } } return false } func IsWrongOAuthInfo(oAuthBody OAuthBody) bool { log.Debug("IsWrongOAuthInfo processing... ") if oAuthBody.GrantType == "" || strings.ToLower(oAuthBody.GrantType) != "password" || oAuthBody.UserName == "" || oAuthBody.Value == "" { return true } return false } */ func IsValidOAuthUri(r *http.Request) bool { vars := mux.Vars(r) Uri := vars["apiCategory"] + "/" + vars["apiVersion"] // 获取Uri if Uri != "securityManagement/v1" { return false } return true } func IsVallidContentType(r *http.Request) bool { log.Debug("IsVallidContentType processing ...") ctype := r.Header["Content-Type"] if len(ctype) != 0 && !strings.Contains(ctype[0], "application/json") { return false } return true } func LoginFromOMC(w http.ResponseWriter, r *http.Request) { log.Debug("LoginFromOMC processing... ") body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小 if err != nil { log.Debug(err) services.ResponseNotFound404UriNotExist(w, r) return } // check media type(content type) only support "application/json" /* if !IsVallidContentType(r) { log.Debug("Invalid Content-Type") services.ResponseUnsupportedMediaType415(w) return } // check extend uri, response 404 if !IsValidOAuthUri(r) { log.Debug("Uri is invalid") services.ResponseNotFound404UriNotExist(w, r) return } */ // Error process .... // response 400-7 if !json.Valid([]byte(body)) { log.Debug("Invalid Json Format") services.ResponseBadRequest400InvalidJson(w) return } var oAuthBody oauth.OAuthBody _ = json.Unmarshal(body, &oAuthBody) //转为json log.Debug("body:", string(body), "oAuthBody:", oAuthBody) defer r.Body.Close() // response 400-5 if oauth.IsWrongOAuthInfo(oAuthBody) { log.Debug("Wrong parameter value") services.ResponseBadRequest400WrongParamValue(w) return } /* if oauth.IsValidOAuthInfo(oAuthBody) { plist := config.GetPermissionFromConfig(oAuthBody.UserName, oAuthBody.GrantType) log.Debug("Permission list:", plist) token := globalSession.NewSession(w, r, plist) services.ResponseStatusOK200Login(w, token) } else { // response 400-4 log.Debug("Authentication failed, mismatch user or password") services.ResponseBadRequest400IncorrectLogin(w) } */ validUser, changePassword, _ := dborm.XormCheckLoginUser(oAuthBody.UserName, oAuthBody.Value, config.GetYamlConfig().Auth.Crypt) if validUser { // plist := config.GetPermissionFromConfig(oAuthBody.UserName, oAuthBody.GrantType) plist := []bool{true, true, true, true} log.Debug("Permission list:", plist) token := globalSession.NewSession(w, r, plist) services.ResponseStatusOK200Login(w, token, changePassword) } else { // response 400-4 log.Error("Authentication failed, mismatch user or password") services.ResponseBadRequest400IncorrectLogin(w) } return } func LogoutFromOMC(w http.ResponseWriter, r *http.Request) { log.Debug("LogoutFromOMC processing... ") // check media type(content type) only support "application/json" if !IsVallidContentType(r) { log.Debug("Invalid Content-Type") services.ResponseUnsupportedMediaType415(w) return } // check extend uri, response 404 if !IsValidOAuthUri(r) { log.Debug("Uri is invalid") services.ResponseNotFound404UriNotExist(w, r) return } // error processing ... // 401-1 response token, ret := globalSession.IsCarriedToken(r) if ret == false { log.Debug("AccessToken is not carried") services.ResponseUnauthorized401AccessTokenNotCarried(w) return } // 401-2 response if globalSession.IsValidToken(token) == false { log.Debug("AccessToken fails or does not exist") services.ResponseUnauthorized401AccessTokenNotExist(w) return } globalSession.EndSession(w, r) services.ResponseStatusOK200Null(w) return } func HandshakeFromOMC(w http.ResponseWriter, r *http.Request) { log.Debug("HandshakeFromOMC processing... ") // check media type(content type) only support "application/json" if !IsVallidContentType(r) { log.Debug("Invalid Content-Type") services.ResponseUnsupportedMediaType415(w) return } // check extend uri, response 404 if !IsValidOAuthUri(r) { log.Debug("Uri is invalid") services.ResponseNotFound404UriNotExist(w, r) return } // error processing ... // 401-1 response token, ret := globalSession.IsCarriedToken(r) if ret == false { log.Debug("AccessToken is not carried") services.ResponseUnauthorized401AccessTokenNotCarried(w) return } if !globalSession.ShakeSession(token) { // 401-2 response log.Debug("AccessToken fails or does not exist") services.ResponseUnauthorized401AccessTokenNotExist(w) return } // 200 response services.ResponseStatusOK200Null(w) return } var ( MAX_RMUID_NUM = config.GetRmUIDMaxNumFromConfig() MAX_ALARMID_NUM = config.GetAlarmIDMaxNumFromConfig() MAX_PMUID_NUM = config.GetPmIDMaxNumFromConfig() MAX_SUBID_NUM = config.GetSubIDMaxNumFromConfig() MAX_URI_LEN = config.GetUriMaxLenFromConfig() RMUID_REGEXP = config.GetRmUIDRegexpFromConfig() ) func CheckParameterName(r *http.Request) []string { var errorParams []string vars := r.URL.Query() for k, v := range vars { log.Debug("vars:", k, v) if k != "rmUIDs" && k != "fields" { errorParams = append(errorParams, k) } } return errorParams } func GetRmUIDArr(r *http.Request) []string { vars := r.URL.Query() rmUIDs, ok := vars["rmUIDs"] if !ok { log.Debug("rmUIDs is not exist") return nil } var rmUIDValues []string for _, r := range rmUIDs { if r != "" { rmUIDValues = global.MergeStringArr(rmUIDValues, strings.Split(r, `,`)) } } return rmUIDValues } func GetAttrNameArr(r *http.Request) []string { vars := r.URL.Query() fields, ok := vars["fields"] if !ok { log.Debug("attributeNames does not exist") return nil } var attrNames []string for _, a := range fields { if a != "" { attrNames = global.MergeStringArr(attrNames, strings.Split(a, `,`)) } } return attrNames } func CheckValidRmUID(rmUIDs []string) []string { log.Debug("GetLocalRmUID processing... ") var invalidRmUIDs []string for _, r := range rmUIDs { if !global.MatchRmUID(RMUID_REGEXP, r) { invalidRmUIDs = append(invalidRmUIDs, r) } } return invalidRmUIDs } func CheckLocalRmUID(rmUIDs []string) string { log.Debug("GetLocalRmUID processing... ") rmUID := config.GetRmUIDFromConfig() for _, r := range rmUIDs { if r == rmUID { return rmUID } } return "" } func GetNRMByUri(w http.ResponseWriter, r *http.Request) { log.Debug("GetNRMByUri processing... ") // response 414-4 uri too long ? (optional) // todo ... ? if bytes.Count([]byte(r.RequestURI), nil) > MAX_URI_LEN { log.Debug("Request Uri too long:", bytes.Count([]byte(r.RequestURI), nil)) services.ResponseRequestURITooLong414UriTooLong(w) return } // check media type(content type) only support "application/json" // response 415-1 if !IsVallidContentType(r) { log.Debug("Invalid Content-Type") services.ResponseUnsupportedMediaType415(w) return } // error processing ... // 401-1 response token, ret := globalSession.IsCarriedToken(r) if ret == false { log.Debug("AccessToken is not carried") services.ResponseUnauthorized401AccessTokenNotCarried(w) return } // 401-2 response if globalSession.IsValidToken(token) == false { log.Debug("AccessToken fails or does not exist") services.ResponseUnauthorized401AccessTokenNotExist(w) return } // response 403 Forbidden, permissions deny // todo... plist := globalSession.GetPermissionFromSession(token) log.Debug("permission list:", plist) if len(plist) == 0 || plist[0] == false { log.Debug("User permission deny") services.ResponseForbidden403NotPermission(w) return } vars := mux.Vars(r) qeuryUri := vars["apiCategory"] + "/" + vars["elementTypeValue"] + "/" + vars["objectTypeValue"] log.Debug("Get by Uri: ", qeuryUri) apiVer := vars["apiVersion"] if apiVer != "v1" { log.Debug("Uri is invalid") services.ResponseNotFound404UriNotExist(w, r) return } // response 406-1 rmUIDValues := GetRmUIDArr(r) if rmUIDValues == nil { log.Debug("missing parameter: rmUIDs") services.ResponseNotAcceptable406MissingParam(w) return } // response 406-2 errorParams := CheckParameterName(r) if errorParams != nil { log.Debug("parameter name error: ", errorParams) services.ResponseNotAcceptable406ParamError(w, errorParams) return } // response 400-5 if len(rmUIDValues) == 0 { log.Debug("rmUIDs is wrong or NULL") services.ResponseBadRequest400WrongParamValue(w) return } // response 414-1 if len(rmUIDValues) > MAX_RMUID_NUM { log.Debug("rmUID greater than", MAX_RMUID_NUM) services.ResponseRequestURITooLong414NRMNumExceed(w, MAX_RMUID_NUM) return } // response 400-1 // check rmUID is valid // todo ... invalidRmUIDs := CheckValidRmUID(rmUIDValues) if len(invalidRmUIDs) != 0 { log.Debug("rmUID is invalid") services.ResponseBadRequest400RmUIDsIsInvalid(w, invalidRmUIDs) return } // response 404-2 rmUID := CheckLocalRmUID(rmUIDValues) if rmUID == "" { log.Debug("rmUID does not exist") services.ResponseNotFound404NRMNotExist(w, rmUIDValues) return } // response 404-1, uri is not exist in map attrNames := GetAttrNameArr(r) var Oids []string Oids = *config.GetOidByFileds(qeuryUri, attrNames, &Oids) if len(Oids) == 0 { log.Debug("Nothing of config map") services.ResponseNotFound404UriNotExist(w, r) return } // response 404-1, uri is not exist in map var nameOids []config.NameOid nameOids = *config.GetDataOidByFields(qeuryUri, attrNames, &nameOids) if len(nameOids) == 0 { log.Debug("Nothing of config map") services.ResponseNotFound404UriNotExist(w, r) return } result, err2 := g.Default.Get(Oids) // Get() accepts up to g.MAX_OIDS if err2 != nil { log.Fatalf("Get() err: %v", err2) } // var nameValues []config.NameValue var nameValue config.NameValue nameValues := make(map[string]interface{}) nameValues["rmUID"] = rmUID for i, variable := range result.Variables { nameValue.Name = nameOids[i].Name log.Debugf("%d: oid: %s name: %s\n", i, variable.Name, nameValue.Name) // if nameOids[i].Oid == variable.Name && global.IsContain(attributeNames, nameValue.Name) { if nameOids[i].Oid == variable.Name { // the Value of each variable returned by Get() implements // interface{}. You could do a type switch... switch variable.Type { case g.OctetString: bytes := variable.Value.([]byte) log.Debugf("string: %s\n", string(bytes)) nameValue.Value = string(bytes) nameValues[nameValue.Name] = nameValue.Value case g.Integer: value := variable.Value.(int) log.Debugf("integer: %d\n", value) nameValue.Value = strconv.Itoa(value) nameValues[nameValue.Name] = nameValue.Value case g.IPAddress: value := variable.Value.(string) log.Debugf("IPAddress: %s\n", variable.Value) nameValue.Value = value nameValues[nameValue.Name] = nameValue.Value default: // ... or often you're just interested in numeric values. // ToBigInt() will return the Value as a BigInt, for plugging // into your calculations. log.Debugf("number: %d\n", g.ToBigInt(variable.Value)) } } } getResponse := services.DataResponse{nameValues} services.ResponseWithJson(w, http.StatusOK, getResponse) } func RestfulPut(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) queryNo := vars["no"] var targetTodo stTodo for _, Todo := range TodoList { if Todo.No == queryNo { targetTodo = Todo } } response := ApiResponse{"200", targetTodo} services.ResponseWithJson(w, http.StatusOK, response) } func RestfulHead(w http.ResponseWriter, r *http.Request) { var targetTodo stTodo response := ApiResponse{"200", targetTodo} services.ResponseWithJson(w, http.StatusOK, response) } func RemoveElement(TodoList []stTodo, No string) stTodo { // var targetTodo stTodo j := 0 if len(TodoList) == 0 { return TodoList[j] } for i := 0; i < len(TodoList); i++ { if TodoList[i].No != No { if i != j { TodoList[i], TodoList[j] = TodoList[j], TodoList[i] } j++ } } log.Debug(TodoList[j].No, TodoList[j].Item) return TodoList[j] } func RestfulDelete(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) queryNo := vars["no"] //获取No log.Debug("RestfulDelete processing... ") targetTodo := RemoveElement(TodoList, queryNo) response := ApiResponse{"200", targetTodo} services.ResponseWithJson(w, http.StatusOK, response) } func RestfulOptions(w http.ResponseWriter, r *http.Request) { var targetTodo stTodo response := ApiResponse{"200", targetTodo} services.ResponseWithJson(w, http.StatusOK, response) } func RestfulTrace(w http.ResponseWriter, r *http.Request) { var targetTodo stTodo response := ApiResponse{"200", targetTodo} services.ResponseWithJson(w, http.StatusOK, response) } func RestfulPatch(w http.ResponseWriter, r *http.Request) { var targetTodo stTodo response := ApiResponse{"200", targetTodo} services.ResponseWithJson(w, http.StatusOK, response) }