influxdb/authorizer/annotation.go

190 lines
6.9 KiB
Go

package authorizer
import (
"context"
"fmt"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/kit/platform"
"github.com/influxdata/influxdb/v2/kit/platform/errors"
)
var _ influxdb.AnnotationService = (*AnnotationService)(nil)
// AnnotationService wraps an influxdb.AnnotationService and authorizes actions
// against it appropriately.
type AnnotationService struct {
s influxdb.AnnotationService
}
// NewAnnotationService constructs an instance of an authorizing check service
func NewAnnotationService(s influxdb.AnnotationService) *AnnotationService {
return &AnnotationService{
s: s,
}
}
// CreateAnnotations checks to see if the authorizer on context has write access for annotations for the provided orgID
func (s *AnnotationService) CreateAnnotations(ctx context.Context, orgID platform.ID, create []influxdb.AnnotationCreate) ([]influxdb.AnnotationEvent, error) {
if _, _, err := AuthorizeCreate(ctx, influxdb.AnnotationsResourceType, orgID); err != nil {
return nil, err
}
return s.s.CreateAnnotations(ctx, orgID, create)
}
// ListAnnotations checks to see if the authorizer on context has read access for annotations for the provided orgID
// and then filters the list down to only the resources that are authorized
func (s *AnnotationService) ListAnnotations(ctx context.Context, orgID platform.ID, filter influxdb.AnnotationListFilter) ([]influxdb.StoredAnnotation, error) {
if _, _, err := AuthorizeOrgReadResource(ctx, influxdb.AnnotationsResourceType, orgID); err != nil {
return nil, err
}
as, err := s.s.ListAnnotations(ctx, orgID, filter)
if err != nil {
return nil, err
}
as, _, err = AuthorizeFindAnnotations(ctx, as)
return as, err
}
// GetAnnotation checks to see if the authorizer on context has read access to the requested annotation
func (s *AnnotationService) GetAnnotation(ctx context.Context, id platform.ID) (*influxdb.StoredAnnotation, error) {
a, err := s.s.GetAnnotation(ctx, id)
if err != nil {
return nil, err
}
if _, _, err := AuthorizeRead(ctx, influxdb.AnnotationsResourceType, id, a.OrgID); err != nil {
return nil, err
}
return a, nil
}
// DeleteAnnotations checks to see if the authorizer on context has write access to the provided orgID
func (s *AnnotationService) DeleteAnnotations(ctx context.Context, orgID platform.ID, delete influxdb.AnnotationDeleteFilter) error {
if _, _, err := AuthorizeOrgWriteResource(ctx, influxdb.AnnotationsResourceType, orgID); err != nil {
return err
}
return s.s.DeleteAnnotations(ctx, orgID, delete)
}
// DeleteAnnotation checks to see if the authorizer on context has write access to the requested annotation
func (s *AnnotationService) DeleteAnnotation(ctx context.Context, id platform.ID) error {
a, err := s.s.GetAnnotation(ctx, id)
if err != nil {
return err
}
if _, _, err := AuthorizeWrite(ctx, influxdb.AnnotationsResourceType, id, a.OrgID); err != nil {
return err
}
return s.s.DeleteAnnotation(ctx, id)
}
// UpdateAnnotation checks to see if the authorizer on context has write access to the requested annotation
func (s *AnnotationService) UpdateAnnotation(ctx context.Context, id platform.ID, update influxdb.AnnotationCreate) (*influxdb.AnnotationEvent, error) {
a, err := s.s.GetAnnotation(ctx, id)
if err != nil {
return nil, err
}
if _, _, err := AuthorizeWrite(ctx, influxdb.AnnotationsResourceType, id, a.OrgID); err != nil {
return nil, err
}
return s.s.UpdateAnnotation(ctx, id, update)
}
// ListStreams checks to see if the authorizer on context has read access for streams for the provided orgID
// and then filters the list down to only the resources that are authorized
func (s *AnnotationService) ListStreams(ctx context.Context, orgID platform.ID, filter influxdb.StreamListFilter) ([]influxdb.StoredStream, error) {
if _, _, err := AuthorizeOrgReadResource(ctx, influxdb.AnnotationsResourceType, orgID); err != nil {
return nil, err
}
ss, err := s.s.ListStreams(ctx, orgID, filter)
if err != nil {
return nil, err
}
ss, _, err = AuthorizeFindStreams(ctx, ss)
return ss, err
}
// GetStream checks to see if the authorizer on context has read access to the requested stream
func (s *AnnotationService) GetStream(ctx context.Context, id platform.ID) (*influxdb.StoredStream, error) {
st, err := s.s.GetStream(ctx, id)
if err != nil {
return nil, err
}
if _, _, err := AuthorizeRead(ctx, influxdb.AnnotationsResourceType, id, st.OrgID); err != nil {
return nil, err
}
return st, nil
}
func (s *AnnotationService) CreateOrUpdateStream(ctx context.Context, orgID platform.ID, stream influxdb.Stream) (*influxdb.ReadStream, error) {
// We need to know if the request is creating a new stream, or updating an existing stream to check
// permissions appropriately
// Get the stream by name. An empty slice will be returned if the stream doesn't exist
// note: a given org can only have one stream by the same name. this constraint is enforced in the database schema
streams, err := s.s.ListStreams(ctx, orgID, influxdb.StreamListFilter{
StreamIncludes: []string{stream.Name},
})
if err != nil {
return nil, err
}
// update an already existing stream
if len(streams) == 1 {
return s.UpdateStream(ctx, streams[0].ID, stream)
}
// create a new stream if one doesn't already exist
if len(streams) == 0 {
if _, _, err := AuthorizeCreate(ctx, influxdb.AnnotationsResourceType, orgID); err != nil {
return nil, err
}
return s.s.CreateOrUpdateStream(ctx, orgID, stream)
}
// if multiple streams were returned somehow, return an error
// this should never happen, so return a server error
return nil, &errors.Error{
Code: errors.EInternal,
Msg: fmt.Sprintf("more than one stream named %q for org %q", streams[0].Name, orgID),
}
}
// UpdateStream checks to see if the authorizer on context has write access to the requested stream
func (s *AnnotationService) UpdateStream(ctx context.Context, id platform.ID, stream influxdb.Stream) (*influxdb.ReadStream, error) {
st, err := s.s.GetStream(ctx, id)
if err != nil {
return nil, err
}
if _, _, err := AuthorizeWrite(ctx, influxdb.AnnotationsResourceType, id, st.OrgID); err != nil {
return nil, err
}
return s.s.UpdateStream(ctx, id, stream)
}
// DeleteStreams checks to see if the authorizer on context has write access to the provided orgID
func (s *AnnotationService) DeleteStreams(ctx context.Context, orgID platform.ID, delete influxdb.BasicStream) error {
if _, _, err := AuthorizeOrgWriteResource(ctx, influxdb.AnnotationsResourceType, orgID); err != nil {
return err
}
return s.s.DeleteStreams(ctx, orgID, delete)
}
// DeleteStreamByID checks to see if the authorizer on context has write access to the requested stream
func (s *AnnotationService) DeleteStreamByID(ctx context.Context, id platform.ID) error {
st, err := s.s.GetStream(ctx, id)
if err != nil {
return err
}
if _, _, err := AuthorizeWrite(ctx, influxdb.AnnotationsResourceType, id, st.OrgID); err != nil {
return err
}
return s.s.DeleteStreamByID(ctx, id)
}