diff --git a/.env.example b/.env.example index f5ff0a7c9..195f64464 100644 --- a/.env.example +++ b/.env.example @@ -84,3 +84,6 @@ DB_DSN=corteza:corteza@tcp(localhost:3306)/corteza?collation=utf8mb4_general_ci # Strict mode: # When true, it does not create un-existing buckets #MINIO_STRICT=false + +# Federation feature +FEDERATION_ENABLED=false diff --git a/federation/rest.yaml b/federation/rest.yaml index c89dc5f78..16c1a30e3 100644 --- a/federation/rest.yaml +++ b/federation/rest.yaml @@ -78,14 +78,19 @@ endpoints: type: string required: true title: Auth token of the origin node - - - title: Foobar - entrypoint: foobar - path: "/foobar" + - title: Modules + description: Federation module definitions + entrypoint: module + path: "/structure/module" authentication: [] - imports: apis: - - name: foobar + - name: read method: GET - title: Foo bar - path: "/" + title: Read federated module + path: "/{moduleID}" + parameters: + path: + - type: uint64 + name: moduleID + required: true + title: Module ID diff --git a/federation/rest/foobar.go b/federation/rest/foobar.go deleted file mode 100644 index 4e1cbabb1..000000000 --- a/federation/rest/foobar.go +++ /dev/null @@ -1,37 +0,0 @@ -package rest - -import ( - "context" - - "github.com/cortezaproject/corteza-server/compose/types" - "github.com/cortezaproject/corteza-server/federation/rest/request" -) - -type ( - namespacePayload struct { - *types.Namespace - - CanGrant bool `json:"canGrant"` - CanUpdateNamespace bool `json:"canUpdateNamespace"` - CanDeleteNamespace bool `json:"canDeleteNamespace"` - CanManageNamespace bool `json:"canManageNamespace"` - CanCreateModule bool `json:"canCreateModule"` - CanCreateChart bool `json:"canCreateChart"` - CanCreatePage bool `json:"canCreatePage"` - } - - payload struct{} - Foobar struct{} - - accessController interface { - CanGrant(context.Context) bool - } -) - -func (Foobar) New() *Foobar { - return &Foobar{} -} - -func (ctrl Foobar) Foobar(ctx context.Context, r *request.FoobarFoobar) (interface{}, error) { - return &struct{}{}, nil -} diff --git a/federation/rest/handlers/foobar.go b/federation/rest/handlers/module.go similarity index 56% rename from federation/rest/handlers/foobar.go rename to federation/rest/handlers/module.go index af75fc41b..4fcae427e 100644 --- a/federation/rest/handlers/foobar.go +++ b/federation/rest/handlers/module.go @@ -20,34 +20,34 @@ import ( type ( // Internal API interface - FoobarAPI interface { - Foobar(context.Context, *request.FoobarFoobar) (interface{}, error) + ModuleAPI interface { + Read(context.Context, *request.ModuleRead) (interface{}, error) } // HTTP API interface - Foobar struct { - Foobar func(http.ResponseWriter, *http.Request) + Module struct { + Read func(http.ResponseWriter, *http.Request) } ) -func NewFoobar(h FoobarAPI) *Foobar { - return &Foobar{ - Foobar: func(w http.ResponseWriter, r *http.Request) { +func NewModule(h ModuleAPI) *Module { + return &Module{ + Read: func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() - params := request.NewFoobarFoobar() + params := request.NewModuleRead() if err := params.Fill(r); err != nil { - logger.LogParamError("Foobar.Foobar", r, err) + logger.LogParamError("Module.Read", r, err) resputil.JSON(w, err) return } - value, err := h.Foobar(r.Context(), params) + value, err := h.Read(r.Context(), params) if err != nil { - logger.LogControllerError("Foobar.Foobar", r, err, params.Auditable()) + logger.LogControllerError("Module.Read", r, err, params.Auditable()) resputil.JSON(w, err) return } - logger.LogControllerCall("Foobar.Foobar", r, params.Auditable()) + logger.LogControllerCall("Module.Read", r, params.Auditable()) if !serveHTTP(value, w, r) { resputil.JSON(w, value) } @@ -55,9 +55,9 @@ func NewFoobar(h FoobarAPI) *Foobar { } } -func (h Foobar) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) { +func (h Module) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) { r.Group(func(r chi.Router) { r.Use(middlewares...) - r.Get("/foobar/", h.Foobar) + r.Get("/structure/module/{moduleID}", h.Read) }) } diff --git a/federation/rest/module.go b/federation/rest/module.go new file mode 100644 index 000000000..05ebf06f8 --- /dev/null +++ b/federation/rest/module.go @@ -0,0 +1,21 @@ +package rest + +import ( + "context" + + "github.com/cortezaproject/corteza-server/federation/rest/request" +) + +type ( + payload struct{} + Module struct{} +) + +func (Module) New() *Module { + return &Module{} +} + +func (ctrl Module) Read(ctx context.Context, r *request.ModuleRead) (interface{}, error) { + // use filtering and call structure sync service + return &struct{}{}, nil +} diff --git a/federation/rest/request/foobar.go b/federation/rest/request/module.go similarity index 59% rename from federation/rest/request/foobar.go rename to federation/rest/request/module.go index 33b23eac6..93d1f88ea 100644 --- a/federation/rest/request/foobar.go +++ b/federation/rest/request/module.go @@ -29,22 +29,33 @@ var ( type ( // Internal API interface - FoobarFoobar struct { + ModuleRead struct { + // ModuleID PATH parameter + // + // Module ID + ModuleID uint64 `json:",string"` } ) -// NewFoobarFoobar request -func NewFoobarFoobar() *FoobarFoobar { - return &FoobarFoobar{} +// NewModuleRead request +func NewModuleRead() *ModuleRead { + return &ModuleRead{} } // Auditable returns all auditable/loggable parameters -func (r FoobarFoobar) Auditable() map[string]interface{} { - return map[string]interface{}{} +func (r ModuleRead) Auditable() map[string]interface{} { + return map[string]interface{}{ + "moduleID": r.ModuleID, + } +} + +// Auditable returns all auditable/loggable parameters +func (r ModuleRead) GetModuleID() uint64 { + return r.ModuleID } // Fill processes request and fills internal variables -func (r *FoobarFoobar) Fill(req *http.Request) (err error) { +func (r *ModuleRead) Fill(req *http.Request) (err error) { if strings.ToLower(req.Header.Get("content-type")) == "application/json" { err = json.NewDecoder(req.Body).Decode(r) @@ -56,5 +67,17 @@ func (r *FoobarFoobar) Fill(req *http.Request) (err error) { } } + { + var val string + // path params + + val = chi.URLParam(req, "moduleID") + r.ModuleID, err = payload.ParseUint64(val), nil + if err != nil { + return err + } + + } + return err } diff --git a/federation/rest/router.go b/federation/rest/router.go index 38fec07cc..7bae14ec6 100644 --- a/federation/rest/router.go +++ b/federation/rest/router.go @@ -11,6 +11,9 @@ func MountRoutes(r chi.Router) { r.Group(func(r chi.Router) { handlers.NewPairRequest(NodePairRequest{}.New()).MountRoutes(r) }) + var ( + module = Module{}.New() + ) // Protect all _private_ routes r.Group(func(r chi.Router) { @@ -19,6 +22,6 @@ func MountRoutes(r chi.Router) { handlers.NewIdentity(NodeIdentity{}.New()).MountRoutes(r) handlers.NewPair(NodePair{}.New()).MountRoutes(r) - handlers.NewFoobar(Foobar{}.New()).MountRoutes(r) + handlers.NewModule(module).MountRoutes(r) }) } diff --git a/federation/service/module.go b/federation/service/module.go new file mode 100644 index 000000000..2ae216ce1 --- /dev/null +++ b/federation/service/module.go @@ -0,0 +1,37 @@ +package service + +import ( + "context" + + composeService "github.com/cortezaproject/corteza-server/compose/service" + composeTypes "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/federation/types" + "github.com/cortezaproject/corteza-server/store" +) + +type ( + module struct { + ctx context.Context + fetcher composeService.ModuleService + // actionlog actionlog.Recorder + // ac moduleAccessController + store store.Storable + } + + ModuleService interface { + Find(ctx context.Context, filter types.ModuleFilter) (composeTypes.ModuleSet, error) + } +) + +func Module() ModuleService { + return &module{ + ctx: context.Background(), + // ac: DefaultAccessControl, + // eventbus: eventbus.Service(), + store: composeService.DefaultNgStore, + } +} + +func (svc module) Find(ctx context.Context, filter types.ModuleFilter) (set composeTypes.ModuleSet, err error) { + return composeTypes.ModuleSet{}, nil +} diff --git a/federation/service/sync/structure.go b/federation/service/sync/structure.go new file mode 100644 index 000000000..edc4a48d6 --- /dev/null +++ b/federation/service/sync/structure.go @@ -0,0 +1,41 @@ +package sync + +import ( + "context" + + composeService "github.com/cortezaproject/corteza-server/compose/service" + composeTypes "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/federation/service" + "github.com/cortezaproject/corteza-server/federation/types" + "github.com/cortezaproject/corteza-server/store" +) + +type ( + module struct { + ctx context.Context + compose composeService.ModuleService + federation service.ModuleService + store store.Storable + } + + ModuleService interface { + FindForNode(ctx context.Context, filter types.ModuleFilter) (composeTypes.ModuleSet, error) + } +) + +func Module() ModuleService { + return &module{ + ctx: context.Background(), + store: composeService.DefaultNgStore, + compose: composeService.Module(), + federation: service.Module(), + } +} + +func (svc module) FindForNode(ctx context.Context, filter types.ModuleFilter) (set composeTypes.ModuleSet, err error) { + // get all modules per-node + // feed the id's into the compose moduleservice + // get the data + // transform (but not here) + return composeTypes.ModuleSet{}, nil +} diff --git a/federation/types/module.go b/federation/types/module.go new file mode 100644 index 000000000..fa7bfa536 --- /dev/null +++ b/federation/types/module.go @@ -0,0 +1,7 @@ +package types + +type ( + ModuleFilter struct { + Node string `json:"node"` + } +)