feat(controller): remove enterprise switch + feat: filter devices
This commit is contained in:
parent
32acb8e9ad
commit
badeaf9820
|
|
@ -17,37 +17,30 @@ import (
|
|||
)
|
||||
|
||||
type Api struct {
|
||||
port string
|
||||
js jetstream.JetStream
|
||||
nc *nats.Conn
|
||||
bridge bridge.Bridge
|
||||
db db.Database
|
||||
kv jetstream.KeyValue
|
||||
ctx context.Context
|
||||
enterpise config.Enterprise
|
||||
port string
|
||||
js jetstream.JetStream
|
||||
nc *nats.Conn
|
||||
bridge bridge.Bridge
|
||||
db db.Database
|
||||
kv jetstream.KeyValue
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
const REQUEST_TIMEOUT = time.Second * 30
|
||||
|
||||
func NewApi(c *config.Config, js jetstream.JetStream, nc *nats.Conn, bridge bridge.Bridge, d db.Database, kv jetstream.KeyValue) Api {
|
||||
return Api{
|
||||
port: c.RestApi.Port,
|
||||
js: js,
|
||||
nc: nc,
|
||||
ctx: c.RestApi.Ctx,
|
||||
bridge: bridge,
|
||||
db: d,
|
||||
kv: kv,
|
||||
enterpise: c.Enterprise,
|
||||
port: c.RestApi.Port,
|
||||
js: js,
|
||||
nc: nc,
|
||||
ctx: c.RestApi.Ctx,
|
||||
bridge: bridge,
|
||||
db: d,
|
||||
kv: kv,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Api) StartApi() {
|
||||
|
||||
if a.enterpise.SupportPassword != "" && a.enterpise.SupportEmail != "" {
|
||||
go registerEnterpriseSupport(a.enterpise.SupportEmail, a.enterpise.SupportPassword, a.db)
|
||||
}
|
||||
|
||||
r := mux.NewRouter()
|
||||
authentication := r.PathPrefix("/api/auth").Subrouter()
|
||||
authentication.HandleFunc("/login", a.generateToken).Methods("PUT")
|
||||
|
|
@ -57,13 +50,6 @@ func (a *Api) StartApi() {
|
|||
authentication.HandleFunc("/password", a.changePassword).Methods("PUT")
|
||||
authentication.HandleFunc("/admin/register", a.registerAdminUser).Methods("POST")
|
||||
authentication.HandleFunc("/admin/exists", a.adminUserExists).Methods("GET")
|
||||
if a.enterpise.Enable {
|
||||
mapRoutes := r.PathPrefix("/api/map").Subrouter()
|
||||
mapRoutes.HandleFunc("", a.devicesLocation).Methods("GET")
|
||||
mapRoutes.Use(func(handler http.Handler) http.Handler {
|
||||
return middleware.Middleware(handler)
|
||||
})
|
||||
}
|
||||
iot := r.PathPrefix("/api/device").Subrouter()
|
||||
iot.HandleFunc("/alias", a.setDeviceAlias).Methods("PUT")
|
||||
iot.HandleFunc("/auth", a.deviceAuth).Methods("GET", "POST", "DELETE")
|
||||
|
|
@ -74,7 +60,7 @@ func (a *Api) StartApi() {
|
|||
iot.HandleFunc("/cwmp/{sn}/addObject", a.cwmpAddObjectMsg).Methods("PUT")
|
||||
iot.HandleFunc("/cwmp/{sn}/deleteObject", a.cwmpDeleteObjectMsg).Methods("PUT")
|
||||
iot.HandleFunc("", a.retrieveDevices).Methods("GET")
|
||||
iot.HandleFunc("/{id}", a.retrieveDevices).Methods("GET")
|
||||
iot.HandleFunc("/filterOptions", a.filterOptions).Methods("GET")
|
||||
iot.HandleFunc("/{sn}/{mtp}/get", a.deviceGetMsg).Methods("PUT")
|
||||
iot.HandleFunc("/{sn}/{mtp}/add", a.deviceCreateMsg).Methods("PUT")
|
||||
iot.HandleFunc("/{sn}/{mtp}/del", a.deviceDeleteMsg).Methods("PUT")
|
||||
|
|
@ -84,13 +70,6 @@ func (a *Api) StartApi() {
|
|||
iot.HandleFunc("/{sn}/{mtp}/instances", a.deviceGetParameterInstances).Methods("PUT")
|
||||
iot.HandleFunc("/{sn}/{mtp}/operate", a.deviceOperateMsg).Methods("PUT")
|
||||
iot.HandleFunc("/{sn}/{mtp}/fw_update", a.deviceFwUpdate).Methods("PUT") //TODO: put it to work and generalize for usp and cwmp
|
||||
if a.enterpise.Enable {
|
||||
iot.HandleFunc("/{sn}/sitesurvey", a.deviceSiteSurvey).Methods("GET")
|
||||
iot.HandleFunc("/{sn}/connecteddevices", a.deviceConnectedDevices).Methods("GET")
|
||||
iot.HandleFunc("/{sn}/traceroute", a.deviceTraceRoute).Methods("GET", "PUT")
|
||||
iot.HandleFunc("/{sn}/speedtest", a.deviceSpeedTest).Methods("PUT")
|
||||
iot.HandleFunc("/{sn}/ping", a.devicePing).Methods("PUT", "GET")
|
||||
}
|
||||
iot.HandleFunc("/{sn}/wifi", a.deviceWifi).Methods("PUT", "GET")
|
||||
dash := r.PathPrefix("/api/info").Subrouter()
|
||||
dash.HandleFunc("/vendors", a.vendorsInfo).Methods("GET")
|
||||
|
|
@ -131,32 +110,3 @@ func (a *Api) StartApi() {
|
|||
}()
|
||||
log.Println("Running REST API at port", a.port)
|
||||
}
|
||||
|
||||
func registerEnterpriseSupport(email, password string, d db.Database) {
|
||||
|
||||
user := db.User{
|
||||
Email: email,
|
||||
Password: password,
|
||||
Name: "Enterprise Support",
|
||||
Level: db.AdminUser,
|
||||
}
|
||||
|
||||
for {
|
||||
if err := user.HashPassword(password); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err := d.RegisterUser(user)
|
||||
if err != nil {
|
||||
if err == db.ErrorUserExists {
|
||||
log.Println("Enterprise support user already registered.")
|
||||
return
|
||||
}
|
||||
log.Println("Error to register enterprise support user:", err)
|
||||
time.Sleep(time.Second * 5)
|
||||
continue
|
||||
}
|
||||
log.Println("Enterprise support user registered successfully.")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ import (
|
|||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/leandrofars/oktopus/internal/bridge"
|
||||
"github.com/leandrofars/oktopus/internal/db"
|
||||
"github.com/leandrofars/oktopus/internal/entity"
|
||||
local "github.com/leandrofars/oktopus/internal/nats"
|
||||
"github.com/leandrofars/oktopus/internal/utils"
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
|
|
@ -16,6 +18,33 @@ import (
|
|||
)
|
||||
|
||||
func (a *Api) retrieveDevices(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodDelete {
|
||||
id := r.URL.Query().Get("id")
|
||||
if id == "" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
err := json.NewEncoder(w).Encode("No id provided")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ids := strings.Split(id, ",")
|
||||
|
||||
msg, err := bridge.NatsReq[int64](local.NATS_ADAPTER_SUBJECT+"devices.delete", utils.Marshall(ids), w, a.nc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"number_of_deleted_devices": msg.Msg,
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const PAGE_SIZE_LIMIT = 50
|
||||
const PAGE_SIZE_DEFAULT = 20
|
||||
|
||||
|
|
@ -33,9 +62,36 @@ func (a *Api) retrieveDevices(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
statusOrderFromUser := r.URL.Query().Get("statusOrder")
|
||||
var statusOrder int
|
||||
if statusOrderFromUser != "" {
|
||||
if statusOrderFromUser == "asc" {
|
||||
statusOrder = 1
|
||||
} else if statusOrderFromUser == "desc" {
|
||||
statusOrder = -1
|
||||
} else {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
json.NewEncoder(w).Encode("Status order must be 'asc' or 'desc'")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
statusOrder = 1
|
||||
}
|
||||
|
||||
sort := bson.M{}
|
||||
sort["status"] = statusOrder
|
||||
|
||||
version := r.URL.Query().Get("version")
|
||||
vendor := r.URL.Query().Get("vendor")
|
||||
productClass := r.URL.Query().Get("type")
|
||||
alias := r.URL.Query().Get("alias")
|
||||
model := r.URL.Query().Get("model")
|
||||
status := r.URL.Query().Get("status")
|
||||
|
||||
// Get devices with pagination
|
||||
page_n := r.URL.Query().Get("page_number")
|
||||
page_s := r.URL.Query().Get("page_size")
|
||||
|
||||
var err error
|
||||
|
||||
var page_number int64
|
||||
|
|
@ -70,52 +126,69 @@ func (a *Api) retrieveDevices(w http.ResponseWriter, r *http.Request) {
|
|||
page_size = PAGE_SIZE_DEFAULT
|
||||
}
|
||||
|
||||
total, err := getDeviceCount(w, a.nc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
skip := page_number * (page_size - 1)
|
||||
if total < page_size {
|
||||
skip = 0
|
||||
|
||||
filter := map[string]interface{}{
|
||||
"status_order": statusOrder,
|
||||
"limit": page_size,
|
||||
"skip": skip,
|
||||
}
|
||||
|
||||
//TODO: fix status ordering
|
||||
statusOrder := r.URL.Query().Get("status")
|
||||
if statusOrder != "" {
|
||||
if statusOrder == "asc" {
|
||||
statusOrder = "1"
|
||||
} else if statusOrder == "desc" {
|
||||
statusOrder = "-1"
|
||||
} else {
|
||||
if version != "" {
|
||||
filter["version"] = version
|
||||
}
|
||||
if vendor != "" {
|
||||
filter["vendor"] = vendor
|
||||
}
|
||||
if productClass != "" {
|
||||
filter["productClass"] = productClass
|
||||
}
|
||||
if alias != "" {
|
||||
filter["alias"] = alias
|
||||
}
|
||||
if model != "" {
|
||||
filter["model"] = model
|
||||
}
|
||||
if status != "" {
|
||||
fmtStatus, err := strconv.Atoi(status)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
json.NewEncoder(w).Encode("Status order must be 'asc' or 'desc'")
|
||||
json.NewEncoder(w).Encode("Status must be an integer")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
sort := bson.M{}
|
||||
sort["status"] = 1
|
||||
|
||||
//TODO: Create filters
|
||||
|
||||
filter := bson.A{
|
||||
//bson.M{"$match": filter},
|
||||
bson.M{"$sort": sort}, // shows online devices first
|
||||
bson.M{"$skip": skip},
|
||||
bson.M{"$limit": page_size},
|
||||
filter["status"] = fmtStatus
|
||||
}
|
||||
|
||||
devices, err := getDevices(w, filter, a.nc)
|
||||
if err != nil {
|
||||
log.Println("Error getting devices", err)
|
||||
return
|
||||
}
|
||||
|
||||
if devices.Total == 0 {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
err := json.NewEncoder(w).Encode("No devices found")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if skip >= devices.Total {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
err := json.NewEncoder(w).Encode("Page number is out of range")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
err = json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"pages": total / page_size,
|
||||
"pages": devices.Total / page_size,
|
||||
"page": page_number,
|
||||
"size": page_size,
|
||||
"devices": devices,
|
||||
"devices": devices.Devices,
|
||||
"total": devices.Total,
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
|
|
@ -283,3 +356,14 @@ func (a *Api) setDeviceAlias(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Api) filterOptions(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
resp, err := bridge.NatsReq[entity.FilterOptions](local.NATS_ADAPTER_SUBJECT+"devices.filterOptions", nil, w, a.nc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(resp.Code)
|
||||
w.Write(utils.Marshall(resp.Msg))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,205 +0,0 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/leandrofars/oktopus/internal/bridge"
|
||||
"github.com/leandrofars/oktopus/internal/entity"
|
||||
"github.com/leandrofars/oktopus/internal/utils"
|
||||
)
|
||||
|
||||
func (a *Api) getEnterpriseResource(
|
||||
resource string,
|
||||
action string,
|
||||
device *entity.Device,
|
||||
sn string,
|
||||
w http.ResponseWriter,
|
||||
body []byte,
|
||||
protocol, datamodel string,
|
||||
) error {
|
||||
model, err := cwmpGetDeviceModel(device, w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = bridge.NatsEnterpriseInteraction("enterprise.v1."+protocol+"."+datamodel+"."+model+"."+sn+"."+resource+"."+action, body, w, a.nc)
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *Api) getMapsResource(
|
||||
action string,
|
||||
w http.ResponseWriter,
|
||||
body []byte,
|
||||
) error {
|
||||
|
||||
err := bridge.NatsEnterpriseInteraction("geolocation.v1."+action, body, w, a.nc)
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *Api) devicesLocation(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodGet {
|
||||
a.getMapsResource("get", w, []byte{})
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Api) deviceSiteSurvey(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
sn := vars["sn"]
|
||||
|
||||
device, err := getDeviceInfo(w, sn, a.nc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.Method == http.MethodGet {
|
||||
|
||||
if device.Cwmp == entity.Online {
|
||||
a.getEnterpriseResource("sitesurvey", "get", device, sn, w, []byte{}, "cwmp", "098")
|
||||
return
|
||||
}
|
||||
|
||||
if device.Mqtt == entity.Online || device.Stomp == entity.Online || device.Websockets == entity.Online {
|
||||
w.WriteHeader(http.StatusNotImplemented)
|
||||
w.Write(utils.Marshall("This feature is only working with CWMP devices"))
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write(utils.Marshall("Device is Offline"))
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Api) deviceConnectedDevices(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
sn := vars["sn"]
|
||||
|
||||
device, err := getDeviceInfo(w, sn, a.nc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.Method == http.MethodGet {
|
||||
|
||||
if device.Cwmp == entity.Online {
|
||||
a.getEnterpriseResource("connecteddevices", "get", device, sn, w, []byte{}, "cwmp", "098")
|
||||
return
|
||||
}
|
||||
|
||||
if device.Mqtt == entity.Online || device.Stomp == entity.Online || device.Websockets == entity.Online {
|
||||
w.WriteHeader(http.StatusNotImplemented)
|
||||
w.Write(utils.Marshall("This feature is only working with CWMP devices"))
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write(utils.Marshall("Device is Offline"))
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Api) deviceTraceRoute(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
sn := vars["sn"]
|
||||
|
||||
device, err := getDeviceInfo(w, sn, a.nc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.Method == http.MethodGet {
|
||||
if device.Cwmp == entity.Online {
|
||||
w.WriteHeader(http.StatusNotImplemented)
|
||||
w.Write(utils.Marshall("Get traceroute configuration is not implemented yet"))
|
||||
}
|
||||
}
|
||||
|
||||
if r.Method == http.MethodPut {
|
||||
if device.Cwmp == entity.Online {
|
||||
a.getEnterpriseResource("traceroute", "set", device, sn, w, []byte{}, "cwmp", "098")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if device.Mqtt == entity.Online || device.Stomp == entity.Online || device.Websockets == entity.Online {
|
||||
w.WriteHeader(http.StatusNotImplemented)
|
||||
w.Write(utils.Marshall("This feature is only working with CWMP devices"))
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write(utils.Marshall("Device is Offline"))
|
||||
}
|
||||
|
||||
func (a *Api) deviceSpeedTest(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
sn := vars["sn"]
|
||||
|
||||
device, err := getDeviceInfo(w, sn, a.nc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
payload, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write(utils.Marshall("Error reading request body"))
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
if device.Cwmp == entity.Online {
|
||||
a.getEnterpriseResource("speedTest", "set", device, sn, w, payload, "cwmp", "098")
|
||||
return
|
||||
}
|
||||
|
||||
if device.Mqtt == entity.Online || device.Stomp == entity.Online || device.Websockets == entity.Online {
|
||||
w.WriteHeader(http.StatusNotImplemented)
|
||||
w.Write(utils.Marshall("This feature is only working with CWMP devices"))
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write(utils.Marshall("Device is Offline"))
|
||||
}
|
||||
|
||||
func (a *Api) devicePing(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
sn := vars["sn"]
|
||||
|
||||
device, err := getDeviceInfo(w, sn, a.nc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if device.Cwmp != entity.Online {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write(utils.Marshall("Device is Offline"))
|
||||
}
|
||||
|
||||
if r.Method == http.MethodGet {
|
||||
if device.Cwmp == entity.Online {
|
||||
a.getEnterpriseResource("ping", "get", device, sn, w, []byte{}, "cwmp", "098")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
payload, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write(utils.Marshall("Error reading request body"))
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
if device.Cwmp == entity.Online {
|
||||
a.getEnterpriseResource("ping", "set", device, sn, w, payload, "cwmp", "098")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if device.Mqtt == entity.Online || device.Stomp == entity.Online || device.Websockets == entity.Online {
|
||||
w.WriteHeader(http.StatusNotImplemented)
|
||||
w.Write(utils.Marshall("This feature is only working with CWMP devices"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -176,7 +176,7 @@ func (a *Api) registerAdminUser(w http.ResponseWriter, r *http.Request) {
|
|||
utils.MarshallEncoder(err, w)
|
||||
}
|
||||
|
||||
if !adminUserExists(users, a.enterpise.SupportEmail) {
|
||||
if !adminUserExists(users) {
|
||||
var user db.User
|
||||
err = json.NewDecoder(r.Body).Decode(&user)
|
||||
if err != nil {
|
||||
|
|
@ -235,14 +235,14 @@ func (a *Api) registerAdminUser(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
func adminUserExists(users []map[string]interface{}, supportEmail string) bool {
|
||||
func adminUserExists(users []map[string]interface{}) bool {
|
||||
|
||||
if len(users) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, x := range users {
|
||||
if db.UserLevels(x["level"].(int32)) == db.AdminUser && x["email"].(string) != supportEmail {
|
||||
if db.UserLevels(x["level"].(int32)) == db.AdminUser {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -257,7 +257,7 @@ func (a *Api) adminUserExists(w http.ResponseWriter, r *http.Request) {
|
|||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
adminExits := adminUserExists(users, a.enterpise.SupportEmail)
|
||||
adminExits := adminUserExists(users)
|
||||
json.NewEncoder(w).Encode(adminExits)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import (
|
|||
local "github.com/leandrofars/oktopus/internal/nats"
|
||||
"github.com/leandrofars/oktopus/internal/utils"
|
||||
"github.com/nats-io/nats.go"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
var errInvalidMtp = errors.New("Invalid MTP, valid options are: mqtt, ws, stomp")
|
||||
|
|
@ -105,8 +104,8 @@ func getDeviceCount(w http.ResponseWriter, nc *nats.Conn) (int64, error) {
|
|||
return msg.Msg, err
|
||||
}
|
||||
|
||||
func getDevices(w http.ResponseWriter, filter primitive.A, nc *nats.Conn) (*[]entity.Device, error) {
|
||||
msg, err := bridge.NatsReq[[]entity.Device](
|
||||
func getDevices(w http.ResponseWriter, filter map[string]interface{}, nc *nats.Conn) (*entity.DevicesList, error) {
|
||||
msg, err := bridge.NatsReq[entity.DevicesList](
|
||||
local.NATS_ADAPTER_SUBJECT+"devices.retrieve",
|
||||
utils.Marshall(filter),
|
||||
w,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
|
@ -213,11 +212,6 @@ func (a *Api) deviceWifi(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
if device.Cwmp == entity.Online {
|
||||
|
||||
if a.enterpise.Enable {
|
||||
a.getEnterpriseResource("wifi", "get", device, sn, w, []byte{}, "cwmp", "098")
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
NUMBER_OF_WIFI_PARAMS_TO_GET = 5
|
||||
)
|
||||
|
|
@ -347,17 +341,6 @@ func (a *Api) deviceWifi(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
if device.Cwmp == entity.Online {
|
||||
|
||||
if a.enterpise.Enable {
|
||||
payload, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write(utils.Marshall(err.Error()))
|
||||
return
|
||||
}
|
||||
a.getEnterpriseResource("wifi", "set", device, sn, w, payload, "cwmp", "098")
|
||||
return
|
||||
}
|
||||
|
||||
var body []WiFi
|
||||
|
||||
err := utils.MarshallDecoder(&body, r.Body)
|
||||
|
|
|
|||
|
|
@ -153,7 +153,6 @@ func NatsReq[T entity.DataType](
|
|||
|
||||
err = json.Unmarshal(msg.Data, &answer)
|
||||
if err != nil {
|
||||
|
||||
var errMsg *entity.MsgAnswer[*string]
|
||||
err = json.Unmarshal(msg.Data, &errMsg)
|
||||
|
||||
|
|
|
|||
|
|
@ -30,17 +30,10 @@ type RestApi struct {
|
|||
Ctx context.Context
|
||||
}
|
||||
|
||||
type Enterprise struct {
|
||||
Enable bool
|
||||
SupportPassword string
|
||||
SupportEmail string
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
RestApi RestApi
|
||||
Nats Nats
|
||||
Mongo Mongo
|
||||
Enterprise Enterprise
|
||||
RestApi RestApi
|
||||
Nats Nats
|
||||
Mongo Mongo
|
||||
}
|
||||
|
||||
type Tls struct {
|
||||
|
|
@ -62,9 +55,6 @@ func NewConfig() *Config {
|
|||
serverCA := flag.String("server_ca", lookupEnvOrString("SERVER_CA", "rootCA.pem"), "server CA file to TLS connection")
|
||||
flApiPort := flag.String("api_port", lookupEnvOrString("REST_API_PORT", "8000"), "Rest api port")
|
||||
mongoUri := flag.String("mongo_uri", lookupEnvOrString("MONGO_URI", "mongodb://localhost:27017"), "uri for mongodb server")
|
||||
enterpise := flag.Bool("enterprise", lookupEnvOrBool("ENTERPRISE", false), "enterprise version enable")
|
||||
enterprise_support_password := flag.String("enterprise_support_password", lookupEnvOrString("ENTERPRISE_SUPPORT_PASSWORD", ""), "enterprise support password")
|
||||
enterpise_support_email := flag.String("enterprise_support_email", lookupEnvOrString("ENTERPRISE_SUPPORT_EMAIL", ""), "enterprise support email")
|
||||
flHelp := flag.Bool("help", false, "Help")
|
||||
|
||||
/*
|
||||
|
|
@ -103,11 +93,6 @@ func NewConfig() *Config {
|
|||
Uri: *mongoUri,
|
||||
Ctx: ctx,
|
||||
},
|
||||
Enterprise: Enterprise{
|
||||
Enable: *enterpise,
|
||||
SupportPassword: *enterprise_support_password,
|
||||
SupportEmail: *enterpise_support_email,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,3 +29,15 @@ type StatusCount struct {
|
|||
Status int `bson:"_id" json:"status"`
|
||||
Count int `bson:"count" json:"count"`
|
||||
}
|
||||
|
||||
type DevicesList struct {
|
||||
Devices []Device `json:"devices" bson:"documents"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
type FilterOptions struct {
|
||||
Models []string `json:"models"`
|
||||
ProductClasses []string `json:"productClasses"`
|
||||
Vendors []string `json:"vendors"`
|
||||
Versions []string `json:"versions"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package entity
|
|||
import "time"
|
||||
|
||||
type DataType interface {
|
||||
[]map[string]interface{} | *string | Device | int64 | []Device | []VendorsCount | []ProductClassCount | []StatusCount | time.Duration | []byte
|
||||
[]map[string]interface{} | *string | Device | int64 | []Device | []VendorsCount | []ProductClassCount | []StatusCount | time.Duration | []byte | []string | FilterOptions | DevicesList
|
||||
}
|
||||
|
||||
type MsgAnswer[T DataType] struct {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"log"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
|
@ -41,6 +42,18 @@ type Device struct {
|
|||
Cwmp Status
|
||||
}
|
||||
|
||||
type DevicesList struct {
|
||||
Devices []Device `json:"devices" bson:"documents"`
|
||||
Total int64 `json:"total" bson:"totalCount"`
|
||||
}
|
||||
|
||||
type FilterOptions struct {
|
||||
Models []string `json:"models"`
|
||||
ProductClasses []string `json:"productClasses"`
|
||||
Vendors []string `json:"vendors"`
|
||||
Versions []string `json:"versions"`
|
||||
}
|
||||
|
||||
func (d *Database) CreateDevice(device Device) error {
|
||||
var result bson.M
|
||||
var deviceExistent Device
|
||||
|
|
@ -100,32 +113,86 @@ func (d *Database) CreateDevice(device Device) error {
|
|||
}
|
||||
return err
|
||||
}
|
||||
func (d *Database) RetrieveDevices(filter bson.A) ([]Device, error) {
|
||||
func (d *Database) RetrieveDevices(filter bson.A) (*DevicesList, error) {
|
||||
|
||||
var results []Device
|
||||
var results []DevicesList
|
||||
|
||||
cursor, err := d.devices.Aggregate(d.ctx, filter)
|
||||
if err != nil {
|
||||
return results, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cursor.Err() != nil {
|
||||
return results, cursor.Err()
|
||||
return nil, cursor.Err()
|
||||
}
|
||||
defer cursor.Close(d.ctx)
|
||||
if err := cursor.All(d.ctx, &results); err != nil {
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for cursor.Next(d.ctx) {
|
||||
var device Device
|
||||
//log.Printf("results: %++v", results)
|
||||
|
||||
err := cursor.Decode(&device)
|
||||
if err != nil {
|
||||
log.Println("Error to decode device info fields")
|
||||
continue
|
||||
}
|
||||
return &results[0], err
|
||||
}
|
||||
|
||||
results = append(results, device)
|
||||
func (d *Database) RetrieveDeviceFilterOptions() (FilterOptions, error) {
|
||||
filter := bson.A{
|
||||
bson.D{
|
||||
{"$group",
|
||||
bson.D{
|
||||
{"_id", primitive.Null{}},
|
||||
{"vendors", bson.D{{"$addToSet", "$vendor"}}},
|
||||
{"versions", bson.D{{"$addToSet", "$version"}}},
|
||||
{"productClasses", bson.D{{"$addToSet", "$productclass"}}},
|
||||
{"models", bson.D{{"$addToSet", "$model"}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
bson.D{
|
||||
{"$project",
|
||||
bson.D{
|
||||
{"_id", 0},
|
||||
{"vendors", 1},
|
||||
{"versions", 1},
|
||||
{"productClasses", 1},
|
||||
{"models", 1},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return results, err
|
||||
var results []FilterOptions
|
||||
cursor, err := d.devices.Aggregate(d.ctx, filter)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return FilterOptions{}, err
|
||||
}
|
||||
defer cursor.Close(d.ctx)
|
||||
|
||||
if err := cursor.All(d.ctx, &results); err != nil {
|
||||
log.Println(err)
|
||||
return FilterOptions{}, err
|
||||
}
|
||||
|
||||
if len(results) > 0 {
|
||||
return results[0], nil
|
||||
} else {
|
||||
return FilterOptions{
|
||||
Models: []string{},
|
||||
ProductClasses: []string{},
|
||||
Vendors: []string{},
|
||||
Versions: []string{},
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Database) DeleteDevices(filter bson.D) (int64, error) {
|
||||
|
||||
result, err := d.devices.DeleteMany(d.ctx, filter)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return result.DeletedCount, err
|
||||
}
|
||||
|
||||
func (d *Database) RetrieveDevice(sn string) (Device, error) {
|
||||
|
|
|
|||
|
|
@ -52,18 +52,135 @@ func StartRequestsListener(ctx context.Context, nc *nats.Conn, db db.Database) {
|
|||
|
||||
nc.QueueSubscribe(local.ADAPTER_SUBJECT+"devices.retrieve", local.ADAPTER_QUEUE, func(msg *nats.Msg) {
|
||||
|
||||
var filter bson.A
|
||||
var criteria map[string]interface{}
|
||||
|
||||
err := json.Unmarshal(msg.Data, &filter)
|
||||
err := json.Unmarshal(msg.Data, &criteria)
|
||||
if err != nil {
|
||||
respondMsg(msg.Respond, 500, err.Error())
|
||||
}
|
||||
|
||||
//log.Println(criteria)
|
||||
propertiesFilter := bson.D{{}}
|
||||
|
||||
vendorFilter := criteria["vendor"]
|
||||
if vendorFilter != nil {
|
||||
log.Println("Vendor filter", vendorFilter)
|
||||
propertiesFilter = append(propertiesFilter, bson.E{Key: "vendor", Value: vendorFilter})
|
||||
}
|
||||
|
||||
versionFilter := criteria["version"]
|
||||
if versionFilter != nil {
|
||||
log.Println("Version filter", versionFilter)
|
||||
propertiesFilter = append(propertiesFilter, bson.E{Key: "version", Value: versionFilter})
|
||||
}
|
||||
|
||||
typeFilter := criteria["productClass"]
|
||||
if typeFilter != nil {
|
||||
log.Println("Type filter", typeFilter)
|
||||
propertiesFilter = append(propertiesFilter, bson.E{Key: "productclass", Value: typeFilter})
|
||||
}
|
||||
|
||||
aliasFilter := criteria["alias"]
|
||||
if aliasFilter != nil {
|
||||
log.Println("Type filter", aliasFilter)
|
||||
propertiesFilter = append(propertiesFilter, bson.E{Key: "alias", Value: aliasFilter})
|
||||
}
|
||||
|
||||
modelFilter := criteria["model"]
|
||||
if modelFilter != nil {
|
||||
log.Println("Model filter", modelFilter)
|
||||
propertiesFilter = append(propertiesFilter, bson.E{Key: "model", Value: modelFilter})
|
||||
}
|
||||
|
||||
statusFilter := criteria["status"]
|
||||
if statusFilter != nil {
|
||||
log.Println("Status filter", statusFilter)
|
||||
propertiesFilter = append(propertiesFilter, bson.E{Key: "status", Value: statusFilter})
|
||||
}
|
||||
|
||||
filter := bson.A{
|
||||
bson.D{
|
||||
{"$match",
|
||||
propertiesFilter,
|
||||
},
|
||||
},
|
||||
bson.D{
|
||||
{"$facet",
|
||||
bson.D{
|
||||
{"totalCount",
|
||||
bson.A{
|
||||
bson.D{{"$count", "count"}},
|
||||
},
|
||||
},
|
||||
{"documents",
|
||||
bson.A{
|
||||
bson.D{{"$sort", bson.D{{"status", criteria["status_order"]}}}},
|
||||
bson.D{{"$skip", criteria["skip"]}},
|
||||
bson.D{{"$limit", criteria["limit"]}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
bson.D{
|
||||
{"$project",
|
||||
bson.D{
|
||||
{"totalCount",
|
||||
bson.D{
|
||||
{"$arrayElemAt",
|
||||
bson.A{
|
||||
"$totalCount.count",
|
||||
0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{"documents", 1},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
devicesList, err := db.RetrieveDevices(filter)
|
||||
if err != nil {
|
||||
respondMsg(msg.Respond, 500, err.Error())
|
||||
}
|
||||
respondMsg(msg.Respond, 200, devicesList)
|
||||
respondMsg(msg.Respond, 200, &devicesList)
|
||||
})
|
||||
|
||||
nc.QueueSubscribe(local.ADAPTER_SUBJECT+"devices.delete", local.ADAPTER_QUEUE, func(msg *nats.Msg) {
|
||||
|
||||
var serialNumbersList []string
|
||||
|
||||
err := json.Unmarshal(msg.Data, &serialNumbersList)
|
||||
if err != nil {
|
||||
respondMsg(msg.Respond, 500, err.Error())
|
||||
}
|
||||
|
||||
var criteria bson.A
|
||||
|
||||
for _, sn := range serialNumbersList {
|
||||
criteria = append(criteria, bson.D{{"sn", sn}})
|
||||
}
|
||||
|
||||
// Create the filter with the $or operator
|
||||
filter := bson.D{
|
||||
{"$or", criteria},
|
||||
}
|
||||
|
||||
deletedCount, err := db.DeleteDevices(filter)
|
||||
if err != nil {
|
||||
respondMsg(msg.Respond, 500, err.Error())
|
||||
}
|
||||
respondMsg(msg.Respond, 200, deletedCount)
|
||||
})
|
||||
|
||||
nc.QueueSubscribe(local.ADAPTER_SUBJECT+"devices.filterOptions", local.ADAPTER_QUEUE, func(msg *nats.Msg) {
|
||||
result, err := db.RetrieveDeviceFilterOptions()
|
||||
if err != nil {
|
||||
respondMsg(msg.Respond, 500, err.Error())
|
||||
}
|
||||
respondMsg(msg.Respond, 200, result)
|
||||
})
|
||||
|
||||
nc.QueueSubscribe(local.ADAPTER_SUBJECT+"devices.class", local.ADAPTER_QUEUE, func(msg *nats.Msg) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user