yats.git

commit 5c0d8115c6843f4797ed13d1a61e7454ed1e5088

Author: Paolo Lulli <paolo@lulli.net>

Add endpoint search for Positions

 client/.gitignore | 2 
 client/.idea/vcs.xml | 1 
 schema/schema.cql | 9 +++
 server/db/position.go | 12 ++++
 server/docs/docs.go | 112 ++++++++++++++++++++++++++++++++++++++
 server/docs/swagger.json | 112 ++++++++++++++++++++++++++++++++++++++
 server/docs/swagger.yaml | 74 +++++++++++++++++++++++++
 server/model/models.go | 7 ++
 server/rest/rest-position.go | 81 +++++++++++++++++++++++++++


diff --git a/client/.gitignore b/client/.gitignore
index 5add2221c9996f92e9334fbeb298cecce7f69742..f60ffd693d430f084275685ca9c7d5c11c058e83 100644
--- a/client/.gitignore
+++ b/client/.gitignore
@@ -1,3 +1,3 @@
 yats
 .dqt
-.idea
+.idea/




diff --git a/client/.idea/vcs.xml b/client/.idea/vcs.xml
index 35eb1ddfbbc029bcab630581847471d7f238ec53..62bd7a01e9c46011ff345da2389b38fd0fa6d41a 100644
--- a/client/.idea/vcs.xml
+++ b/client/.idea/vcs.xml
@@ -2,5 +2,6 @@ 
 <project version="4">
   <component name="VcsDirectoryMappings">
     <mapping directory="" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
   </component>
 </project>
\ No newline at end of file




diff --git a/schema/schema.cql b/schema/schema.cql
index fad6b290beeea10d17dea832703fb5d4e851d1bf..4f958d807e5a243e397a8972e0feedb69e1768e9 100644
--- a/schema/schema.cql
+++ b/schema/schema.cql
@@ -32,6 +32,15 @@     lon double, 
     name text,
     PRIMARY KEY (id_client,ptime)
 );
+CREATE TABLE sources (
+    id_client text,
+    name text,
+    type text,
+    app text,
+    description text,
+    PRIMARY KEY (id_client,app,type,name)
+);
+CREATE INDEX ON sources(id_client);
 
 CREATE TABLE location (
     hash text,




diff --git a/server/db/position.go b/server/db/position.go
index 128b7e40faf6316a3144d6f8c5a35c10cd49610f..c2047a8749f06f5118f68c7f20a7f573123f7460 100644
--- a/server/db/position.go
+++ b/server/db/position.go
@@ -27,3 +27,15 @@ 	q := fmt.Sprintf("insert into position ( id_client, ptime, lat, lon, name) values ('%s','%s',%f,%f,'%s');", idClient, string(timeAsBytes), lat, lon, positionName)
 	fmt.Printf("q=%s", q)
 	Session.Query(q).Exec()
 }
+func CanReadSourcePosition(idClient string, sourceApp string) bool {
+	m := map[string]interface{}{}
+
+	q := fmt.Sprintf(" SELECT name,app,type from sources where id_client='%s' and app='%s' and type='position';", idClient, sourceApp)
+	fmt.Println(q)
+	iter := Session.Query(q).Iter()
+
+	for iter.MapScan(m) {
+		return true
+	}
+	return false
+}




diff --git a/server/docs/docs.go b/server/docs/docs.go
index 92cd9d1b1212b0b1011b8366718c7646e5766d9d..ac74a0e0a98edf161091a590a93f7d6afae01027 100644
--- a/server/docs/docs.go
+++ b/server/docs/docs.go
@@ -319,6 +319,95 @@                         }
                     }
                 }
             }
+        },
+        "/position/search": {
+            "post": {
+                "description": "retrieve positions in the specified time window",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Positions"
+                ],
+                "summary": "Get the positions From ... and To when present",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "clientCN",
+                        "name": "X-SSL-Client-CN",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Position query filters",
+                        "name": "position",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/model.PositionSearchRequest"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/position/{from}": {
+            "get": {
+                "description": "retrieve positions  from timestamp {from}",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Positions"
+                ],
+                "summary": "Get the positions from timestamp {from}",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "clientCN",
+                        "name": "X-SSL-Client-CN",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Event query filters",
+                        "name": "position",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/model.PositionSearchRequest"
+                        }
+                    },
+                    {
+                        "type": "string",
+                        "description": "Starting from timestamp :from",
+                        "name": "from",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
         }
     },
     "definitions": {
@@ -345,6 +434,9 @@                 },
                 "id_client": {
                     "type": "string"
                 },
+                "source": {
+                    "type": "string"
+                },
                 "to": {
                     "type": "integer"
                 }
@@ -379,6 +471,9 @@                 },
                 "name": {
                     "type": "string"
                 },
+                "source": {
+                    "type": "string"
+                },
                 "to": {
                     "type": "integer"
                 }
@@ -402,6 +497,23 @@                 "name": {
                     "type": "string"
                 },
                 "ptime": {
+                    "type": "integer"
+                }
+            }
+        },
+        "model.PositionSearchRequest": {
+            "type": "object",
+            "properties": {
+                "from": {
+                    "type": "integer"
+                },
+                "id_client": {
+                    "type": "string"
+                },
+                "source": {
+                    "type": "string"
+                },
+                "to": {
                     "type": "integer"
                 }
             }




diff --git a/server/docs/swagger.json b/server/docs/swagger.json
index 7879f76ac280dd8e848914e957e24f8e92b67642..7fa7784282a08cc301e1e9f2eaca8a0f110defb0 100755
--- a/server/docs/swagger.json
+++ b/server/docs/swagger.json
@@ -312,6 +312,95 @@                         }
                     }
                 }
             }
+        },
+        "/position/search": {
+            "post": {
+                "description": "retrieve positions in the specified time window",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Positions"
+                ],
+                "summary": "Get the positions From ... and To when present",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "clientCN",
+                        "name": "X-SSL-Client-CN",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Position query filters",
+                        "name": "position",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/model.PositionSearchRequest"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/position/{from}": {
+            "get": {
+                "description": "retrieve positions  from timestamp {from}",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Positions"
+                ],
+                "summary": "Get the positions from timestamp {from}",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "clientCN",
+                        "name": "X-SSL-Client-CN",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Event query filters",
+                        "name": "position",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/model.PositionSearchRequest"
+                        }
+                    },
+                    {
+                        "type": "string",
+                        "description": "Starting from timestamp :from",
+                        "name": "from",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
         }
     },
     "definitions": {
@@ -338,6 +427,9 @@                 },
                 "id_client": {
                     "type": "string"
                 },
+                "source": {
+                    "type": "string"
+                },
                 "to": {
                     "type": "integer"
                 }
@@ -372,6 +464,9 @@                 },
                 "name": {
                     "type": "string"
                 },
+                "source": {
+                    "type": "string"
+                },
                 "to": {
                     "type": "integer"
                 }
@@ -395,6 +490,23 @@                 "name": {
                     "type": "string"
                 },
                 "ptime": {
+                    "type": "integer"
+                }
+            }
+        },
+        "model.PositionSearchRequest": {
+            "type": "object",
+            "properties": {
+                "from": {
+                    "type": "integer"
+                },
+                "id_client": {
+                    "type": "string"
+                },
+                "source": {
+                    "type": "string"
+                },
+                "to": {
                     "type": "integer"
                 }
             }




diff --git a/server/docs/swagger.yaml b/server/docs/swagger.yaml
index 880f7eb10c381fa3b2da76bafe98c4d2f30cc568..5b73ff2eb0b1523b49ed64a2e29a08c1bea95e68 100755
--- a/server/docs/swagger.yaml
+++ b/server/docs/swagger.yaml
@@ -15,6 +15,8 @@       from:
         type: integer
       id_client:
         type: string
+      source:
+        type: string
       to:
         type: integer
     type: object
@@ -36,6 +38,8 @@         type: integer
       id_client:
         type: string
       name:
+        type: string
+      source:
         type: string
       to:
         type: integer
@@ -53,6 +57,17 @@         type: number
       name:
         type: string
       ptime:
+        type: integer
+    type: object
+  model.PositionSearchRequest:
+    properties:
+      from:
+        type: integer
+      id_client:
+        type: string
+      source:
+        type: string
+      to:
         type: integer
     type: object
 externalDocs:
@@ -265,6 +280,65 @@           description: Accepted
           schema:
             type: string
       summary: write position to db
+      tags:
+      - Positions
+  /position/{from}:
+    get:
+      consumes:
+      - application/json
+      description: retrieve positions  from timestamp {from}
+      parameters:
+      - description: clientCN
+        in: header
+        name: X-SSL-Client-CN
+        required: true
+        type: string
+      - description: Event query filters
+        in: body
+        name: position
+        required: true
+        schema:
+          $ref: '#/definitions/model.PositionSearchRequest'
+      - description: Starting from timestamp :from
+        in: path
+        name: from
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            type: string
+      summary: Get the positions from timestamp {from}
+      tags:
+      - Positions
+  /position/search:
+    post:
+      consumes:
+      - application/json
+      description: retrieve positions in the specified time window
+      parameters:
+      - description: clientCN
+        in: header
+        name: X-SSL-Client-CN
+        required: true
+        type: string
+      - description: Position query filters
+        in: body
+        name: position
+        required: true
+        schema:
+          $ref: '#/definitions/model.PositionSearchRequest'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            type: string
+      summary: Get the positions From ... and To when present
       tags:
       - Positions
 swagger: "2.0"




diff --git a/server/model/models.go b/server/model/models.go
index c35470218a7dfa100a08f62065f9eabbe9fa5740..20fa899887561a9bd028472d00521a26fa87d1e2 100644
--- a/server/model/models.go
+++ b/server/model/models.go
@@ -57,3 +57,10 @@ 	To                int64  `json:"to" parquet:"name=mtime, type=INT64, convertedtype=TIMESTAMP_MILLIS"`
 	IdClient          string `json:"id_client" parquet:"name=id_client, type=BYTE_ARRAY, convertedtype=UTF8"`
 	SourceApplication string `json:"source" parquet:"name=source_application, type=BYTE_ARRAY, convertedtype=UTF8"`
 }
+
+type PositionSearchRequest struct {
+	From              int64  `json:"from" parquet:"name=mtime, type=INT64, convertedtype=TIMESTAMP_MILLIS"`
+	To                int64  `json:"to" parquet:"name=mtime, type=INT64, convertedtype=TIMESTAMP_MILLIS"`
+	IdClient          string `json:"id_client" parquet:"name=id_client, type=BYTE_ARRAY, convertedtype=UTF8"`
+	SourceApplication string `json:"source" parquet:"name=source_application, type=BYTE_ARRAY, convertedtype=UTF8"`
+}




diff --git a/server/rest/rest-position.go b/server/rest/rest-position.go
index 4177d4a544e12b67f269b6499ca9f4ce48b95938..762e083964b1a9f8a7af4a120c1da8d93f5ff017 100644
--- a/server/rest/rest-position.go
+++ b/server/rest/rest-position.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"github.com/gin-gonic/gin"
 	"net/http"
+	"strconv"
 	"time"
 	"yats-server/config"
 	"yats-server/db"
@@ -42,3 +43,83 @@ 		}
 		c.IndentedJSON(http.StatusAccepted, gin.H{"ret": "OK"})
 	}
 }
+
+// SearchPositions  godoc
+// @Param X-SSL-Client-CN header string true "clientCN"
+// @Summary Get the positions From ... and To when present
+// @Schemes
+// @Description retrieve positions in the specified time window
+// @Tags Positions
+// @Accept json
+// @Param position body model.PositionSearchRequest true "Position query filters"
+// @Produce json
+// @Success 200 {string} SearchPositions
+// @Router /position/search [post]
+func SearchPositions(cfg config.Configuration) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		var position model.PositionSearchRequest
+
+		if err := c.BindJSON(&position); err != nil {
+			c.IndentedJSON(http.StatusAccepted, gin.H{"ret": "-1"})
+			return
+		}
+
+		clientCN := GetClientCN(c, cfg)
+		fmt.Printf("Client ID: %s\n ", clientCN)
+
+		if position.SourceApplication != "" {
+			if !db.CanReadSourcePosition(clientCN, position.SourceApplication) {
+				c.IndentedJSON(http.StatusAccepted, gin.H{"ret": "-1"})
+			}
+			clientCN = position.SourceApplication
+		}
+
+		var eventsPack []model.EventModel
+		if position.To == 0 {
+			unixTimeUTC := time.Unix(position.From, 0)
+			timeAsBytes, _ := unixTimeUTC.UTC().MarshalText()
+			eventsPack = db.EventsFrom(db.Session, clientCN, string(timeAsBytes), 100)
+		} else if position.From != 0 {
+			fromUnixTimeUTC := time.Unix(position.From, 0)
+			toUnixTimeUTC := time.Unix(position.To, 0)
+			fromInBytes, _ := fromUnixTimeUTC.UTC().MarshalText()
+			toInBytes, _ := toUnixTimeUTC.UTC().MarshalText()
+			eventsPack = db.EventsBetween(db.Session, clientCN, string(fromInBytes), string(toInBytes), 100)
+		}
+		c.IndentedJSON(http.StatusAccepted, gin.H{"ret": "OK", "content": eventsPack})
+	}
+}
+
+// GetPositionsFrom godoc
+// @Param X-SSL-Client-CN header string true "clientCN"
+// @Summary Get the positions from timestamp {from}
+// @Schemes
+// @Description retrieve positions  from timestamp {from}
+// @Tags Positions
+// @Accept json
+// @Param position body model.PositionSearchRequest true "Event query filters"
+// @Produce json
+// @Success 200 {string} SearchPositions
+// @Router /position/{from} [get]
+// @Param from path string true "Starting from timestamp :from"
+func GetPositionsFrom(cfg config.Configuration) gin.HandlerFunc {
+	return func(c *gin.Context) {
+
+		fromParam := c.Param("from")
+		fromParamInt64, err := strconv.ParseInt(fromParam, 10, 64)
+		if err != nil {
+			c.IndentedJSON(http.StatusAccepted, gin.H{"ret": "-1"})
+		}
+
+		clientCN := GetClientCN(c, cfg)
+		fmt.Printf("Client ID: %s\n ", clientCN)
+
+		var eventsPack []model.EventModel
+
+		unixTimeUTC := time.Unix(fromParamInt64, 0)
+		timeAsBytes, _ := unixTimeUTC.UTC().MarshalText()
+		eventsPack = db.EventsFrom(db.Session, clientCN, string(timeAsBytes), 100)
+
+		c.IndentedJSON(http.StatusAccepted, gin.H{"ret": "OK", "content": eventsPack})
+	}
+}