Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
corteza
corteza-server
Commits
cb9682e4
Commit
cb9682e4
authored
5 years ago
by
Denis Arh
Browse files
Options
Download
Plain Diff
Merge branch 'feature-corredor-iterators' into develop
parents
314cf76f
2fac997b
Changes
47
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
463 additions
and
32 deletions
+463
-32
api/compose/spec.json
api/compose/spec.json
+16
-0
api/compose/spec/record.json
api/compose/spec/record.json
+16
-0
compose/rest/automation.go
compose/rest/automation.go
+1
-1
compose/rest/handlers/record.go
compose/rest/handlers/record.go
+37
-14
compose/rest/module.go
compose/rest/module.go
+1
-1
compose/rest/namespace.go
compose/rest/namespace.go
+1
-1
compose/rest/page.go
compose/rest/page.go
+1
-1
compose/rest/record.go
compose/rest/record.go
+22
-1
compose/rest/request/record.go
compose/rest/request/record.go
+59
-0
compose/service/event/events.yaml
compose/service/event/events.yaml
+1
-1
compose/service/event/module.go
compose/service/event/module.go
+6
-3
compose/service/event/namespace.go
compose/service/event/namespace.go
+3
-3
compose/service/event/page.go
compose/service/event/page.go
+6
-3
compose/service/event/record.gen.go
compose/service/event/record.gen.go
+60
-0
compose/service/event/record.go
compose/service/event/record.go
+7
-3
compose/service/module.go
compose/service/module.go
+26
-0
compose/service/namespace.go
compose/service/namespace.go
+26
-0
compose/service/record.go
compose/service/record.go
+119
-0
compose/service/service.go
compose/service/service.go
+37
-0
docs/compose/README.md
docs/compose/README.md
+18
-0
No files found.
api/compose/spec.json
View file @
cb9682e4
...
...
@@ -1073,6 +1073,22 @@
}
]
}
},
{
"name"
:
"triggerScriptOnList"
,
"method"
:
"POST"
,
"title"
:
"Fire compose:record trigger"
,
"path"
:
"/trigger"
,
"parameters"
:
{
"post"
:
[
{
"name"
:
"script"
,
"type"
:
"string"
,
"title"
:
"Script to execute"
,
"required"
:
true
}
]
}
}
]
},
...
...
This diff is collapsed.
Click to expand it.
api/compose/spec/record.json
View file @
cb9682e4
...
...
@@ -364,6 +364,22 @@
}
]
}
},
{
"Name"
:
"triggerScriptOnList"
,
"Method"
:
"POST"
,
"Title"
:
"Fire compose:record trigger"
,
"Path"
:
"/trigger"
,
"Parameters"
:
{
"post"
:
[
{
"name"
:
"script"
,
"required"
:
true
,
"title"
:
"Script to execute"
,
"type"
:
"string"
}
]
}
}
]
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
compose/rest/automation.go
View file @
cb9682e4
...
...
@@ -48,5 +48,5 @@ func (ctrl *Automation) Bundle(ctx context.Context, r *request.AutomationBundle)
}
func
(
ctrl
*
Automation
)
TriggerScript
(
ctx
context
.
Context
,
r
*
request
.
AutomationTriggerScript
)
(
interface
{},
error
)
{
return
resputil
.
OK
(),
corredor
.
Service
()
.
Exec
OnManual
(
ctx
,
r
.
Script
,
event
.
ComposeOnManual
())
return
resputil
.
OK
(),
corredor
.
Service
()
.
Exec
(
ctx
,
r
.
Script
,
event
.
ComposeOnManual
())
}
This diff is collapsed.
Click to expand it.
compose/rest/handlers/record.go
View file @
cb9682e4
...
...
@@ -43,24 +43,26 @@ type RecordAPI interface {
Delete
(
context
.
Context
,
*
request
.
RecordDelete
)
(
interface
{},
error
)
Upload
(
context
.
Context
,
*
request
.
RecordUpload
)
(
interface
{},
error
)
TriggerScript
(
context
.
Context
,
*
request
.
RecordTriggerScript
)
(
interface
{},
error
)
TriggerScriptOnList
(
context
.
Context
,
*
request
.
RecordTriggerScriptOnList
)
(
interface
{},
error
)
}
// HTTP API interface
type
Record
struct
{
Report
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
List
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
ImportInit
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
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
)
BulkDelete
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
Delete
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
Upload
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
TriggerScript
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
Report
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
List
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
ImportInit
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
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
)
BulkDelete
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
Delete
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
Upload
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
TriggerScript
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
TriggerScriptOnList
func
(
http
.
ResponseWriter
,
*
http
.
Request
)
}
func
NewRecord
(
h
RecordAPI
)
*
Record
{
...
...
@@ -345,6 +347,26 @@ func NewRecord(h RecordAPI) *Record {
resputil
.
JSON
(
w
,
value
)
}
},
TriggerScriptOnList
:
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
defer
r
.
Body
.
Close
()
params
:=
request
.
NewRecordTriggerScriptOnList
()
if
err
:=
params
.
Fill
(
r
);
err
!=
nil
{
logger
.
LogParamError
(
"Record.TriggerScriptOnList"
,
r
,
err
)
resputil
.
JSON
(
w
,
err
)
return
}
value
,
err
:=
h
.
TriggerScriptOnList
(
r
.
Context
(),
params
)
if
err
!=
nil
{
logger
.
LogControllerError
(
"Record.TriggerScriptOnList"
,
r
,
err
,
params
.
Auditable
())
resputil
.
JSON
(
w
,
err
)
return
}
logger
.
LogControllerCall
(
"Record.TriggerScriptOnList"
,
r
,
params
.
Auditable
())
if
!
serveHTTP
(
value
,
w
,
r
)
{
resputil
.
JSON
(
w
,
value
)
}
},
}
}
...
...
@@ -365,5 +387,6 @@ func (h Record) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http
r
.
Delete
(
"/namespace/{namespaceID}/module/{moduleID}/record/{recordID}"
,
h
.
Delete
)
r
.
Post
(
"/namespace/{namespaceID}/module/{moduleID}/record/attachment"
,
h
.
Upload
)
r
.
Post
(
"/namespace/{namespaceID}/module/{moduleID}/record/{recordID}/trigger"
,
h
.
TriggerScript
)
r
.
Post
(
"/namespace/{namespaceID}/module/{moduleID}/record/trigger"
,
h
.
TriggerScriptOnList
)
})
}
This diff is collapsed.
Click to expand it.
compose/rest/module.go
View file @
cb9682e4
...
...
@@ -151,7 +151,7 @@ func (ctrl *Module) TriggerScript(ctx context.Context, r *request.ModuleTriggerS
}
// @todo implement same behaviour as we have on record - module+oldModule
err
=
corredor
.
Service
()
.
Exec
OnManual
(
ctx
,
r
.
Script
,
event
.
ModuleOnManual
(
module
,
module
,
namespace
))
err
=
corredor
.
Service
()
.
Exec
(
ctx
,
r
.
Script
,
event
.
ModuleOnManual
(
module
,
module
,
namespace
))
return
ctrl
.
makePayload
(
ctx
,
module
,
err
)
}
...
...
This diff is collapsed.
Click to expand it.
compose/rest/namespace.go
View file @
cb9682e4
...
...
@@ -131,7 +131,7 @@ func (ctrl *Namespace) TriggerScript(ctx context.Context, r *request.NamespaceTr
return
}
err
=
corredor
.
Service
()
.
Exec
OnManual
(
ctx
,
r
.
Script
,
event
.
NamespaceOnManual
(
namespace
,
nil
))
err
=
corredor
.
Service
()
.
Exec
(
ctx
,
r
.
Script
,
event
.
NamespaceOnManual
(
namespace
,
nil
))
return
ctrl
.
makePayload
(
ctx
,
namespace
,
err
)
}
...
...
This diff is collapsed.
Click to expand it.
compose/rest/page.go
View file @
cb9682e4
...
...
@@ -172,7 +172,7 @@ func (ctrl *Page) TriggerScript(ctx context.Context, r *request.PageTriggerScrip
}
// @todo implement same behaviour as we have on record - page+oldPage
err
=
corredor
.
Service
()
.
Exec
OnManual
(
ctx
,
r
.
Script
,
event
.
PageOnManual
(
page
,
page
,
namespace
))
err
=
corredor
.
Service
()
.
Exec
(
ctx
,
r
.
Script
,
event
.
PageOnManual
(
page
,
page
,
namespace
))
return
ctrl
.
makePayload
(
ctx
,
page
,
err
)
}
...
...
This diff is collapsed.
Click to expand it.
compose/rest/record.go
View file @
cb9682e4
...
...
@@ -426,7 +426,7 @@ func (ctrl *Record) TriggerScript(ctx context.Context, r *request.RecordTriggerS
record
.
Values
=
values
.
Sanitizer
()
.
Run
(
module
,
r
.
Values
)
validated
:=
values
.
Validator
()
.
Run
(
module
,
record
)
err
=
corredor
.
Service
()
.
Exec
OnManual
(
err
=
corredor
.
Service
()
.
Exec
(
ctx
,
r
.
Script
,
event
.
RecordOnManual
(
record
,
oldRecord
,
module
,
namespace
,
validated
),
...
...
@@ -436,6 +436,27 @@ func (ctrl *Record) TriggerScript(ctx context.Context, r *request.RecordTriggerS
return
ctrl
.
makePayload
(
ctx
,
module
,
record
,
err
)
}
func
(
ctrl
*
Record
)
TriggerScriptOnList
(
ctx
context
.
Context
,
r
*
request
.
RecordTriggerScriptOnList
)
(
rsp
interface
{},
err
error
)
{
//var (
// module *types.Module
// namespace *types.Namespace
//)
//
//if module, err = ctrl.module.With(ctx).FindByID(r.NamespaceID, r.ModuleID); err != nil {
// return
//}
//
//if namespace, err = ctrl.namespace.With(ctx).FindByID(r.NamespaceID); err != nil {
// return
//}
// @todo this does not need to be under /record ... where then?!?!
err
=
corredor
.
Service
()
.
ExecIterator
(
ctx
,
r
.
Script
)
// Script can return modified record and we'll pass it on to the caller
return
resputil
.
OK
(),
err
}
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
...
...
This diff is collapsed.
Click to expand it.
compose/rest/request/record.go
View file @
cb9682e4
...
...
@@ -923,3 +923,62 @@ func (r *RecordTriggerScript) Fill(req *http.Request) (err error) {
}
var
_
RequestFiller
=
NewRecordTriggerScript
()
// Record triggerScriptOnList request parameters
type
RecordTriggerScriptOnList
struct
{
Script
string
NamespaceID
uint64
`json:",string"`
ModuleID
uint64
`json:",string"`
}
func
NewRecordTriggerScriptOnList
()
*
RecordTriggerScriptOnList
{
return
&
RecordTriggerScriptOnList
{}
}
func
(
r
RecordTriggerScriptOnList
)
Auditable
()
map
[
string
]
interface
{}
{
var
out
=
map
[
string
]
interface
{}{}
out
[
"script"
]
=
r
.
Script
out
[
"namespaceID"
]
=
r
.
NamespaceID
out
[
"moduleID"
]
=
r
.
ModuleID
return
out
}
func
(
r
*
RecordTriggerScriptOnList
)
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
])
}
if
val
,
ok
:=
post
[
"script"
];
ok
{
r
.
Script
=
val
}
r
.
NamespaceID
=
parseUInt64
(
chi
.
URLParam
(
req
,
"namespaceID"
))
r
.
ModuleID
=
parseUInt64
(
chi
.
URLParam
(
req
,
"moduleID"
))
return
err
}
var
_
RequestFiller
=
NewRecordTriggerScriptOnList
()
This diff is collapsed.
Click to expand it.
compose/service/event/events.yaml
View file @
cb9682e4
...
...
@@ -38,7 +38,7 @@ compose:module:
immutable
:
true
compose:record:
on
:
[
'
manual'
]
on
:
[
'
manual'
,
'
iteration'
]
ba
:
[
'
create'
,
'
update'
,
'
delete'
]
props
:
-
name
:
'
record'
...
...
This diff is collapsed.
Click to expand it.
compose/service/event/module.go
View file @
cb9682e4
...
...
@@ -7,11 +7,14 @@ import (
// Match returns false if given conditions do not match event & resource internals
func
(
res
moduleBase
)
Match
(
c
eventbus
.
ConstraintMatcher
)
bool
{
return
namespaceMatch
(
res
.
namespace
,
c
,
moduleMatch
(
res
.
module
,
c
,
false
))
return
eventbus
.
MatchFirst
(
func
()
bool
{
return
moduleMatch
(
res
.
module
,
c
)
},
func
()
bool
{
return
namespaceMatch
(
res
.
namespace
,
c
)
},
)
}
// Handles module matchers
func
moduleMatch
(
r
*
types
.
Module
,
c
eventbus
.
ConstraintMatcher
,
def
bool
)
bool
{
func
moduleMatch
(
r
*
types
.
Module
,
c
eventbus
.
ConstraintMatcher
)
bool
{
switch
c
.
Name
()
{
case
"module"
,
"module.handle"
:
return
c
.
Match
(
r
.
Handle
)
...
...
@@ -19,5 +22,5 @@ func moduleMatch(r *types.Module, c eventbus.ConstraintMatcher, def bool) bool {
return
c
.
Match
(
r
.
Name
)
}
return
def
return
false
}
This diff is collapsed.
Click to expand it.
compose/service/event/namespace.go
View file @
cb9682e4
...
...
@@ -7,11 +7,11 @@ import (
// Match returns false if given conditions do not match event & resource internals
func
(
res
namespaceBase
)
Match
(
c
eventbus
.
ConstraintMatcher
)
bool
{
return
namespaceMatch
(
res
.
namespace
,
c
,
false
)
return
namespaceMatch
(
res
.
namespace
,
c
)
}
// Handles namespace matchers
func
namespaceMatch
(
r
*
types
.
Namespace
,
c
eventbus
.
ConstraintMatcher
,
def
bool
)
bool
{
func
namespaceMatch
(
r
*
types
.
Namespace
,
c
eventbus
.
ConstraintMatcher
)
bool
{
switch
c
.
Name
()
{
case
"namespace"
,
"namespace.slug"
:
return
c
.
Match
(
r
.
Slug
)
...
...
@@ -19,5 +19,5 @@ func namespaceMatch(r *types.Namespace, c eventbus.ConstraintMatcher, def bool)
return
c
.
Match
(
r
.
Name
)
}
return
def
return
false
}
This diff is collapsed.
Click to expand it.
compose/service/event/page.go
View file @
cb9682e4
...
...
@@ -7,11 +7,14 @@ import (
// Match returns false if given conditions do not match event & resource internals
func
(
res
pageBase
)
Match
(
c
eventbus
.
ConstraintMatcher
)
bool
{
return
namespaceMatch
(
res
.
namespace
,
c
,
pageMatch
(
res
.
page
,
c
,
false
))
return
eventbus
.
MatchFirst
(
func
()
bool
{
return
pageMatch
(
res
.
page
,
c
)
},
func
()
bool
{
return
namespaceMatch
(
res
.
namespace
,
c
)
},
)
}
// Handles namespace matchers
func
pageMatch
(
r
*
types
.
Page
,
c
eventbus
.
ConstraintMatcher
,
def
bool
)
bool
{
func
pageMatch
(
r
*
types
.
Page
,
c
eventbus
.
ConstraintMatcher
)
bool
{
switch
c
.
Name
()
{
case
"page"
,
"page.handle"
:
return
c
.
Match
(
r
.
Handle
)
...
...
@@ -19,5 +22,5 @@ func pageMatch(r *types.Page, c eventbus.ConstraintMatcher, def bool) bool {
return
c
.
Match
(
r
.
Title
)
}
return
def
return
false
}
This diff is collapsed.
Click to expand it.
compose/service/event/record.gen.go
View file @
cb9682e4
...
...
@@ -38,6 +38,13 @@ type (
*
recordBase
}
// recordOnIteration
//
// This type is auto-generated.
recordOnIteration
struct
{
*
recordBase
}
// recordBeforeCreate
//
// This type is auto-generated.
...
...
@@ -95,6 +102,13 @@ func (recordOnManual) EventType() string {
return
"onManual"
}
// EventType on recordOnIteration returns "onIteration"
//
// This function is auto-generated.
func
(
recordOnIteration
)
EventType
()
string
{
return
"onIteration"
}
// EventType on recordBeforeCreate returns "beforeCreate"
//
// This function is auto-generated.
...
...
@@ -183,6 +197,52 @@ func RecordOnManualImmutable(
}
}
// RecordOnIteration creates onIteration for compose:record resource
//
// This function is auto-generated.
func
RecordOnIteration
(
argRecord
*
types
.
Record
,
argOldRecord
*
types
.
Record
,
argModule
*
types
.
Module
,
argNamespace
*
types
.
Namespace
,
argRecordValueErrors
*
types
.
RecordValueErrorSet
,
)
*
recordOnIteration
{
return
&
recordOnIteration
{
recordBase
:
&
recordBase
{
immutable
:
false
,
record
:
argRecord
,
oldRecord
:
argOldRecord
,
module
:
argModule
,
namespace
:
argNamespace
,
recordValueErrors
:
argRecordValueErrors
,
},
}
}
// RecordOnIterationImmutable creates onIteration for compose:record resource
//
// None of the arguments will be mutable!
//
// This function is auto-generated.
func
RecordOnIterationImmutable
(
argRecord
*
types
.
Record
,
argOldRecord
*
types
.
Record
,
argModule
*
types
.
Module
,
argNamespace
*
types
.
Namespace
,
argRecordValueErrors
*
types
.
RecordValueErrorSet
,
)
*
recordOnIteration
{
return
&
recordOnIteration
{
recordBase
:
&
recordBase
{
immutable
:
true
,
record
:
argRecord
,
oldRecord
:
argOldRecord
,
module
:
argModule
,
namespace
:
argNamespace
,
recordValueErrors
:
argRecordValueErrors
,
},
}
}
// RecordBeforeCreate creates beforeCreate for compose:record resource
//
// This function is auto-generated.
...
...
This diff is collapsed.
Click to expand it.
compose/service/event/record.go
View file @
cb9682e4
...
...
@@ -13,10 +13,14 @@ const (
// Match returns false if given conditions do not match event & resource internals
func
(
res
recordBase
)
Match
(
c
eventbus
.
ConstraintMatcher
)
bool
{
return
recordMatch
(
res
.
record
,
c
,
namespaceMatch
(
res
.
namespace
,
c
,
moduleMatch
(
res
.
module
,
c
,
false
)))
return
eventbus
.
MatchFirst
(
func
()
bool
{
return
recordMatch
(
res
.
record
,
c
)
},
func
()
bool
{
return
moduleMatch
(
res
.
module
,
c
)
},
func
()
bool
{
return
namespaceMatch
(
res
.
namespace
,
c
)
},
)
}
func
recordMatch
(
r
*
types
.
Record
,
c
eventbus
.
ConstraintMatcher
,
def
bool
)
bool
{
func
recordMatch
(
r
*
types
.
Record
,
c
eventbus
.
ConstraintMatcher
)
bool
{
switch
c
.
Name
()
{
case
"record.updatedAt"
:
return
c
.
Match
(
r
.
UpdatedAt
.
Format
(
time
.
RFC3339
))
...
...
@@ -35,5 +39,5 @@ func recordMatch(r *types.Record, c eventbus.ConstraintMatcher, def bool) bool {
}
}
return
def
return
false
}
This diff is collapsed.
Click to expand it.
compose/service/module.go
View file @
cb9682e4
...
...
@@ -2,6 +2,7 @@ package service
import
(
"context"
"strconv"
"github.com/titpetric/factory"
"go.uber.org/zap"
...
...
@@ -47,6 +48,7 @@ type (
FindByID
(
namespaceID
,
moduleID
uint64
)
(
*
types
.
Module
,
error
)
FindByName
(
namespaceID
uint64
,
name
string
)
(
*
types
.
Module
,
error
)
FindByHandle
(
namespaceID
uint64
,
handle
string
)
(
*
types
.
Module
,
error
)
FindByAny
(
namespaceID
uint64
,
identifier
interface
{})
(
*
types
.
Module
,
error
)
Find
(
filter
types
.
ModuleFilter
)
(
set
types
.
ModuleSet
,
f
types
.
ModuleFilter
,
err
error
)
Create
(
module
*
types
.
Module
)
(
*
types
.
Module
,
error
)
...
...
@@ -109,6 +111,30 @@ func (svc module) FindByHandle(namespaceID uint64, handle string) (m *types.Modu
}
}
// FindByAny tries to find module in a particular namespace by id, handle or name
func
(
svc
module
)
FindByAny
(
namespaceID
uint64
,
identifier
interface
{})
(
r
*
types
.
Module
,
err
error
)
{
if
ID
,
ok
:=
identifier
.
(
uint64
);
ok
{
r
,
err
=
svc
.
FindByID
(
namespaceID
,
ID
)
}
else
if
strIdentifier
,
ok
:=
identifier
.
(
string
);
ok
{
if
ID
,
_
:=
strconv
.
ParseUint
(
strIdentifier
,
10
,
64
);
ID
>
0
{
r
,
err
=
svc
.
FindByID
(
namespaceID
,
ID
)
}
else
{
r
,
err
=
svc
.
FindByHandle
(
namespaceID
,
strIdentifier
)
if
err
==
nil
&&
r
.
ID
==
0
{
r
,
err
=
svc
.
FindByName
(
namespaceID
,
strIdentifier
)
}
}
}
else
{
err
=
ErrInvalidID
.
withStack
()
}
if
err
!=
nil
{
return
}
return
}
func
(
svc
module
)
loader
(
m
*
types
.
Module
,
err
error
)
(
*
types
.
Module
,
error
)
{
if
err
!=
nil
{
return
nil
,
err
...
...
This diff is collapsed.
Click to expand it.
compose/service/namespace.go
View file @
cb9682e4
...
...
@@ -2,6 +2,7 @@ package service
import
(
"context"
"strconv"
"github.com/titpetric/factory"
"go.uber.org/zap"
...
...
@@ -45,6 +46,7 @@ type (
FindByID
(
namespaceID
uint64
)
(
*
types
.
Namespace
,
error
)
FindByHandle
(
handle
string
)
(
*
types
.
Namespace
,
error
)
Find
(
types
.
NamespaceFilter
)
(
types
.
NamespaceSet
,
types
.
NamespaceFilter
,
error
)
FindByAny
(
interface
{})
(
*
types
.
Namespace
,
error
)
Create
(
namespace
*
types
.
Namespace
)
(
*
types
.
Namespace
,
error
)
Update
(
namespace
*
types
.
Namespace
)
(
*
types
.
Namespace
,
error
)
...
...
@@ -91,6 +93,30 @@ func (svc namespace) FindBySlug(slug string) (ns *types.Namespace, err error) {
return
svc
.
checkPermissions
(
svc
.
namespaceRepo
.
FindBySlug
(
slug
))
}
// FindByAny tries to find namespace by id, handle or slug
func
(
svc
namespace
)
FindByAny
(
identifier
interface
{})
(
r
*
types
.
Namespace
,
err
error
)
{
if
ID
,
ok
:=
identifier
.
(
uint64
);
ok
{
r
,
err
=
svc
.
FindByID
(
ID
)
}
else
if
strIdentifier
,
ok
:=
identifier
.
(
string
);
ok
{
if
ID
,
_
:=
strconv
.
ParseUint
(
strIdentifier
,
10
,
64
);
ID
>
0
{
r
,
err
=
svc
.
FindByID
(
ID
)
}
else
{
r
,
err
=
svc
.
FindByHandle
(
strIdentifier
)
if
err
==
nil
&&
r
.
ID
==
0
{
r
,
err
=
svc
.
FindBySlug
(
strIdentifier
)
}
}
}
else
{
err
=
ErrInvalidID
.
withStack
()
}
if
err
!=
nil
{
return
}
return
}
func
(
svc
namespace
)
checkPermissions
(
p
*
types
.
Namespace
,
err
error
)
(
*
types
.
Namespace
,
error
)
{
if
err
!=
nil
{
return
nil
,
err
...
...
This diff is collapsed.
Click to expand it.
compose/service/record.go
View file @
cb9682e4
...
...
@@ -82,6 +82,8 @@ type (
DeleteByID
(
namespaceID
,
moduleID
uint64
,
recordID
...
uint64
)
error
Organize
(
namespaceID
,
moduleID
,
recordID
uint64
,
sortingField
,
sortingValue
,
sortingFilter
,
valueField
,
value
string
)
error
Iterator
(
f
types
.
RecordFilter
,
fn
eventbus
.
HandlerFn
,
action
string
)
(
err
error
)
}
Encoder
interface
{
...
...
@@ -795,6 +797,123 @@ func (svc record) Organize(namespaceID, moduleID, recordID uint64, posField, pos
})
}
// Iterator loads and iterates through list of records
//
// For each record, RecordOnIteration is generated and passed to fn()
// to be then passed to automation script that invoked the iteration
//
// No other triggers (before/after update/delete/create) are fired when (if)
// records are changed
//
// action arg enables one of the following scenarios:
// - clone: make new record (unless aborted)
// - update: update records (unless aborted)
// - delete: delete records (unless aborted)
// - default: only iterates over records, records are not changed, return value is ignored
//
//
// Iterator can be invoked only when defined in corredor script:
//
// return default {
// iterator (each) {
// return each({
// resourceType: 'compose:record',
// // action: 'update',
// filter: {
// namespace: '122709101053521922',
// module: '122709116471783426',
// query: 'Status = "foo"',
// sort: 'Status DESC',
// limit: 3,
// },
// })
// },
//
// // this is required in case of a deferred iterator
// // security: { runAs: .... } }
//
// // exec gets called for every record found by iterator
// exec () { ... }
// }
func
(
svc
record
)
Iterator
(
f
types
.
RecordFilter
,
fn
eventbus
.
HandlerFn
,
action
string
)
(
err
error
)
{
var
(
invokerID
=
auth
.
GetIdentityFromContext
(
svc
.
ctx
)
.
Identity
()
ns
*
types
.
Namespace
m
*
types
.
Module
set
types
.
RecordSet
)
return
svc
.
db
.
Transaction
(
func
()
(
err
error
)
{
if
ns
,
m
,
_
,
err
=
svc
.
loadCombo
(
f
.
NamespaceID
,
f
.
ModuleID
,
0
);
err
!=
nil
{
return
}
if
!
svc
.
ac
.
CanUpdateRecord
(
svc
.
ctx
,
m
)
{
return
ErrNoUpdatePermissions
.
withStack
()
}
// @todo might be good to split set into smaller chunks
set
,
f
,
err
=
svc
.
recordRepo
.
Find
(
m
,
f
)
if
err
!=
nil
{
return
}
if
err
=
svc
.
preloadValues
(
m
,
set
...
);
err
!=
nil
{
return
}
for
_
,
rec
:=
range
set
{
if
err
=
fn
(
svc
.
ctx
,
event
.
RecordOnIteration
(
rec
,
nil
,
m
,
ns
,
nil
));
err
!=
nil
{
if
err
.
Error
()
!=
"Aborted"
{
// When script was softly aborted (return false),
// proceed with iteration but do not clone, update or delete
// current record!
return
}
}
switch
action
{
case
"clone"
:
var
cln
*
types
.
Record
// Assign defaults (only on missing values)
rec
.
Values
=
svc
.
setDefaultValues
(
m
,
rec
.
Values
)
// Handle payload from automation scripts
if
rve
:=
svc
.
procCreate
(
invokerID
,
m
,
rec
);
!
rve
.
IsValid
()
{
return
rve
}
if
cln
,
err
=
svc
.
recordRepo
.
Create
(
rec
);
err
!=
nil
{
return
}
else
if
err
=
svc
.
recordRepo
.
UpdateValues
(
cln
.
ID
,
cln
.
Values
);
err
!=
nil
{
return
}
case
"update"
:
// Handle input payload
if
rve
:=
svc
.
procUpdate
(
invokerID
,
m
,
rec
,
rec
);
!
rve
.
IsValid
()
{
return
rve
}
if
rec
,
err
=
svc
.
recordRepo
.
Update
(
rec
);
err
!=
nil
{
return
}
else
if
err
=
svc
.
recordRepo
.
UpdateValues
(
rec
.
ID
,
rec
.
Values
);
err
!=
nil
{
return
}
case
"delete"
:
if
err
=
svc
.
recordRepo
.
Delete
(
rec
);
err
!=
nil
{
return
err
}
else
if
err
=
svc
.
recordRepo
.
DeleteValues
(
rec
);
err
!=
nil
{
return
err
}
}
}
return
})
}
// loadCombo Loads everything we need for record manipulation
//
// Loads namespace, module, record and set of triggers.
...
...
This diff is collapsed.
Click to expand it.
compose/service/service.go
View file @
cb9682e4
...
...
@@ -2,6 +2,8 @@ package service
import
(
"context"
"errors"
"github.com/cortezaproject/corteza-server/pkg/corredor"
"time"
"go.uber.org/zap"
...
...
@@ -141,6 +143,8 @@ func Initialize(ctx context.Context, log *zap.Logger, c Config) (err error) {
DefaultNotification
=
Notification
()
DefaultAttachment
=
Attachment
(
DefaultStore
)
RegisterIteratorProviders
()
return
nil
}
...
...
@@ -159,6 +163,39 @@ func Watchers(ctx context.Context) {
DefaultPermissions
.
Watch
(
ctx
)
}
func
RegisterIteratorProviders
()
{
// Register resource finders on iterator
corredor
.
Service
()
.
RegisterIteratorProvider
(
"compose:record"
,
func
(
ctx
context
.
Context
,
f
map
[
string
]
string
,
h
eventbus
.
HandlerFn
,
action
string
)
error
{
rf
:=
types
.
RecordFilter
{
Filter
:
f
[
"filter"
],
Sort
:
f
[
"sort"
],
}
rf
.
ParsePagination
(
f
)
if
nsLookup
,
has
:=
f
[
"namespace"
];
!
has
{
return
errors
.
New
(
"namespace for record iteration filter not defined"
)
}
else
if
ns
,
err
:=
DefaultNamespace
.
With
(
ctx
)
.
FindByAny
(
nsLookup
);
err
!=
nil
{
return
err
}
else
{
rf
.
NamespaceID
=
ns
.
ID
}
if
mLookup
,
has
:=
f
[
"module"
];
!
has
{
return
errors
.
New
(
"module for record iteration filter not defined"
)
}
else
if
m
,
err
:=
DefaultModule
.
With
(
ctx
)
.
FindByAny
(
rf
.
NamespaceID
,
mLookup
);
err
!=
nil
{
return
err
}
else
{
rf
.
ModuleID
=
m
.
ID
}
return
DefaultRecord
.
With
(
ctx
)
.
Iterator
(
rf
,
h
,
action
)
},
)
}
// Data is stale when new date does not match updatedAt or createdAt (before first update)
func
isStale
(
new
*
time
.
Time
,
updatedAt
*
time
.
Time
,
createdAt
time
.
Time
)
bool
{
if
new
==
nil
{
...
...
This diff is collapsed.
Click to expand it.
docs/compose/README.md
View file @
cb9682e4
...
...
@@ -651,6 +651,7 @@ Compose pages
| title | string | POST | Title | N/A | YES |
| handle | string | POST | Handle | N/A | NO |
| description | string | POST | Description | N/A | NO |
| weight | int | POST | Page tree weight | N/A | NO |
| visible | bool | POST | Visible in navigation | N/A | NO |
| blocks | sqlxTypes.JSONText | POST | Blocks JSON | N/A | NO |
...
...
@@ -827,6 +828,7 @@ Compose records
|
`DELETE`
|
`/namespace/{namespaceID}/module/{moduleID}/record/{recordID}`
| Delete record row from module section |
|
`POST`
|
`/namespace/{namespaceID}/module/{moduleID}/record/attachment`
| Uploads attachment and validates it against record field requirements |
|
`POST`
|
`/namespace/{namespaceID}/module/{moduleID}/record/{recordID}/trigger`
| Fire compose:record trigger |
|
`POST`
|
`/namespace/{namespaceID}/module/{moduleID}/record/trigger`
| Fire compose:record trigger |
## Generates report from module records
...
...
@@ -1069,6 +1071,22 @@ Compose records
| script | string | POST | Script to execute | N/A | YES |
| values | types.RecordValueSet | POST | Record values | N/A | YES |
## Fire compose:record trigger
#### Method
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
|
`/namespace/{namespaceID}/module/{moduleID}/record/trigger`
| HTTP/S | POST | |
#### Request parameters
| Parameter | Type | Method | Description | Default | Required? |
| --------- | ---- | ------ | ----------- | ------- | --------- |
| script | string | POST | Script to execute | N/A | YES |
| namespaceID | uint64 | PATH | Namespace ID | N/A | YES |
| moduleID | uint64 | PATH | Module ID | N/A | YES |
---
...
...
This diff is collapsed.
Click to expand it.
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment