package api import ( "encoding/json" "log" "net/http" "strconv" "github.com/leandrofars/oktopus/internal/utils" "github.com/nats-io/nats.go/jetstream" "go.mongodb.org/mongo-driver/bson" ) func (a *Api) retrieveDevices(w http.ResponseWriter, r *http.Request) { const PAGE_SIZE_LIMIT = 50 const PAGE_SIZE_DEFAULT = 20 // Get specific device id := r.URL.Query().Get("id") if id != "" { device, err := getDeviceInfo(w, id, a.nc) if err != nil { return } err = json.NewEncoder(w).Encode(device) if err != nil { log.Println(err) } return } // 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 if page_n == "" { page_number = 0 } else { page_number, err = strconv.ParseInt(page_n, 10, 64) if err != nil { w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode("Page number must be an integer") return } } var page_size int64 if page_s != "" { page_size, err = strconv.ParseInt(page_s, 10, 64) if err != nil { w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode("Page size must be an integer") return } if page_size > PAGE_SIZE_LIMIT { w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode("Page size must not exceed " + strconv.Itoa(PAGE_SIZE_LIMIT)) return } } else { 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 } //TODO: Create filters //TODO: Create sorting sort := bson.M{} sort["status"] = 1 filter := bson.A{ //bson.M{"$match": filter}, bson.M{"$sort": sort}, // shows online devices first bson.M{"$skip": skip}, bson.M{"$limit": page_size}, } devices, err := getDevices(w, filter, a.nc) if err != nil { return } err = json.NewEncoder(w).Encode(map[string]interface{}{ "pages": total / page_size, "page": page_number, "size": page_size, "devices": devices, }) if err != nil { log.Println(err) } } type DeviceAuth struct { User string `json:"id"` Password string `json:"password"` } func (a *Api) deviceAuth(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodGet { id := r.URL.Query().Get("id") if id != "" { entry, err := a.kv.Get(r.Context(), id) if err != nil { if err == jetstream.ErrKeyNotFound { w.WriteHeader(http.StatusNotFound) return } w.WriteHeader(http.StatusInternalServerError) utils.MarshallEncoder(err, w) return } utils.MarshallEncoder(map[string]string{ id: string(entry.Value()), }, w) return } entries, err := a.kv.ListKeys(r.Context(), jetstream.IgnoreDeletes()) if err != nil { w.WriteHeader(http.StatusInternalServerError) utils.MarshallEncoder(err, w) return } listOfKeys := make(map[string]string) keys := entries.Keys() for key := range keys { entry, err := a.kv.Get(r.Context(), key) if err != nil { w.WriteHeader(http.StatusInternalServerError) utils.MarshallEncoder(err, w) return } /*listOfKeys = append(listOfKeys, map[string]string{ key: string(entry.Value()), })*/ listOfKeys[key] = string(entry.Value()) } utils.MarshallEncoder(listOfKeys, w) } else if r.Method == http.MethodDelete { id := r.URL.Query().Get("id") if id != "" { err := a.kv.Purge(r.Context(), id) if err != nil { if err == jetstream.ErrKeyNotFound { w.WriteHeader(http.StatusNotFound) return } w.WriteHeader(http.StatusInternalServerError) utils.MarshallEncoder(err, w) return } return } w.WriteHeader(http.StatusBadRequest) utils.MarshallEncoder("No id provided", w) } else if r.Method == http.MethodPut { var deviceAuth DeviceAuth err := utils.MarshallDecoder(&deviceAuth, r.Body) if err != nil { w.WriteHeader(http.StatusBadRequest) utils.MarshallEncoder(err, w) return } if deviceAuth.User != "" { _, err := a.kv.PutString(r.Context(), deviceAuth.User, deviceAuth.Password) if err != nil { w.WriteHeader(http.StatusInternalServerError) utils.MarshallEncoder(err, w) return } return } w.WriteHeader(http.StatusBadRequest) utils.MarshallEncoder("device must have a user", w) } else { log.Println("Unknown method used in device auth api") w.WriteHeader(http.StatusMethodNotAllowed) return } }