Add record procedure exec capabilities
This will allow us to perform bulk operations on record & record-values
This commit is contained in:
@@ -35,6 +35,7 @@ type RecordAPI interface {
|
||||
ImportRun(context.Context, *request.RecordImportRun) (interface{}, error)
|
||||
ImportProgress(context.Context, *request.RecordImportProgress) (interface{}, error)
|
||||
Export(context.Context, *request.RecordExport) (interface{}, error)
|
||||
Exec(context.Context, *request.RecordExec) (interface{}, error)
|
||||
Create(context.Context, *request.RecordCreate) (interface{}, error)
|
||||
Read(context.Context, *request.RecordRead) (interface{}, error)
|
||||
Update(context.Context, *request.RecordUpdate) (interface{}, error)
|
||||
@@ -50,6 +51,7 @@ type Record struct {
|
||||
ImportRun func(http.ResponseWriter, *http.Request)
|
||||
ImportProgress func(http.ResponseWriter, *http.Request)
|
||||
Export func(http.ResponseWriter, *http.Request)
|
||||
Exec func(http.ResponseWriter, *http.Request)
|
||||
Create func(http.ResponseWriter, *http.Request)
|
||||
Read func(http.ResponseWriter, *http.Request)
|
||||
Update func(http.ResponseWriter, *http.Request)
|
||||
@@ -179,6 +181,26 @@ func NewRecord(h RecordAPI) *Record {
|
||||
resputil.JSON(w, value)
|
||||
}
|
||||
},
|
||||
Exec: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewRecordExec()
|
||||
if err := params.Fill(r); err != nil {
|
||||
logger.LogParamError("Record.Exec", r, err)
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.Exec(r.Context(), params)
|
||||
if err != nil {
|
||||
logger.LogControllerError("Record.Exec", r, err, params.Auditable())
|
||||
resputil.JSON(w, err)
|
||||
return
|
||||
}
|
||||
logger.LogControllerCall("Record.Exec", r, params.Auditable())
|
||||
if !serveHTTP(value, w, r) {
|
||||
resputil.JSON(w, value)
|
||||
}
|
||||
},
|
||||
Create: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewRecordCreate()
|
||||
@@ -291,6 +313,7 @@ func (h Record) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http
|
||||
r.Patch("/namespace/{namespaceID}/module/{moduleID}/record/import/{sessionID}", h.ImportRun)
|
||||
r.Get("/namespace/{namespaceID}/module/{moduleID}/record/import/{sessionID}", h.ImportProgress)
|
||||
r.Get("/namespace/{namespaceID}/module/{moduleID}/record/export{filename}.{ext}", h.Export)
|
||||
r.Post("/namespace/{namespaceID}/module/{moduleID}/record/exec/{procedure}", h.Exec)
|
||||
r.Post("/namespace/{namespaceID}/module/{moduleID}/record/", h.Create)
|
||||
r.Get("/namespace/{namespaceID}/module/{moduleID}/record/{recordID}", h.Read)
|
||||
r.Post("/namespace/{namespaceID}/module/{moduleID}/record/{recordID}", h.Update)
|
||||
|
||||
@@ -347,6 +347,28 @@ func (ctrl *Record) Export(ctx context.Context, r *request.RecordExport) (interf
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ctrl Record) Exec(ctx context.Context, r *request.RecordExec) (interface{}, error) {
|
||||
aa := request.ProcedureArgs(r.Args)
|
||||
|
||||
switch r.Procedure {
|
||||
case "organize":
|
||||
return resputil.OK(), ctrl.record.With(ctx).Organize(
|
||||
r.NamespaceID,
|
||||
r.ModuleID,
|
||||
aa.GetUint64("recordID"),
|
||||
aa.Get("sortingField"),
|
||||
aa.Get("sortingValue"),
|
||||
aa.Get("sortingFilter"),
|
||||
aa.Get("valueField"),
|
||||
aa.Get("value"),
|
||||
)
|
||||
default:
|
||||
return nil, errors.New("unknown procedure")
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (ctrl Record) makePayload(ctx context.Context, m *types.Module, r *types.Record, err error) (*recordPayload, error) {
|
||||
if err != nil || r == nil {
|
||||
return nil, err
|
||||
|
||||
@@ -435,6 +435,65 @@ func (r *RecordExport) Fill(req *http.Request) (err error) {
|
||||
|
||||
var _ RequestFiller = NewRecordExport()
|
||||
|
||||
// Record exec request parameters
|
||||
type RecordExec struct {
|
||||
Procedure string
|
||||
NamespaceID uint64 `json:",string"`
|
||||
ModuleID uint64 `json:",string"`
|
||||
Args []ProcedureArg
|
||||
}
|
||||
|
||||
func NewRecordExec() *RecordExec {
|
||||
return &RecordExec{}
|
||||
}
|
||||
|
||||
func (r RecordExec) Auditable() map[string]interface{} {
|
||||
var out = map[string]interface{}{}
|
||||
|
||||
out["procedure"] = r.Procedure
|
||||
out["namespaceID"] = r.NamespaceID
|
||||
out["moduleID"] = r.ModuleID
|
||||
out["args"] = r.Args
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *RecordExec) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(req.Body).Decode(r)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := req.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := req.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
r.Procedure = chi.URLParam(req, "procedure")
|
||||
r.NamespaceID = parseUInt64(chi.URLParam(req, "namespaceID"))
|
||||
r.ModuleID = parseUInt64(chi.URLParam(req, "moduleID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewRecordExec()
|
||||
|
||||
// Record create request parameters
|
||||
type RecordCreate struct {
|
||||
Values types.RecordValueSet
|
||||
|
||||
@@ -12,6 +12,15 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type (
|
||||
ProcedureArgs []ProcedureArg
|
||||
|
||||
ProcedureArg struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
)
|
||||
|
||||
var truthy = regexp.MustCompile(`^\s*(t(rue)?|y(es)?|1)\s*$`)
|
||||
|
||||
func parseJSONTextWithErr(s string) (types.JSONText, error) {
|
||||
@@ -97,3 +106,19 @@ func is(s string, matches ...string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (args ProcedureArgs) GetUint64(name string) uint64 {
|
||||
u, _ := strconv.ParseUint(args.Get(name), 10, 64)
|
||||
return u
|
||||
}
|
||||
|
||||
func (args ProcedureArgs) Get(name string) string {
|
||||
name = strings.ToLower(name)
|
||||
for _, arg := range args {
|
||||
if strings.ToLower(arg.Name) == name {
|
||||
return arg.Value
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user