Files
upstream-corteza/server/system/service/data_privacy.go
upstream-mirror 7e385fc126
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
snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
2026-09-18 01:22:23 +05:00

297 lines
8.2 KiB
Go

package service
import (
"context"
"github.com/cortezaproject/corteza/server/pkg/actionlog"
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/service/event"
"github.com/cortezaproject/corteza/server/system/types"
)
type (
dataPrivacy struct {
actionlog actionlog.Recorder
store store.Storer
ac dataPrivacyAccessController
eventbus eventDispatcher
dalConn dalConnectionService
}
dataPrivacyAccessController interface {
CanSearchDataPrivacyRequests(context.Context) bool
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)
UpdateRequestStatus(ctx context.Context, request *types.DataPrivacyRequest) (*types.DataPrivacyRequest, error)
FindRequestComments(ctx context.Context, filter types.DataPrivacyRequestCommentFilter) (rr types.DataPrivacyRequestCommentSet, f types.DataPrivacyRequestCommentFilter, err error)
CreateRequestComment(ctx context.Context, new *types.DataPrivacyRequestComment) (r *types.DataPrivacyRequestComment, err error)
}
)
func DataPrivacy(s store.Storer, ac dataPrivacyAccessController, al actionlog.Recorder, eb eventDispatcher) *dataPrivacy {
return &dataPrivacy{
actionlog: al,
store: s,
ac: ac,
eventbus: eb,
dalConn: DefaultDalConnection,
}
}
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 cc, f, err = store.SearchDalConnections(ctx, svc.store, filter); err != nil {
return err
}
err = cc.Walk(func(c *types.DalConnection) error {
pc := types.PrivacyDalConnection{
ID: c.ID,
Handle: c.Handle,
Type: c.Type,
Meta: types.PrivacyDalConnectionMeta{
Name: c.Meta.Name,
Ownership: c.Meta.Ownership,
Location: c.Meta.Location,
},
Config: types.PrivacyDalConnectionConfig{
Privacy: c.Config.Privacy,
},
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}}
)
err = func() error {
r, err = loadDataPrivacyRequest(ctx, svc.store, requestID)
if r, err = svc.procRequest(ctx, r, err); err != nil {
return err
}
raProps.setDataPrivacyRequest(r)
if !svc.ac.CanReadDataPrivacyRequest(ctx, r) {
return DataPrivacyErrNotAllowedToRead()
}
return nil
}()
return r, svc.recordAction(ctx, raProps, DataPrivacyActionLookup, err)
}
func (svc dataPrivacy) procRequest(_ context.Context, r *types.DataPrivacyRequest, err error) (*types.DataPrivacyRequest, error) {
if err != nil {
if errors.IsNotFound(err) {
return nil, DataPrivacyErrNotFound()
}
return nil, err
}
return r, nil
}
func (svc dataPrivacy) FindRequests(ctx context.Context, filter types.DataPrivacyRequestFilter) (rr types.DataPrivacyRequestSet, f types.DataPrivacyRequestFilter, err error) {
var (
raProps = &dataPrivacyActionProps{filter: &filter}
)
// For each fetched item, store backend will check if it is valid or not
filter.Check = func(req *types.DataPrivacyRequest) (bool, error) {
if !svc.ac.CanReadDataPrivacyRequest(ctx, req) {
return false, nil
}
return true, nil
}
err = func() error {
if !svc.ac.CanSearchDataPrivacyRequests(ctx) {
return DataPrivacyErrNotAllowedToSearch()
}
if rr, f, err = store.SearchDataPrivacyRequests(ctx, svc.store, filter); err != nil {
return err
}
return nil
}()
return rr, f, svc.recordAction(ctx, raProps, DataPrivacyActionSearch, err)
}
func (svc dataPrivacy) CreateRequest(ctx context.Context, new *types.DataPrivacyRequest) (r *types.DataPrivacyRequest, err error) {
var (
raProps = &dataPrivacyActionProps{new: new}
)
err = func() (err error) {
if len(new.Kind.String()) == 0 {
return DataPrivacyErrInvalidKind()
}
if !svc.ac.CanCreateDataPrivacyRequest(ctx) {
return DataPrivacyErrNotAllowedToCreate()
}
if err = svc.eventbus.WaitFor(ctx, event.DataPrivacyRequestBeforeCreate(new, r)); err != nil {
return
}
new.ID = nextID()
new.Status = types.RequestStatusPending
new.RequestedAt = *now()
new.RequestedBy = a.GetIdentityFromContext(ctx).Identity()
new.CreatedAt = *now()
if err = store.CreateDataPrivacyRequest(ctx, svc.store, new); err != nil {
return
}
r = new
svc.eventbus.Dispatch(ctx, event.DataPrivacyRequestAfterCreate(new, r))
return
}()
return r, svc.recordAction(ctx, raProps, DataPrivacyActionCreate, err)
}
func (svc dataPrivacy) UpdateRequestStatus(ctx context.Context, upd *types.DataPrivacyRequest) (r *types.DataPrivacyRequest, err error) {
var (
raProps = &dataPrivacyActionProps{update: upd}
)
err = func() (err error) {
if len(upd.Status.String()) == 0 {
return DataPrivacyErrInvalidStatus()
}
if upd.Status == types.RequestStatusPending {
return DataPrivacyErrInvalidStatus()
}
if upd.Status == types.RequestStatusApproved || upd.Status == types.RequestStatusRejected {
if !svc.ac.CanApproveDataPrivacyRequest(ctx, upd) {
return DataPrivacyErrNotAllowedToApprove()
}
}
if r, err = loadDataPrivacyRequest(ctx, svc.store, upd.ID); err != nil {
return
}
raProps.setDataPrivacyRequest(r)
if err = svc.eventbus.WaitFor(ctx, event.DataPrivacyRequestBeforeUpdate(upd, r)); err != nil {
return
}
r.Status = upd.Status
r.CompletedAt = now()
r.CompletedBy = a.GetIdentityFromContext(ctx).Identity()
r.UpdatedAt = now()
// Assign changed values
if err = store.UpdateDataPrivacyRequest(ctx, svc.store, r); err != nil {
return err
}
svc.eventbus.Dispatch(ctx, event.DataPrivacyRequestAfterUpdate(upd, r))
return nil
}()
return r, svc.recordAction(ctx, raProps, DataPrivacyActionApprove, err)
}
func (svc dataPrivacy) FindRequestComments(ctx context.Context, filter types.DataPrivacyRequestCommentFilter) (rr types.DataPrivacyRequestCommentSet, f types.DataPrivacyRequestCommentFilter, err error) {
err = func() error {
if rr, f, err = store.SearchDataPrivacyRequestComments(ctx, svc.store, filter); err != nil {
return err
}
return nil
}()
return rr, f, err
}
func (svc dataPrivacy) CreateRequestComment(ctx context.Context, new *types.DataPrivacyRequestComment) (r *types.DataPrivacyRequestComment, err error) {
err = func() (err error) {
_, err = svc.FindRequestByID(ctx, new.RequestID)
if err != nil {
return
}
new.ID = nextID()
new.CreatedBy = a.GetIdentityFromContext(ctx).Identity()
new.CreatedAt = *now()
if err = store.CreateDataPrivacyRequestComment(ctx, svc.store, new); err != nil {
return
}
r = new
return
}()
return r, err
}
func loadDataPrivacyRequest(ctx context.Context, s store.DataPrivacyRequests, ID uint64) (res *types.DataPrivacyRequest, err error) {
if ID == 0 {
return nil, DataPrivacyErrInvalidID()
}
if res, err = store.LookupDataPrivacyRequestByID(ctx, s, ID); errors.IsNotFound(err) {
return nil, DataPrivacyErrNotFound()
}
return
}