This commit is contained in:
Darko Luketic
2018-03-28 01:29:06 +02:00
commit 02f372bc85
8 changed files with 1018 additions and 0 deletions

251
api/handler/data.go Normal file
View File

@ -0,0 +1,251 @@
package handler
import (
"strconv"
"git.icod.de/dalu/refdata/api/repo"
"git.icod.de/dalu/refdata/model"
"github.com/gin-gonic/gin"
)
func (h *Handler) DataRoutes(api *gin.RouterGroup) {
dataRoutes := api.Group("/data")
dataRoutes.GET("/", h.FindData)
dataRoutes.POST("/", h.CreateData)
dataRoutes.PUT("/:id", h.UpdateData)
dataRoutes.DELETE("/:id", h.RemoveData)
}
func (h *Handler) FindData(cx *gin.Context) {
switch cx.Query("response_type") {
case "list":
h.ListData(cx)
case "one":
h.GetData(cx)
default:
cx.AbortWithStatus(400)
}
}
func (h *Handler) ListData(cx *gin.Context) {
p := new(repo.DataListParams)
startQuery := cx.Query("start")
if startQuery != "" {
start, e := strconv.Atoi(startQuery)
if e != nil {
cx.AbortWithStatus(400)
return
}
p.Start = start
}
limitQuery := cx.Query("limit")
if limitQuery != "" {
limit, e := strconv.Atoi(limitQuery)
if e != nil {
cx.AbortWithStatus(400)
return
}
p.Limit = limit
}
p.Sort = cx.Query("sort")
name := cx.Query("name")
address := cx.Query("address")
location := cx.Query("location")
age := cx.Query("age")
price := cx.Query("price")
// string
if name == "1" {
p.Name = true
p.NameQuery = repo.DataNameQuery{}
p.NameQuery.Operation = cx.Query("name.operation")
p.NameQuery.Query = cx.Query("name.query")
p.NameQuery.Options = cx.Query("name.options")
}
// string
if address == "1" {
p.Address = true
p.AddressQuery = repo.DataAddressQuery{}
p.AddressQuery.Operation = cx.Query("address.operation")
p.AddressQuery.Query = cx.Query("address.query")
p.AddressQuery.Options = cx.Query("address.options")
}
// string
if location == "1" {
p.Location = true
p.LocationQuery = repo.DataLocationQuery{}
p.LocationQuery.Operation = cx.Query("location.operation")
p.LocationQuery.Query = cx.Query("location.query")
p.LocationQuery.Options = cx.Query("location.options")
}
if age == "1" {
p.Age = true
p.AgeQuery = repo.DataAgeQuery{}
p.AgeQuery.Operation = cx.Query("age.operation")
from, e := strconv.ParseInt(cx.Query("age.from"), 10, 64)
if e != nil {
cx.AbortWithStatus(400)
return
}
to, e := strconv.ParseInt(cx.Query("age.from"), 10, 64)
if e != nil {
cx.AbortWithStatus(400)
return
}
p.AgeQuery.From = from
p.AgeQuery.To = to
}
if price == "1" {
p.Price = true
p.PriceQuery = repo.DataPriceQuery{}
from, e := strconv.ParseFloat(cx.Query("age.from"), 64)
if e != nil {
cx.AbortWithStatus(400)
return
}
to, e := strconv.ParseFloat(cx.Query("age.from"), 64)
if e != nil {
cx.AbortWithStatus(400)
return
}
p.PriceQuery.From = from
p.PriceQuery.To = to
}
m, e := h.dataRepo.List(p)
if e != nil {
cx.AbortWithError(500, e)
return
}
cx.SecureJSON(200, m)
}
func (h *Handler) GetData(cx *gin.Context) {
p := new(repo.DataGetParams)
id := cx.Query("id")
name := cx.Query("name")
address := cx.Query("address")
location := cx.Query("location")
age := cx.Query("age")
price := cx.Query("price")
// id
if id == "1" {
p.Id = true
p.IdQuery = repo.DataIdQuery{}
p.IdQuery.Id = cx.Query("id.query")
}
// string
if name == "1" {
p.Name = true
p.NameQuery = repo.DataNameQuery{}
p.NameQuery.Operation = cx.Query("name.operation")
p.NameQuery.Query = cx.Query("name.query")
p.NameQuery.Options = cx.Query("name.options")
}
// string
if address == "1" {
p.Address = true
p.AddressQuery = repo.DataAddressQuery{}
p.AddressQuery.Operation = cx.Query("address.operation")
p.AddressQuery.Query = cx.Query("address.query")
p.AddressQuery.Options = cx.Query("address.options")
}
// string
if location == "1" {
p.Location = true
p.LocationQuery = repo.DataLocationQuery{}
p.LocationQuery.Operation = cx.Query("location.operation")
p.LocationQuery.Query = cx.Query("location.query")
p.LocationQuery.Options = cx.Query("location.options")
}
// int64
if age == "1" {
p.Age = true
p.AgeQuery = repo.DataAgeQuery{}
p.AgeQuery.Operation = cx.Query("age.operation")
from, e := strconv.ParseInt(cx.Query("age.from"), 10, 64)
if e != nil {
cx.AbortWithStatus(400)
return
}
to, e := strconv.ParseInt(cx.Query("age.from"), 10, 64)
if e != nil {
cx.AbortWithStatus(400)
return
}
p.AgeQuery.From = from
p.AgeQuery.To = to
}
// float64
if price == "1" {
p.Price = true
p.PriceQuery = repo.DataPriceQuery{}
from, e := strconv.ParseFloat(cx.Query("age.from"), 64)
if e != nil {
cx.AbortWithStatus(400)
return
}
to, e := strconv.ParseFloat(cx.Query("age.from"), 64)
if e != nil {
cx.AbortWithStatus(400)
return
}
p.PriceQuery.From = from
p.PriceQuery.To = to
}
m, e := h.dataRepo.Get(p)
if e != nil {
cx.AbortWithError(500, e)
return
}
cx.SecureJSON(200, m)
}
func (h *Handler) CreateData(cx *gin.Context) {
m := new(model.Data)
if e := cx.BindJSON(m); e != nil {
return
}
if e := h.dataRepo.Create(m); e != nil {
cx.AbortWithError(500, e)
return
}
cx.SecureJSON(201, map[string]interface{}{})
}
func (h *Handler) UpdateData(cx *gin.Context) {
m := new(model.Data)
if e := cx.BindJSON(m); e != nil {
return
}
if e := h.dataRepo.UpdateId(cx.Param("id"), m); e != nil {
cx.AbortWithError(500, e)
return
}
cx.SecureJSON(200, map[string]interface{}{})
}
func (h *Handler) RemoveData(cx *gin.Context) {
if e := h.dataRepo.RemoveId(cx.Param("id")); e != nil {
cx.AbortWithError(500, e)
return
}
cx.SecureJSON(200, map[string]interface{}{})
}

13
api/handler/handler.go Normal file
View File

@ -0,0 +1,13 @@
package handler
import "git.icod.de/dalu/refdata/api/repo"
type Handler struct {
dataRepo *repo.DataRepository
}
func NewHandler(dataRepo *repo.DataRepository) *Handler {
h := new(Handler)
h.dataRepo = dataRepo
return h
}

383
api/repo/data.go Normal file
View File

@ -0,0 +1,383 @@
package repo
import (
"errors"
"fmt"
"git.icod.de/dalu/refdata/model"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
)
//
type DataIdQuery struct {
Id string
}
// string
type DataNameQuery struct {
Operation string
Query string
Options string
}
// string
type DataAddressQuery struct {
Operation string
Query string
Options string
}
// string
type DataLocationQuery struct {
Operation string
Query string
Options string
}
// int
type DataAgeQuery struct {
Operation string
From int64
To int64
}
// float64
type DataPriceQuery struct {
Operation string
From float64
To float64
}
type DataListParams struct {
Start int
Limit int
Sort string
Name bool
Address bool
Location bool
Age bool
Price bool
NameQuery DataNameQuery
AddressQuery DataAddressQuery
LocationQuery DataLocationQuery
AgeQuery DataAgeQuery
PriceQuery DataPriceQuery
}
type DataGetParams struct {
Id bool
Name bool
Address bool
Location bool
Age bool
Price bool
IdQuery DataIdQuery
NameQuery DataNameQuery
AddressQuery DataAddressQuery
LocationQuery DataLocationQuery
AgeQuery DataAgeQuery
PriceQuery DataPriceQuery
}
type DataRepository struct {
ms *mgo.Session
database string
collection string
}
func NewDataRepository(ms *mgo.Session, db, c string) *DataRepository {
r := new(DataRepository)
r.ms = ms.Clone()
r.database = db
r.collection = c
return r
}
func (r *DataRepository) Close() {
r.ms.Close()
}
func (r *DataRepository) List(p *DataListParams) ([]*model.Data, error) {
ms := r.ms.Copy()
defer ms.Close()
c := ms.DB(r.database).C(r.collection)
q := bson.M{}
// string
if p.Name {
switch p.NameQuery.Operation {
case "eq":
q["name"] = p.NameQuery.Query
case "regex":
q["name"] = bson.RegEx{Pattern: p.NameQuery.Query, Options: p.NameQuery.Options}
}
}
// string
if p.Address {
switch p.AddressQuery.Operation {
case "eq":
q["address"] = p.AddressQuery.Query
case "regex":
q["address"] = bson.RegEx{Pattern: p.AddressQuery.Query, Options: p.AddressQuery.Options}
}
}
// int64
if p.Age {
switch p.AgeQuery.Operation {
case "eq":
q["age"] = p.AgeQuery.From
case "gt-lt":
q["age"] = bson.M{"$gt": p.AgeQuery.From, "$lt": p.AgeQuery.To}
case "gte-lte":
q["age"] = bson.M{"$gte": p.AgeQuery.From, "$lte": p.AgeQuery.To}
case "gte-lt":
q["age"] = bson.M{"$gte": p.AgeQuery.From, "$lt": p.AgeQuery.To}
case "gt-lte":
q["age"] = bson.M{"$gt": p.AgeQuery.From, "$lte": p.AgeQuery.To}
}
}
// string
if p.Location {
switch p.LocationQuery.Operation {
case "eq":
q["address"] = p.LocationQuery.Query
case "regex":
q["address"] = bson.RegEx{Pattern: p.LocationQuery.Query, Options: p.LocationQuery.Options}
}
}
if p.Price {
switch p.PriceQuery.Operation {
case "eq":
q["age"] = p.PriceQuery.From
case "gt-lt":
q["age"] = bson.M{"$gt": p.PriceQuery.From, "$lt": p.PriceQuery.To}
case "gte-lte":
q["age"] = bson.M{"$gte": p.PriceQuery.From, "$lte": p.PriceQuery.To}
case "gte-lt":
q["age"] = bson.M{"$gte": p.PriceQuery.From, "$lt": p.PriceQuery.To}
case "gt-lte":
q["age"] = bson.M{"$gt": p.PriceQuery.From, "$lte": p.PriceQuery.To}
}
}
var m []*model.Data
rq := c.Find(q)
if p.Sort != "" {
rq = rq.Sort(p.Sort)
}
if p.Start > 0 && p.Limit > 0 {
rq = rq.Skip(p.Start).Limit(p.Limit)
} else if p.Start > 0 && p.Limit < 1 {
rq = rq.Skip(p.Start)
} else if p.Start < 1 && p.Limit > 0 {
rq = rq.Limit(p.Limit)
}
if e := rq.All(&m); e != nil {
return nil, e
}
return m, nil
}
func (r *DataRepository) Get(p *DataGetParams) (*model.Data, error) {
ms := r.ms.Copy()
defer ms.Close()
c := ms.DB(r.database).C(r.collection)
q := bson.M{}
// id
if p.Id {
q["_id"] = bson.ObjectIdHex(p.IdQuery.Id)
}
// string
if p.Name {
switch p.NameQuery.Operation {
case "eq":
q["name"] = p.NameQuery.Query
case "regex":
q["name"] = bson.RegEx{Pattern: p.NameQuery.Query, Options: p.NameQuery.Options}
}
}
// string
if p.Address {
switch p.AddressQuery.Operation {
case "eq":
q["address"] = p.AddressQuery.Query
case "regex":
q["address"] = bson.RegEx{Pattern: p.AddressQuery.Query, Options: p.AddressQuery.Options}
}
}
// int64
if p.Age {
switch p.AgeQuery.Operation {
case "eq":
q["age"] = p.AgeQuery.From
case "gt-lt":
q["age"] = bson.M{"$gt": p.AgeQuery.From, "$lt": p.AgeQuery.To}
case "gte-lte":
q["age"] = bson.M{"$gte": p.AgeQuery.From, "$lte": p.AgeQuery.To}
case "gte-lt":
q["age"] = bson.M{"$gte": p.AgeQuery.From, "$lt": p.AgeQuery.To}
case "gt-lte":
q["age"] = bson.M{"$gt": p.AgeQuery.From, "$lte": p.AgeQuery.To}
}
}
// string
if p.Location {
switch p.LocationQuery.Operation {
case "eq":
q["address"] = p.LocationQuery.Query
case "regex":
q["address"] = bson.RegEx{Pattern: p.LocationQuery.Query, Options: p.LocationQuery.Options}
}
}
if p.Price {
switch p.PriceQuery.Operation {
case "eq":
q["age"] = p.PriceQuery.From
case "gt-lt":
q["age"] = bson.M{"$gt": p.PriceQuery.From, "$lt": p.PriceQuery.To}
case "gte-lte":
q["age"] = bson.M{"$gte": p.PriceQuery.From, "$lte": p.PriceQuery.To}
case "gte-lt":
q["age"] = bson.M{"$gte": p.PriceQuery.From, "$lt": p.PriceQuery.To}
case "gt-lte":
q["age"] = bson.M{"$gt": p.PriceQuery.From, "$lte": p.PriceQuery.To}
}
}
m := new(model.Data)
rq := c.Find(q)
if e := rq.All(m); e != nil {
return nil, e
}
return m, nil
}
func (r *DataRepository) GetCount(p *DataGetParams) (int, error) {
ms := r.ms.Copy()
defer ms.Close()
c := ms.DB(r.database).C(r.collection)
q := bson.M{}
// id
if p.Id {
q["_id"] = bson.ObjectIdHex(p.IdQuery.Id)
}
// string
if p.Name {
switch p.NameQuery.Operation {
case "eq":
q["name"] = p.NameQuery.Query
case "regex":
q["name"] = bson.RegEx{Pattern: p.NameQuery.Query, Options: p.NameQuery.Options}
}
}
// string
if p.Address {
switch p.AddressQuery.Operation {
case "eq":
q["address"] = p.AddressQuery.Query
case "regex":
q["address"] = bson.RegEx{Pattern: p.AddressQuery.Query, Options: p.AddressQuery.Options}
}
}
// int64
if p.Age {
switch p.AgeQuery.Operation {
case "eq":
q["age"] = p.AgeQuery.From
case "gt-lt":
q["age"] = bson.M{"$gt": p.AgeQuery.From, "$lt": p.AgeQuery.To}
case "gte-lte":
q["age"] = bson.M{"$gte": p.AgeQuery.From, "$lte": p.AgeQuery.To}
case "gte-lt":
q["age"] = bson.M{"$gte": p.AgeQuery.From, "$lt": p.AgeQuery.To}
case "gt-lte":
q["age"] = bson.M{"$gt": p.AgeQuery.From, "$lte": p.AgeQuery.To}
}
}
// string
if p.Location {
switch p.LocationQuery.Operation {
case "eq":
q["address"] = p.LocationQuery.Query
case "regex":
q["address"] = bson.RegEx{Pattern: p.LocationQuery.Query, Options: p.LocationQuery.Options}
}
}
if p.Price {
switch p.PriceQuery.Operation {
case "eq":
q["age"] = p.PriceQuery.From
case "gt-lt":
q["age"] = bson.M{"$gt": p.PriceQuery.From, "$lt": p.PriceQuery.To}
case "gte-lte":
q["age"] = bson.M{"$gte": p.PriceQuery.From, "$lte": p.PriceQuery.To}
case "gte-lt":
q["age"] = bson.M{"$gte": p.PriceQuery.From, "$lt": p.PriceQuery.To}
case "gt-lte":
q["age"] = bson.M{"$gt": p.PriceQuery.From, "$lte": p.PriceQuery.To}
}
}
rq := c.Find(q)
return rq.Count()
}
func (r *DataRepository) Create(m *model.Data) error {
ms := r.ms.Copy()
defer ms.Close()
c := ms.DB(r.database).C(r.collection)
return c.Insert(m)
}
func (r *DataRepository) UpdateId(id string, m *model.Data) error {
if !bson.IsObjectIdHex(id) {
return errors.New(fmt.Sprintf("%s is not an ObjectId", id))
}
ms := r.ms.Copy()
defer ms.Close()
c := ms.DB(r.database).C(r.collection)
return c.UpdateId(bson.ObjectIdHex(id), m)
}
func (r *DataRepository) RemoveId(id string) error {
if !bson.IsObjectIdHex(id) {
return errors.New(fmt.Sprintf("%s is not an ObjectId", id))
}
ms := r.ms.Copy()
defer ms.Close()
c := ms.DB(r.database).C(r.collection)
return c.RemoveId(bson.ObjectIdHex(id))
}