snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
This commit is contained in:
274
server/system/service/apigw_route.go
Normal file
274
server/system/service/apigw_route.go
Normal file
@@ -0,0 +1,274 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/actionlog"
|
||||
"github.com/cortezaproject/corteza/server/pkg/apigw"
|
||||
a "github.com/cortezaproject/corteza/server/pkg/auth"
|
||||
"github.com/cortezaproject/corteza/server/pkg/errors"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
)
|
||||
|
||||
type (
|
||||
apigwRoute struct {
|
||||
actionlog actionlog.Recorder
|
||||
store store.Storer
|
||||
ac routeAccessController
|
||||
}
|
||||
|
||||
routeAccessController interface {
|
||||
CanGrant(context.Context) bool
|
||||
CanSearchApigwRoutes(ctx context.Context) bool
|
||||
|
||||
CanCreateApigwRoute(context.Context) bool
|
||||
CanReadApigwRoute(context.Context, *types.ApigwRoute) bool
|
||||
CanUpdateApigwRoute(context.Context, *types.ApigwRoute) bool
|
||||
CanDeleteApigwRoute(context.Context, *types.ApigwRoute) bool
|
||||
}
|
||||
)
|
||||
|
||||
func Route() *apigwRoute {
|
||||
return &apigwRoute{
|
||||
ac: DefaultAccessControl,
|
||||
actionlog: DefaultActionlog,
|
||||
store: DefaultStore,
|
||||
}
|
||||
}
|
||||
|
||||
func (svc *apigwRoute) FindByID(ctx context.Context, ID uint64) (q *types.ApigwRoute, err error) {
|
||||
var (
|
||||
rProps = &apigwRouteActionProps{}
|
||||
)
|
||||
|
||||
err = func() error {
|
||||
if q, err = loadApigwRoute(ctx, svc.store, ID); err != nil {
|
||||
return ApigwRouteErrInvalidID().Wrap(err)
|
||||
}
|
||||
|
||||
rProps.setRoute(q)
|
||||
|
||||
if !svc.ac.CanReadApigwRoute(ctx, q) {
|
||||
return ApigwRouteErrNotAllowedToRead(rProps)
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return q, svc.recordAction(ctx, rProps, ApigwRouteActionLookup, err)
|
||||
}
|
||||
|
||||
func (svc *apigwRoute) Create(ctx context.Context, new *types.ApigwRoute) (q *types.ApigwRoute, err error) {
|
||||
var (
|
||||
qProps = &apigwRouteActionProps{route: new}
|
||||
)
|
||||
|
||||
err = func() (err error) {
|
||||
if !svc.ac.CanCreateApigwRoute(ctx) {
|
||||
return ApigwRouteErrNotAllowedToCreate(qProps)
|
||||
}
|
||||
|
||||
new.ID = nextID()
|
||||
new.CreatedAt = *now()
|
||||
new.CreatedBy = a.GetIdentityFromContext(ctx).Identity()
|
||||
|
||||
// todo
|
||||
new.Group = 0
|
||||
|
||||
qProps.setNew(new)
|
||||
|
||||
if err = store.CreateApigwRoute(ctx, svc.store, new); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
q = new
|
||||
|
||||
// send the signal to reload new route
|
||||
if new.Enabled {
|
||||
if err = apigw.Service().ReloadEndpoint(ctx, new.Method, new.Endpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return q, svc.recordAction(ctx, qProps, ApigwRouteActionCreate, err)
|
||||
}
|
||||
|
||||
func (svc *apigwRoute) Update(ctx context.Context, upd *types.ApigwRoute) (res *types.ApigwRoute, err error) {
|
||||
var (
|
||||
qProps = &apigwRouteActionProps{update: upd}
|
||||
e error
|
||||
)
|
||||
|
||||
err = func() (err error) {
|
||||
if res, e = loadApigwRoute(ctx, svc.store, upd.ID); e != nil {
|
||||
return ApigwRouteErrNotFound(qProps)
|
||||
}
|
||||
|
||||
var (
|
||||
// check if old endpoint moved and attach the 404 handler
|
||||
endpointMoved = res.Enabled != upd.Enabled || res.Method != upd.Method || res.Endpoint != upd.Endpoint
|
||||
)
|
||||
|
||||
if !svc.ac.CanUpdateApigwRoute(ctx, res) {
|
||||
return ApigwRouteErrNotAllowedToUpdate(qProps)
|
||||
}
|
||||
|
||||
// Test if stale (update has an older version of data)
|
||||
if isStale(upd.UpdatedAt, res.UpdatedAt, res.CreatedAt) {
|
||||
return ApigwRouteErrStaleData()
|
||||
}
|
||||
|
||||
// copy (potentially) updated files from the payload
|
||||
res.Meta = upd.Meta
|
||||
res.Method = upd.Method
|
||||
res.Endpoint = upd.Endpoint
|
||||
res.Enabled = upd.Enabled
|
||||
res.Group = upd.Group
|
||||
|
||||
// ensure we have a valid endpoint
|
||||
res.UpdatedAt = now()
|
||||
res.UpdatedBy = a.GetIdentityFromContext(ctx).Identity()
|
||||
|
||||
if err = store.UpdateApigwRoute(ctx, svc.store, res); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// @todo move this into struct of the service (svc),
|
||||
// same as we do for services for other structs
|
||||
ags := apigw.Service()
|
||||
|
||||
// old endpoint moved: attach 404 handler
|
||||
if endpointMoved {
|
||||
ags.NotFound(ctx, res.Method, res.Endpoint)
|
||||
}
|
||||
|
||||
// send the signal to reload updated route
|
||||
if upd.Enabled {
|
||||
if err = ags.ReloadEndpoint(ctx, upd.Method, upd.Endpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return res, svc.recordAction(ctx, qProps, ApigwRouteActionUpdate, err)
|
||||
}
|
||||
|
||||
func (svc *apigwRoute) DeleteByID(ctx context.Context, ID uint64) (err error) {
|
||||
var (
|
||||
qProps = &apigwRouteActionProps{}
|
||||
q *types.ApigwRoute
|
||||
)
|
||||
|
||||
err = func() (err error) {
|
||||
if q, err = loadApigwRoute(ctx, svc.store, ID); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !svc.ac.CanDeleteApigwRoute(ctx, q) {
|
||||
return ApigwRouteErrNotAllowedToDelete(qProps)
|
||||
}
|
||||
|
||||
qProps.setRoute(q)
|
||||
|
||||
q.DeletedAt = now()
|
||||
q.DeletedBy = a.GetIdentityFromContext(ctx).Identity()
|
||||
|
||||
if err = store.UpdateApigwRoute(ctx, svc.store, q); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// send the signal to reload deleted route
|
||||
if q.Enabled {
|
||||
apigw.Service().NotFound(ctx, q.Method, q.Endpoint)
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return svc.recordAction(ctx, qProps, ApigwRouteActionDelete, err)
|
||||
}
|
||||
|
||||
func (svc *apigwRoute) UndeleteByID(ctx context.Context, ID uint64) (err error) {
|
||||
var (
|
||||
qProps = &apigwRouteActionProps{}
|
||||
q *types.ApigwRoute
|
||||
)
|
||||
|
||||
err = func() (err error) {
|
||||
if q, err = loadApigwRoute(ctx, svc.store, ID); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !svc.ac.CanDeleteApigwRoute(ctx, q) {
|
||||
return ApigwRouteErrNotAllowedToUndelete(qProps)
|
||||
}
|
||||
|
||||
qProps.setRoute(q)
|
||||
|
||||
q.DeletedAt = nil
|
||||
q.UpdatedBy = a.GetIdentityFromContext(ctx).Identity()
|
||||
|
||||
if err = store.UpdateApigwRoute(ctx, svc.store, q); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// send the signal to reload all queues
|
||||
if q.Enabled {
|
||||
if err = apigw.Service().ReloadEndpoint(ctx, q.Method, q.Endpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return svc.recordAction(ctx, qProps, ApigwRouteActionDelete, err)
|
||||
}
|
||||
|
||||
func (svc *apigwRoute) Search(ctx context.Context, filter types.ApigwRouteFilter) (r types.ApigwRouteSet, f types.ApigwRouteFilter, err error) {
|
||||
var (
|
||||
aProps = &apigwRouteActionProps{search: &filter}
|
||||
)
|
||||
|
||||
// For each fetched item, store backend will check if it is valid or not
|
||||
filter.Check = func(res *types.ApigwRoute) (bool, error) {
|
||||
if !svc.ac.CanReadApigwRoute(ctx, res) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
err = func() error {
|
||||
if !svc.ac.CanSearchApigwRoutes(ctx) {
|
||||
return ApigwRouteErrNotAllowedToSearch()
|
||||
}
|
||||
|
||||
if r, f, err = store.SearchApigwRoutes(ctx, svc.store, filter); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return r, f, svc.recordAction(ctx, aProps, ApigwRouteActionSearch, err)
|
||||
}
|
||||
|
||||
func loadApigwRoute(ctx context.Context, s store.ApigwRoutes, ID uint64) (res *types.ApigwRoute, err error) {
|
||||
if ID == 0 {
|
||||
return nil, ApigwRouteErrInvalidID()
|
||||
}
|
||||
|
||||
if res, err = store.LookupApigwRouteByID(ctx, s, ID); errors.IsNotFound(err) {
|
||||
return nil, ApigwRouteErrNotFound()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user