123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- package api
- import (
- "errors"
- "fmt"
- "net/http"
- "strconv"
- "github.com/go-chi/chi"
- "github.com/go-chi/render"
- "wkla.no-ip.biz/gogs/Willie/MsgService/MessageService/dao"
- "wkla.no-ip.biz/gogs/Willie/MsgService/MessageService/internal"
- "wkla.no-ip.biz/gogs/Willie/MsgService/MessageService/model"
- "wkla.no-ip.biz/gogs/Willie/MsgService/MessageService/worker"
- )
- //DeleteRefHeader header key for the delete reference options
- const DeleteRefHeader = "X-mcs-deleteref"
- /*
- ModelRoutes getting all routes for the config endpoint
- */
- func ModelRoutes() *chi.Mux {
- router := chi.NewRouter()
- router.With(RoleCheck([]string{"edit"})).Post("/{bename}/{model}/", PostModelEndpoint)
- //TODO insert bulk import api
- router.With(RoleCheck([]string{"edit", "read"})).Get("/{bename}/{model}/count", GetModelCountEndpoint)
- router.With(RoleCheck([]string{"edit", "read"})).With(Paginate).Get("/{bename}/{model}/", GetManyModelsEndpoint)
- router.With(RoleCheck([]string{"edit", "read"})).Get("/{bename}/{model}/{modelid}", GetModelEndpoint)
- router.With(RoleCheck([]string{"edit"})).Put("/{bename}/{model}/{modelid}", PutModelEndpoint)
- router.With(RoleCheck([]string{"edit"})).Delete("/{bename}/{model}/{modelid}", DeleteModelEndpoint)
- return router
- }
- //PostModelEndpoint , this method will always return 201
- func PostModelEndpoint(response http.ResponseWriter, request *http.Request) {
- backend := chi.URLParam(request, "bename")
- mymodel := chi.URLParam(request, "model")
- route := model.Route{
- Backend: backend,
- Model: mymodel,
- }
- route = enrichRouteInformation(request, route)
- data := &model.JSONMap{}
- if err := render.Decode(request, data); err != nil {
- render.Render(response, request, ErrInvalidRequest(err))
- return
- }
- bemodel := *data
- log.Infof("POST: path: %s, route: %s \n", request.URL.Path, route.String())
- validModel, err := worker.Validate(route, bemodel)
- if err != nil {
- if pe, ok := err.(worker.ErrValidationError); ok {
- render.Render(response, request, ErrInvalidRequest(pe))
- return
- }
- if err == dao.ErrNotImplemented {
- render.Render(response, request, ErrNotImplemted)
- return
- }
- if err == worker.ErrBackendNotFound || err == worker.ErrBackendModelNotFound {
- render.Render(response, request, ErrNotFound)
- return
- }
- render.Render(response, request, ErrInternalServer(err))
- return
- }
- if validModel == nil {
- render.Render(response, request, ErrInvalidRequest(errors.New("data model not valid")))
- return
- }
- validModel, err = worker.Store(route, validModel)
- if err != nil {
- if err == dao.ErrNotImplemented {
- render.Render(response, request, ErrNotImplemted)
- return
- }
- if err == dao.ErrUniqueIndexError {
- render.Render(response, request, ErrUniqueIndexError)
- return
- }
- render.Render(response, request, ErrInternalServer(err))
- return
- }
- route.Identity = validModel[internal.AttributeID].(string)
- buildLocationHeader(response, request, route)
- render.Status(request, http.StatusCreated)
- render.JSON(response, request, validModel)
- }
- //GetManyModelsEndpoint searching for a list of model instances
- func GetManyModelsEndpoint(response http.ResponseWriter, request *http.Request) {
- offset := request.Context().Value(contextKeyOffset)
- limit := request.Context().Value(contextKeyLimit)
- log.Infof("GET many: offset: %d, limit: %d", offset, limit)
- backend := chi.URLParam(request, "bename")
- mymodel := chi.URLParam(request, "model")
- route := model.Route{
- Backend: backend,
- Model: mymodel,
- }
- route = enrichRouteInformation(request, route)
- log.Infof("GET many: path: %s, route: %s", request.URL.Path, route.String())
- query := request.URL.Query().Get("query")
- log.Infof("query: %s, offset: %d, limit: %d", query, offset, limit)
- //owner, _, _ := request.BasicAuth()
- n, models, err := worker.Query(route, query, offset.(int), limit.(int))
- if err != nil {
- if err == dao.ErrNotImplemented {
- render.Render(response, request, ErrNotImplemted)
- return
- }
- render.Render(response, request, ErrInternalServer(err))
- return
- }
- m := make(map[string]interface{})
- m["data"] = models
- m["found"] = n
- m["count"] = len(models)
- m["query"] = query
- m["offset"] = offset
- m["limit"] = limit
- render.JSON(response, request, m)
- }
- //GetModelCountEndpoint getting a model with an identifier
- func GetModelCountEndpoint(response http.ResponseWriter, request *http.Request) {
- backend := chi.URLParam(request, "bename")
- mymodel := chi.URLParam(request, "model")
- route := model.Route{
- Backend: backend,
- Model: mymodel,
- }
- route = enrichRouteInformation(request, route)
- log.Infof("GET count: path: %s, route: %s", request.URL.Path, route.String())
- modelCount, err := worker.GetCount(route)
- if err != nil {
- if err == dao.ErrNotImplemented {
- render.Render(response, request, ErrNotImplemted)
- return
- }
- if err == dao.ErrNoDocument {
- render.Render(response, request, ErrNotFound)
- return
- }
- render.Render(response, request, ErrInternalServer(err))
- return
- }
- m := make(map[string]interface{})
- m["found"] = modelCount
- render.JSON(response, request, m)
- }
- //GetModelEndpoint getting a model with an identifier
- func GetModelEndpoint(response http.ResponseWriter, request *http.Request) {
- backend := chi.URLParam(request, "bename")
- mymodel := chi.URLParam(request, "model")
- modelid := chi.URLParam(request, "modelid")
- route := model.Route{
- Backend: backend,
- Model: mymodel,
- Identity: modelid,
- }
- route = enrichRouteInformation(request, route)
- log.Infof("GET: path: %s, route: %s", request.URL.Path, route.String())
- model, err := worker.Get(route)
- if err != nil {
- if err == dao.ErrNotImplemented {
- render.Render(response, request, ErrNotImplemted)
- return
- }
- if err == dao.ErrNoDocument {
- render.Render(response, request, ErrNotFound)
- return
- }
- render.Render(response, request, ErrInternalServer(err))
- return
- }
- render.JSON(response, request, model)
- }
- //PutModelEndpoint change a model
- func PutModelEndpoint(response http.ResponseWriter, request *http.Request) {
- backend := chi.URLParam(request, "bename")
- mymodel := chi.URLParam(request, "model")
- modelid := chi.URLParam(request, "modelid")
- route := model.Route{
- Backend: backend,
- Model: mymodel,
- Identity: modelid,
- }
- route = enrichRouteInformation(request, route)
- log.Infof("PUT: path: %s, route: %s", request.URL.Path, route.String())
- data := &model.JSONMap{}
- if err := render.Decode(request, data); err != nil {
- render.Render(response, request, ErrInvalidRequest(err))
- return
- }
- bemodel := *data
- validModel, err := worker.Validate(route, bemodel)
- if err != nil {
- if err == dao.ErrNotImplemented {
- render.Render(response, request, ErrNotImplemted)
- return
- }
- render.Render(response, request, ErrInternalServer(err))
- return
- }
- if validModel == nil {
- render.Render(response, request, ErrInvalidRequest(errors.New("data model not valid")))
- return
- }
- validModel, err = worker.Update(route, validModel)
- if err != nil {
- if err == dao.ErrNoDocument {
- render.Render(response, request, ErrNotFound)
- return
- }
- if err == dao.ErrNotImplemented {
- render.Render(response, request, ErrNotImplemted)
- return
- }
- render.Render(response, request, ErrInternalServer(err))
- return
- }
- route.Identity = validModel[internal.AttributeID].(string)
- buildLocationHeader(response, request, route)
- render.Status(request, http.StatusCreated)
- render.JSON(response, request, validModel)
- }
- //DeleteModelEndpoint deleting a model
- func DeleteModelEndpoint(response http.ResponseWriter, request *http.Request) {
- backend := chi.URLParam(request, "bename")
- mymodel := chi.URLParam(request, "model")
- modelid := chi.URLParam(request, "modelid")
- route := model.Route{
- Backend: backend,
- Model: mymodel,
- Identity: modelid,
- }
- route = enrichRouteInformation(request, route)
- deleteRef := isDeleteRef(request)
- log.Infof("DELETE: path: %s, route: %s, delRef: %t", request.URL.Path, route.String(), deleteRef)
- err := worker.Delete(route, deleteRef)
- if err != nil {
- if err == dao.ErrNoDocument {
- render.Render(response, request, ErrNotFound)
- return
- }
- if err == dao.ErrNotImplemented {
- render.Render(response, request, ErrNotImplemted)
- return
- }
- render.Render(response, request, ErrInternalServer(err))
- return
- }
- MsgResponse(response, http.StatusOK, "model deleted.")
- }
- func isDeleteRef(request *http.Request) bool {
- deleteRef := true
- if request.Header.Get(DeleteRefHeader) != "" {
- b, err := strconv.ParseBool(request.Header.Get(DeleteRefHeader))
- if err == nil {
- deleteRef = b
- }
- }
- return deleteRef
- }
- func enrichRouteInformation(request *http.Request, route model.Route) model.Route {
- if request.Header.Get(APIKeyHeader) != "" {
- route.Apikey = request.Header.Get(APIKeyHeader)
- }
- if request.Header.Get(SystemHeader) != "" {
- route.SystemID = request.Header.Get(SystemHeader)
- }
- username, _, _ := request.BasicAuth()
- if username != "" {
- route.Username = username
- }
- return route
- }
- func buildLocationHeader(response http.ResponseWriter, request *http.Request, route model.Route) {
- loc := fmt.Sprintf("%s/%s", request.URL.Path, route.Identity)
- response.Header().Add("Location", loc)
- }
|