217 lines
5.1 KiB
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
|
|
}
|