influxdb/kv/document_options.go

217 lines
5.1 KiB
Go

package kv
import (
"context"
"fmt"
"github.com/influxdata/influxdb/v2"
)
// DocumentIndex implements influxdb.DocumentIndex. It is used to access labels/owners of documents.
type DocumentIndex struct {
service *Service
namespace string
ctx context.Context
tx Tx
writable bool
}
// FindLabelByID retrieves a label by id.
func (i *DocumentIndex) FindLabelByID(id influxdb.ID) error {
_, err := i.service.findLabelByID(i.ctx, i.tx, id)
return err
}
// UsersOrgs retrieves a list of all orgs that a user is an accessor of.
func (i *DocumentIndex) UsersOrgs(userID influxdb.ID) ([]influxdb.ID, error) {
f := influxdb.UserResourceMappingFilter{
UserID: userID,
ResourceType: influxdb.OrgsResourceType,
}
ms, err := i.service.findUserResourceMappings(i.ctx, i.tx, f)
if err != nil {
return nil, err
}
ids := make([]influxdb.ID, 0, len(ms))
for _, m := range ms {
ids = append(ids, m.ResourceID)
}
return ids, nil
}
// IsOrgAccessor checks to see if the user is an accessor of the org provided. If the operation
// is writable it ensures that the user is owner.
func (i *DocumentIndex) IsOrgAccessor(userID influxdb.ID, orgID influxdb.ID) error {
f := influxdb.UserResourceMappingFilter{
UserID: userID,
ResourceType: influxdb.OrgsResourceType,
ResourceID: orgID,
}
if i.writable {
f.UserType = influxdb.Owner
}
ms, err := i.service.findUserResourceMappings(i.ctx, i.tx, f)
if err != nil {
return err
}
for _, m := range ms {
switch m.UserType {
case influxdb.Owner, influxdb.Member:
return nil
default:
continue
}
}
return &influxdb.Error{
Code: influxdb.EUnauthorized,
Msg: "user is not org member",
}
}
func (i *DocumentIndex) ownerExists(ownerType string, ownerID influxdb.ID) error {
switch ownerType {
case "org":
if _, err := i.service.findOrganizationByID(i.ctx, i.tx, ownerID); err != nil {
return err
}
case "user":
if _, err := i.service.findUserByID(i.ctx, i.tx, ownerID); err != nil {
return err
}
default:
return &influxdb.Error{
Code: influxdb.EInternal,
Msg: fmt.Sprintf("unknown owner type %q", ownerType),
}
}
return nil
}
// FindOrganizationByName retrieves the organization ID of the org provided.
func (i *DocumentIndex) FindOrganizationByName(org string) (influxdb.ID, error) {
o, err := i.service.findOrganizationByName(i.ctx, i.tx, org)
if err != nil {
return influxdb.InvalidID(), err
}
return o.ID, nil
}
// FindOrganizationByID checks if the org existence by the org id provided.
func (i *DocumentIndex) FindOrganizationByID(id influxdb.ID) error {
_, err := i.service.findOrganizationByID(i.ctx, i.tx, id)
if err != nil {
return err
}
return nil
}
// GetDocumentsAccessors retrieves the list of accessors of a document.
func (i *DocumentIndex) GetDocumentsAccessors(docID influxdb.ID) ([]influxdb.ID, error) {
f := influxdb.UserResourceMappingFilter{
ResourceType: influxdb.DocumentsResourceType,
ResourceID: docID,
}
if i.writable {
f.UserType = influxdb.Owner
}
ms, err := i.service.findUserResourceMappings(i.ctx, i.tx, f)
if err != nil {
return nil, err
}
ids := make([]influxdb.ID, 0, len(ms))
for _, m := range ms {
if m.MappingType == influxdb.UserMappingType {
continue
}
// TODO(desa): this is really an orgID, eventually we should support users and org as owners of documents
ids = append(ids, m.UserID)
}
return ids, nil
}
// GetAccessorsDocuments retrieves the list of documents a user is allowed to access.
func (i *DocumentIndex) GetAccessorsDocuments(ownerType string, ownerID influxdb.ID) ([]influxdb.ID, error) {
if err := i.ownerExists(ownerType, ownerID); err != nil {
return nil, err
}
f := influxdb.UserResourceMappingFilter{
UserID: ownerID,
ResourceType: influxdb.DocumentsResourceType,
}
if i.writable {
f.UserType = influxdb.Owner
}
ms, err := i.service.findUserResourceMappings(i.ctx, i.tx, f)
if err != nil {
return nil, err
}
ids := make([]influxdb.ID, 0, len(ms))
for _, m := range ms {
ids = append(ids, m.ResourceID)
}
return ids, nil
}
// DocumentDecorator is used to communication the decoration of documents to the
// document store.
type DocumentDecorator struct {
data bool
labels bool
orgs bool
writable bool
}
// IncludeContent signals that the document should include its content when returned.
func (d *DocumentDecorator) IncludeContent() error {
if d.writable {
return &influxdb.Error{
Code: influxdb.EInternal,
Msg: "cannot include data in document",
}
}
d.data = true
return nil
}
// IncludeLabels signals that the document should include its labels when returned.
func (d *DocumentDecorator) IncludeLabels() error {
if d.writable {
return &influxdb.Error{
Code: influxdb.EInternal,
Msg: "cannot include labels in document",
}
}
d.labels = true
return nil
}
// IncludeOwner signals that the document should include its owner.
func (d *DocumentDecorator) IncludeOrganizations() error {
if d.writable {
return &influxdb.Error{
Code: influxdb.EInternal,
Msg: "cannot include labels in document",
}
}
d.orgs = true
return nil
}