b/68251055 Fixes #25 Add sanity check on timestamps (#28)

diff --git a/api_helper.go b/api_helper.go
index 67e9725..45fbcec 100644
--- a/api_helper.go
+++ b/api_helper.go
@@ -20,6 +20,7 @@
 	"io"
 	"net/http"
 	"strings"
+	"time"
 )
 
 /*
@@ -178,6 +179,23 @@
 				ErrorCode: "BAD_DATA",
 				Reason: "client_received_start_timestamp " +
 					"> client_received_end_timestamp"}
+		} else {
+			ts, _ := crst.Int64()
+			crstTime := time.Unix(ts/1000, 0) // Convert crst(ms) to seconds
+			diff := time.Now().UTC().Sub(crstTime)
+			if diff <= 0 {
+				return false, errResponse{
+					ErrorCode: "BAD_DATA",
+					Reason: "client_received_start_timestamp " +
+						"cannot be after current time"}
+			} else if diff.Hours() > 90*24 { // 90 Days
+				return false, errResponse{
+					ErrorCode: "BAD_DATA",
+					Reason: "client_received_start_timestamp " +
+						"cannot be older than 90 days"}
+			} else {
+				return true, errResponse{}
+			}
 		}
 	}
 	return true, errResponse{}
diff --git a/api_helper_test.go b/api_helper_test.go
index 4101c5c..a6200a2 100644
--- a/api_helper_test.go
+++ b/api_helper_test.go
@@ -18,8 +18,10 @@
 	"bytes"
 	"encoding/json"
 
+	"fmt"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"time"
 )
 
 // BeforeSuite setup and AfterSuite cleanup is in apidAnalytics_suite_test.go
@@ -71,11 +73,12 @@
 			Expect(e.ErrorCode).To(Equal("MISSING_FIELD"))
 
 			By("payload with clst > clet")
+			now := time.Now().Unix() * 1000
 			record = []byte(`{
 						"response_status_code": 200,
 						"client_id":"testapikey",
-						"client_received_start_timestamp": 1486406248277,
-						"client_received_end_timestamp": 1486406248260
+						"client_received_start_timestamp":` + fmt.Sprintf("%v", now) + `,
+						"client_received_end_timestamp":` + fmt.Sprintf("%v", now-60000) + `
 					}`)
 			raw = getRaw(record)
 			valid, e = validate(raw)
@@ -90,7 +93,7 @@
 						"response_status_code": 200,
 						"client_id":"testapikey",
 						"client_received_start_timestamp": 0,
-						"client_received_end_timestamp": 1486406248260
+						"client_received_end_timestamp":` + fmt.Sprintf("%v", now) + `
 					}`)
 			raw = getRaw(record)
 			valid, e = validate(raw)
@@ -105,7 +108,7 @@
 						"response_status_code": 200,
 						"client_id":"testapikey",
 						"client_received_start_timestamp": null,
-						"client_received_end_timestamp": 1486406248260
+						"client_received_end_timestamp":` + fmt.Sprintf("%v", now) + `
 					}`)
 			raw = getRaw(record)
 			valid, e = validate(raw)
@@ -118,7 +121,7 @@
 						"response_status_code": 200,
 						"client_id":"testapikey",
 						"client_received_start_timestamp": "",
-						"client_received_end_timestamp": 1486406248260
+						"client_received_end_timestamp":` + fmt.Sprintf("%v", now) + `
 					}`)
 			raw = getRaw(record)
 			valid, e = validate(raw)
@@ -127,15 +130,48 @@
 			Expect(e.ErrorCode).To(Equal("BAD_DATA"))
 			Expect(e.Reason).To(Equal("client_received_start_timestamp and " +
 				"client_received_end_timestamp has to be number"))
+
+			By("payload with clst after current time")
+			record = []byte(`{
+						"response_status_code": 200,
+						"client_id":"testapikey",
+						"client_received_start_timestamp":` + fmt.Sprintf("%v", now+120000) + `,
+						"client_received_end_timestamp":` + fmt.Sprintf("%v", now+160000) + `
+					}`)
+			raw = getRaw(record)
+			valid, e = validate(raw)
+
+			Expect(valid).To(BeFalse())
+			Expect(e.ErrorCode).To(Equal("BAD_DATA"))
+			Expect(e.Reason).To(Equal("client_received_start_timestamp " +
+				"cannot be after current time"))
+
+			By("payload with clst older than 90 days")
+			starttime := time.Now().UTC().AddDate(0, 0, -95)
+			clst := starttime.Unix() * 1000
+			record = []byte(`{
+						"response_status_code": 200,
+						"client_id":"testapikey",
+						"client_received_start_timestamp":` + fmt.Sprintf("%v", clst) + `,
+						"client_received_end_timestamp":` + fmt.Sprintf("%v", clst+160000) + `
+					}`)
+			raw = getRaw(record)
+			valid, e = validate(raw)
+
+			Expect(valid).To(BeFalse())
+			Expect(e.ErrorCode).To(Equal("BAD_DATA"))
+			Expect(e.Reason).To(Equal("client_received_start_timestamp " +
+				"cannot be older than 90 days"))
 		})
 	})
 	Context("valid record", func() {
 		It("should return true", func() {
+			now := time.Now().Unix() * 1000
 			var record = []byte(`{
 					"response_status_code": 200,
 					"client_id":"testapikey",
-					"client_received_start_timestamp": 1486406248277,
-					"client_received_end_timestamp": 1486406248290
+					"client_received_start_timestamp":` + fmt.Sprintf("%v", now) + `,
+					"client_received_end_timestamp":` + fmt.Sprintf("%v", now+160000) + `
 				}`)
 			raw := getRaw(record)
 			valid, _ := validate(raw)
diff --git a/api_test.go b/api_test.go
index 96664c8..a9a78c1 100644
--- a/api_test.go
+++ b/api_test.go
@@ -24,6 +24,7 @@
 
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"time"
 )
 
 // BeforeSuite setup and AfterSuite cleanup is in apidAnalytics_suite_test.go
@@ -107,12 +108,13 @@
 			Expect(e.Reason).To(Equal("Gzip Encoded data cannot be read"))
 
 			By("1 bad record")
+			now := time.Now().Unix() * 1000
 			payload = []byte(`{
 						"records":[{
 							"response_status_code": 200,
 							"client_id":"testapikey",
-							"client_received_start_timestamp": 1486406248277,
-							"client_received_end_timestamp": 1486406248290
+							"client_received_start_timestamp":` + fmt.Sprintf("%v", now) + `,
+							"client_received_end_timestamp":` + fmt.Sprintf("%v", now+60000) + `
 						},{
 							"response_status_code": 200,
 							"client_id":"testapikey"
@@ -127,14 +129,16 @@
 
 	Context("valid payload", func() {
 		It("should return successfully", func() {
+			now := time.Now().Unix() * 1000
+
 			var payload = []byte(`{
-					"records":[{
-						"response_status_code": 200,
-						"client_id":"testapikey",
-						"client_received_start_timestamp": 1486406248277,
-						"client_received_end_timestamp": 1486406248290
-					}]
-				}`)
+						"records":[{
+							"response_status_code": 200,
+							"client_id":"testapikey",
+							"client_received_start_timestamp":` + fmt.Sprintf("%v", now) + `,
+							"client_received_end_timestamp":` + fmt.Sprintf("%v", now+60000) + `
+							}]
+						}`)
 			req := getRequestWithScope("testid", payload)
 			res, _ := makeRequest(req)
 			Expect(res.StatusCode).To(Equal(http.StatusOK))
@@ -265,14 +269,15 @@
 			Expect(e.Reason).To(Equal("Gzip Encoded data cannot be read"))
 
 			By("1 bad record")
+			now := time.Now().Unix() * 1000
 			payload = []byte(`{
 						"organization":"testorg",
 						"environment":"testenv",
 						"records":[{
 							"response_status_code": 200,
 							"client_id":"testapikey",
-							"client_received_start_timestamp": 1486406248277,
-							"client_received_end_timestamp": 1486406248290
+							"client_received_start_timestamp":` + fmt.Sprintf("%v", now) + `,
+							"client_received_end_timestamp":` + fmt.Sprintf("%v", now+60000) + `
 						},{
 							"response_status_code": 200,
 							"client_id":"testapikey"
@@ -286,15 +291,17 @@
 	})
 
 	Context("valid payload", func() {
+
 		It("should return successfully", func() {
+			now := time.Now().Unix() * 1000
 			var payload = []byte(`{
 					"organization":"testorg",
 					"environment":"testenv",
 					"records":[{
 						"response_status_code": 200,
 						"client_id":"testapikey",
-						"client_received_start_timestamp": 1486406248277,
-						"client_received_end_timestamp": 1486406248290
+						"client_received_start_timestamp":` + fmt.Sprintf("%v", now) + `,
+						"client_received_end_timestamp":` + fmt.Sprintf("%v", now+60000) + `
 					}]
 				}`)
 			req := getRequest(payload)