diff --git a/federation/rest.yaml b/federation/rest.yaml index 267ed431e..255b7dc6a 100644 --- a/federation/rest.yaml +++ b/federation/rest.yaml @@ -69,6 +69,13 @@ endpoints: required: false title: Pairing URI + - name: read + method: GET + title: Read a federation node + path: "/{nodeID}" + parameters: + path: [ { name: nodeID, type: uint64, required: true, title: NodeID } ] + - name: generateURI method: POST title: Creates new sharable federation URI diff --git a/federation/rest/handlers/node.go b/federation/rest/handlers/node.go index 1ff7a02a4..932783326 100644 --- a/federation/rest/handlers/node.go +++ b/federation/rest/handlers/node.go @@ -23,6 +23,7 @@ type ( NodeAPI interface { Search(context.Context, *request.NodeSearch) (interface{}, error) Create(context.Context, *request.NodeCreate) (interface{}, error) + Read(context.Context, *request.NodeRead) (interface{}, error) GenerateURI(context.Context, *request.NodeGenerateURI) (interface{}, error) Update(context.Context, *request.NodeUpdate) (interface{}, error) Delete(context.Context, *request.NodeDelete) (interface{}, error) @@ -36,6 +37,7 @@ type ( Node struct { Search func(http.ResponseWriter, *http.Request) Create func(http.ResponseWriter, *http.Request) + Read func(http.ResponseWriter, *http.Request) GenerateURI func(http.ResponseWriter, *http.Request) Update func(http.ResponseWriter, *http.Request) Delete func(http.ResponseWriter, *http.Request) @@ -88,6 +90,26 @@ func NewNode(h NodeAPI) *Node { resputil.JSON(w, value) } }, + Read: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewNodeRead() + if err := params.Fill(r); err != nil { + logger.LogParamError("Node.Read", r, err) + resputil.JSON(w, err) + return + } + + value, err := h.Read(r.Context(), params) + if err != nil { + logger.LogControllerError("Node.Read", r, err, params.Auditable()) + resputil.JSON(w, err) + return + } + logger.LogControllerCall("Node.Read", r, params.Auditable()) + if !serveHTTP(value, w, r) { + resputil.JSON(w, value) + } + }, GenerateURI: func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() params := request.NewNodeGenerateURI() @@ -236,6 +258,7 @@ func (h Node) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.H r.Use(middlewares...) r.Get("/nodes/", h.Search) r.Post("/nodes/", h.Create) + r.Get("/nodes/{nodeID}", h.Read) r.Post("/nodes/{nodeID}/uri", h.GenerateURI) r.Post("/nodes/{nodeID}", h.Update) r.Delete("/nodes/{nodeID}", h.Delete) diff --git a/federation/rest/node.go b/federation/rest/node.go index f82a572e9..8aaaa4077 100644 --- a/federation/rest/node.go +++ b/federation/rest/node.go @@ -2,6 +2,7 @@ package rest import ( "context" + "github.com/cortezaproject/corteza-server/federation/rest/request" "github.com/cortezaproject/corteza-server/federation/service" "github.com/cortezaproject/corteza-server/federation/types" @@ -13,6 +14,7 @@ type ( Search(ctx context.Context, f types.NodeFilter) (types.NodeSet, types.NodeFilter, error) Create(ctx context.Context, n *types.Node) (*types.Node, error) CreateFromPairingURI(ctx context.Context, uri string) (*types.Node, error) + Read(ctx context.Context, ID uint64) (*types.Node, error) Update(ctx context.Context, n *types.Node) (*types.Node, error) DeleteByID(ctx context.Context, ID uint64) error UndeleteByID(ctx context.Context, ID uint64) error @@ -67,6 +69,11 @@ func (ctrl Node) Create(ctx context.Context, r *request.NodeCreate) (interface{} } } +func (ctrl Node) Read(ctx context.Context, r *request.NodeRead) (interface{}, error) { + n, err := ctrl.svcNode.Read(ctx, r.NodeID) + + return ctrl.makePayload(ctx, n, err) +} func (ctrl Node) Update(ctx context.Context, r *request.NodeUpdate) (interface{}, error) { n, err := ctrl.svcNode.Update(ctx, &types.Node{ ID: r.NodeID, diff --git a/federation/rest/request/node.go b/federation/rest/request/node.go index 0d6c22900..d2504c0a3 100644 --- a/federation/rest/request/node.go +++ b/federation/rest/request/node.go @@ -58,6 +58,13 @@ type ( PairingURI string } + NodeRead struct { + // NodeID PATH parameter + // + // NodeID + NodeID uint64 `json:",string"` + } + NodeGenerateURI struct { // NodeID PATH parameter // @@ -254,6 +261,51 @@ func (r *NodeCreate) Fill(req *http.Request) (err error) { return err } +// NewNodeRead request +func NewNodeRead() *NodeRead { + return &NodeRead{} +} + +// Auditable returns all auditable/loggable parameters +func (r NodeRead) Auditable() map[string]interface{} { + return map[string]interface{}{ + "nodeID": r.NodeID, + } +} + +// Auditable returns all auditable/loggable parameters +func (r NodeRead) GetNodeID() uint64 { + return r.NodeID +} + +// Fill processes request and fills internal variables +func (r *NodeRead) 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 fmt.Errorf("error parsing http request body: %w", err) + } + } + + { + var val string + // path params + + val = chi.URLParam(req, "nodeID") + r.NodeID, err = payload.ParseUint64(val), nil + if err != nil { + return err + } + + } + + return err +} + // NewNodeGenerateURI request func NewNodeGenerateURI() *NodeGenerateURI { return &NodeGenerateURI{} diff --git a/federation/service/node.go b/federation/service/node.go index bbe637cbf..8a452f71a 100644 --- a/federation/service/node.go +++ b/federation/service/node.go @@ -107,6 +107,16 @@ func (svc node) Create(ctx context.Context, new *types.Node) (*types.Node, error return n, svc.recordAction(ctx, aProps, NodeActionCreate, err) } +// Read is used mainly in UI, when retrieving details about the node +func (svc node) Read(ctx context.Context, ID uint64) (*types.Node, error) { + var ( + n, err = store.LookupFederationNodeByID(ctx, svc.store, ID) + aProps = &nodeActionProps{node: n} + ) + + return n, svc.recordAction(ctx, aProps, NodeActionCreate, err) +} + // CreateFromURI is used on server B to create federation with server A func (svc node) CreateFromPairingURI(ctx context.Context, uri string) (n *types.Node, err error) { var (