3
0

Add route to list dal connections for privacy console

It will only list dal connections with minimal data.
This commit is contained in:
Vivek Patel
2022-08-03 16:32:16 +05:30
parent 12fd426ec7
commit db325fc125
11 changed files with 512 additions and 5 deletions

View File

@@ -2268,3 +2268,31 @@ endpoints:
post:
- { name: comment, type: "string", title: "Comment description", required: true }
- title: Data Privacy
entrypoint: dataPrivacy
imports:
- github.com/cortezaproject/corteza-server/pkg/filter
path: "/data-privacy"
apis:
- name: connection list
method: GET
title: List connections for data privacy
path: "/connection/"
parameters:
get:
- name: connectionID
type: "[]string"
required: false
title: Filter by connection ID
- type: string
name: handle
required: false
title: Search handle to match against connections
- type: string
name: type
required: false
title: Search type to match against connections
- name: deleted
required: false
title: Exclude (0, default), include (1) or return only (2) deleted connections
type: filter.State

View File

@@ -0,0 +1,63 @@
package rest
import (
"context"
"github.com/cortezaproject/corteza-server/pkg/payload"
"github.com/cortezaproject/corteza-server/system/rest/request"
"github.com/cortezaproject/corteza-server/system/service"
"github.com/cortezaproject/corteza-server/system/types"
)
type (
DataPrivacy struct {
privacy service.DataPrivacyService
ac privacyAccessController
}
privacyAccessController interface {
CanGrant(context.Context) bool
}
privacyConnectionSetPayload struct {
Filter types.DalConnectionFilter `json:"filter"`
Set types.PrivacyDalConnectionSet `json:"set"`
}
)
func (DataPrivacy) New() *DataPrivacy {
return &DataPrivacy{
privacy: service.DefaultDataPrivacy,
ac: service.DefaultAccessControl,
}
}
func (ctrl DataPrivacy) ConnectionList(ctx context.Context, r *request.DataPrivacyConnectionList) (interface{}, error) {
var (
err error
set types.PrivacyDalConnectionSet
f = types.DalConnectionFilter{
ConnectionID: payload.ParseUint64s(r.ConnectionID),
Handle: r.Handle,
Type: r.Type,
Deleted: r.Deleted,
}
)
set, f, err = ctrl.privacy.FindConnections(ctx, f)
return ctrl.makeFilterConnectionPayload(ctx, set, f, err)
}
func (ctrl DataPrivacy) makeFilterConnectionPayload(_ context.Context, rr types.PrivacyDalConnectionSet, f types.DalConnectionFilter, err error) (*privacyConnectionSetPayload, error) {
if err != nil {
return nil, err
}
if len(rr) == 0 {
rr = make([]*types.PrivacyDalConnection, 0)
}
return &privacyConnectionSetPayload{Filter: f, Set: rr}, nil
}

View File

@@ -0,0 +1,57 @@
package handlers
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
//
import (
"context"
"github.com/cortezaproject/corteza-server/pkg/api"
"github.com/cortezaproject/corteza-server/system/rest/request"
"github.com/go-chi/chi/v5"
"net/http"
)
type (
// Internal API interface
DataPrivacyAPI interface {
ConnectionList(context.Context, *request.DataPrivacyConnectionList) (interface{}, error)
}
// HTTP API interface
DataPrivacy struct {
ConnectionList func(http.ResponseWriter, *http.Request)
}
)
func NewDataPrivacy(h DataPrivacyAPI) *DataPrivacy {
return &DataPrivacy{
ConnectionList: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewDataPrivacyConnectionList()
if err := params.Fill(r); err != nil {
api.Send(w, r, err)
return
}
value, err := h.ConnectionList(r.Context(), params)
if err != nil {
api.Send(w, r, err)
return
}
api.Send(w, r, value)
},
}
}
func (h DataPrivacy) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) {
r.Group(func(r chi.Router) {
r.Use(middlewares...)
r.Get("/data-privacy/connection/", h.ConnectionList)
})
}

View File

@@ -0,0 +1,134 @@
package request
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
//
import (
"encoding/json"
"fmt"
"github.com/cortezaproject/corteza-server/pkg/filter"
"github.com/cortezaproject/corteza-server/pkg/payload"
"github.com/go-chi/chi/v5"
"io"
"mime/multipart"
"net/http"
"strings"
)
// dummy vars to prevent
// unused imports complain
var (
_ = chi.URLParam
_ = multipart.ErrMessageTooLarge
_ = payload.ParseUint64s
_ = strings.ToLower
_ = io.EOF
_ = fmt.Errorf
_ = json.NewEncoder
)
type (
// Internal API interface
DataPrivacyConnectionList struct {
// ConnectionID GET parameter
//
// Filter by connection ID
ConnectionID []string
// Handle GET parameter
//
// Search handle to match against connections
Handle string
// Type GET parameter
//
// Search type to match against connections
Type string
// Deleted GET parameter
//
// Exclude (0, default), include (1) or return only (2) deleted connections
Deleted filter.State
}
)
// NewDataPrivacyConnectionList request
func NewDataPrivacyConnectionList() *DataPrivacyConnectionList {
return &DataPrivacyConnectionList{}
}
// Auditable returns all auditable/loggable parameters
func (r DataPrivacyConnectionList) Auditable() map[string]interface{} {
return map[string]interface{}{
"connectionID": r.ConnectionID,
"handle": r.Handle,
"type": r.Type,
"deleted": r.Deleted,
}
}
// Auditable returns all auditable/loggable parameters
func (r DataPrivacyConnectionList) GetConnectionID() []string {
return r.ConnectionID
}
// Auditable returns all auditable/loggable parameters
func (r DataPrivacyConnectionList) GetHandle() string {
return r.Handle
}
// Auditable returns all auditable/loggable parameters
func (r DataPrivacyConnectionList) GetType() string {
return r.Type
}
// Auditable returns all auditable/loggable parameters
func (r DataPrivacyConnectionList) GetDeleted() filter.State {
return r.Deleted
}
// Fill processes request and fills internal variables
func (r *DataPrivacyConnectionList) Fill(req *http.Request) (err error) {
{
// GET params
tmp := req.URL.Query()
if val, ok := tmp["connectionID[]"]; ok {
r.ConnectionID, err = val, nil
if err != nil {
return err
}
} else if val, ok := tmp["connectionID"]; ok {
r.ConnectionID, err = val, nil
if err != nil {
return err
}
}
if val, ok := tmp["handle"]; ok && len(val) > 0 {
r.Handle, err = val[0], nil
if err != nil {
return err
}
}
if val, ok := tmp["type"]; ok && len(val) > 0 {
r.Type, err = val[0], nil
if err != nil {
return err
}
}
if val, ok := tmp["deleted"]; ok && len(val) > 0 {
r.Deleted, err = payload.ParseFilterState(val[0]), nil
if err != nil {
return err
}
}
}
return err
}

View File

@@ -47,6 +47,8 @@ func MountRoutes() func(r chi.Router) {
handlers.NewApigwRoute(ApigwRoute{}.New()).MountRoutes(r)
handlers.NewApigwFilter(ApigwFilter{}.New()).MountRoutes(r)
handlers.NewApigwProfiler(ApigwProfiler{}.New()).MountRoutes(r)
handlers.NewDataPrivacy(DataPrivacy{}.New()).MountRoutes(r)
// @todo move these two to dataPrivacy routes
handlers.NewDataPrivacyRequest(DataPrivacyRequest{}.New()).MountRoutes(r)
handlers.NewDataPrivacyRequestComment(DataPrivacyRequestComment{}.New()).MountRoutes(r)
})

View File

@@ -13,11 +13,11 @@ import (
type (
dataPrivacy struct {
actionlog actionlog.Recorder
store store.Storer
ac dataPrivacyAccessController
eventbus eventDispatcher
store store.Storer
dalConn dalConnectionService
}
dataPrivacyAccessController interface {
@@ -25,9 +25,17 @@ type (
CanCreateDataPrivacyRequest(context.Context) bool
CanReadDataPrivacyRequest(context.Context, *types.DataPrivacyRequest) bool
CanApproveDataPrivacyRequest(context.Context, *types.DataPrivacyRequest) bool
CanSearchDalConnections(context.Context) bool
}
dalConnectionService interface {
Search(ctx context.Context, filter types.DalConnectionFilter) (r types.DalConnectionSet, f types.DalConnectionFilter, err error)
}
DataPrivacyService interface {
FindConnections(ctx context.Context, filter types.DalConnectionFilter) (out types.PrivacyDalConnectionSet, f types.DalConnectionFilter, err error)
FindRequestByID(ctx context.Context, requestID uint64) (*types.DataPrivacyRequest, error)
FindRequests(context.Context, types.DataPrivacyRequestFilter) (types.DataPrivacyRequestSet, types.DataPrivacyRequestFilter, error)
CreateRequest(ctx context.Context, request *types.DataPrivacyRequest) (*types.DataPrivacyRequest, error)
@@ -41,12 +49,55 @@ type (
func DataPrivacy(s store.Storer, ac dataPrivacyAccessController, al actionlog.Recorder, eb eventDispatcher) *dataPrivacy {
return &dataPrivacy{
actionlog: al,
store: s,
ac: ac,
eventbus: eb,
store: s,
}
}
func (svc dataPrivacy) FindConnections(ctx context.Context, filter types.DalConnectionFilter) (out types.PrivacyDalConnectionSet, f types.DalConnectionFilter, err error) {
var (
cc types.DalConnectionSet
)
err = func() error {
if !svc.ac.CanSearchDalConnections(ctx) {
return DalConnectionErrNotAllowedToSearch()
}
cc, f, err = svc.dalConn.Search(ctx, filter)
if err != nil {
return err
}
err = cc.Walk(func(c *types.DalConnection) error {
pc := types.PrivacyDalConnection{
ID: c.ID,
Name: c.Meta.Name,
Handle: c.Handle,
Type: c.Type,
Location: c.Meta.Location,
Ownership: c.Meta.Ownership,
SensitivityLevel: c.Config.Privacy.SensitivityLevelID,
CreatedAt: c.CreatedAt,
CreatedBy: c.CreatedBy,
UpdatedAt: c.UpdatedAt,
UpdatedBy: c.UpdatedBy,
DeletedAt: c.DeletedAt,
DeletedBy: c.DeletedBy,
}
out = append(out, &pc)
return nil
})
if err != nil {
return err
}
return nil
}()
return
}
func (svc dataPrivacy) FindRequestByID(ctx context.Context, requestID uint64) (r *types.DataPrivacyRequest, err error) {
var (
raProps = &dataPrivacyActionProps{dataPrivacyRequest: &types.DataPrivacyRequest{ID: requestID}}

View File

@@ -28,9 +28,9 @@ type (
CreatedAt time.Time `json:"createdAt,omitempty"`
CreatedBy uint64 `json:"createdBy,string" `
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
UpdatedBy uint64 `json:"updatedBy,string,omitempty" `
UpdatedBy uint64 `json:"updatedBy,string,omitempty"`
DeletedAt *time.Time `json:"deletedAt,omitempty"`
DeletedBy uint64 `json:"deletedBy,string,omitempty" `
DeletedBy uint64 `json:"deletedBy,string,omitempty"`
}
ConnectionConfig struct {

View File

@@ -3,6 +3,7 @@ package types
import (
"database/sql/driver"
"encoding/json"
"github.com/cortezaproject/corteza-server/pkg/geolocation"
"github.com/cortezaproject/corteza-server/pkg/sql"
"time"
@@ -99,6 +100,25 @@ type (
filter.Paging
}
PrivacyDalConnection struct {
ID uint64 `json:"connectionID,string"`
Name string `json:"name"`
Handle string `json:"handle"`
Type string `json:"type"`
Location geolocation.Full `json:"location"`
Ownership string `json:"ownership"`
SensitivityLevel uint64 `json:"sensitivityLevel,string,omitempty"`
CreatedAt time.Time `json:"createdAt,omitempty"`
CreatedBy uint64 `json:"createdBy,string" `
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
UpdatedBy uint64 `json:"updatedBy,string,omitempty" `
DeletedAt *time.Time `json:"deletedAt,omitempty"`
DeletedBy uint64 `json:"deletedBy,string,omitempty" `
}
RequestStatus string
RequestKind string
)

View File

@@ -85,6 +85,11 @@ type (
// This type is auto-generated.
DataPrivacyRequestCommentSet []*DataPrivacyRequestComment
// PrivacyDalConnectionSet slice of PrivacyDalConnection
//
// This type is auto-generated.
PrivacyDalConnectionSet []*PrivacyDalConnection
// QueueSet slice of Queue
//
// This type is auto-generated.
@@ -872,6 +877,62 @@ func (set DataPrivacyRequestCommentSet) IDs() (IDs []uint64) {
return
}
// Walk iterates through every slice item and calls w(PrivacyDalConnection) err
//
// This function is auto-generated.
func (set PrivacyDalConnectionSet) Walk(w func(*PrivacyDalConnection) error) (err error) {
for i := range set {
if err = w(set[i]); err != nil {
return
}
}
return
}
// Filter iterates through every slice item, calls f(PrivacyDalConnection) (bool, err) and return filtered slice
//
// This function is auto-generated.
func (set PrivacyDalConnectionSet) Filter(f func(*PrivacyDalConnection) (bool, error)) (out PrivacyDalConnectionSet, err error) {
var ok bool
out = PrivacyDalConnectionSet{}
for i := range set {
if ok, err = f(set[i]); err != nil {
return
} else if ok {
out = append(out, set[i])
}
}
return
}
// FindByID finds items from slice by its ID property
//
// This function is auto-generated.
func (set PrivacyDalConnectionSet) FindByID(ID uint64) *PrivacyDalConnection {
for i := range set {
if set[i].ID == ID {
return set[i]
}
}
return nil
}
// IDs returns a slice of uint64s from all items in the set
//
// This function is auto-generated.
func (set PrivacyDalConnectionSet) IDs() (IDs []uint64) {
IDs = make([]uint64, len(set))
for i := range set {
IDs[i] = set[i].ID
}
return
}
// Walk iterates through every slice item and calls w(Queue) err
//
// This function is auto-generated.

View File

@@ -1228,6 +1228,96 @@ func TestDataPrivacyRequestCommentSetIDs(t *testing.T) {
}
}
func TestPrivacyDalConnectionSetWalk(t *testing.T) {
var (
value = make(PrivacyDalConnectionSet, 3)
req = require.New(t)
)
// check walk with no errors
{
err := value.Walk(func(*PrivacyDalConnection) error {
return nil
})
req.NoError(err)
}
// check walk with error
req.Error(value.Walk(func(*PrivacyDalConnection) error { return fmt.Errorf("walk error") }))
}
func TestPrivacyDalConnectionSetFilter(t *testing.T) {
var (
value = make(PrivacyDalConnectionSet, 3)
req = require.New(t)
)
// filter nothing
{
set, err := value.Filter(func(*PrivacyDalConnection) (bool, error) {
return true, nil
})
req.NoError(err)
req.Equal(len(set), len(value))
}
// filter one item
{
found := false
set, err := value.Filter(func(*PrivacyDalConnection) (bool, error) {
if !found {
found = true
return found, nil
}
return false, nil
})
req.NoError(err)
req.Len(set, 1)
}
// filter error
{
_, err := value.Filter(func(*PrivacyDalConnection) (bool, error) {
return false, fmt.Errorf("filter error")
})
req.Error(err)
}
}
func TestPrivacyDalConnectionSetIDs(t *testing.T) {
var (
value = make(PrivacyDalConnectionSet, 3)
req = require.New(t)
)
// construct objects
value[0] = new(PrivacyDalConnection)
value[1] = new(PrivacyDalConnection)
value[2] = new(PrivacyDalConnection)
// set ids
value[0].ID = 1
value[1].ID = 2
value[2].ID = 3
// Find existing
{
val := value.FindByID(2)
req.Equal(uint64(2), val.ID)
}
// Find non-existing
{
val := value.FindByID(4)
req.Nil(val)
}
// List IDs from set
{
val := value.IDs()
req.Equal(len(val), len(value))
}
}
func TestQueueSetWalk(t *testing.T) {
var (
value = make(QueueSet, 3)

View File

@@ -37,3 +37,4 @@ types:
noIdField: true
DataPrivacyRequest: {}
DataPrivacyRequestComment: {}
PrivacyDalConnection: