distrubutes ServiceResource throughout path
Adds utilization of the ServiceResource struct to all of the path package functionality. In general, this takes most instances where a service and resource are requested, and replaces those values with a slice of ServiceResource tuples. To keep the review smaller, this change does not update any packages outside of path. Therefore the tests and build are guaranteed to fail. The next PR, which updates all other packages with the changes, is necessary for both PRs to move forward.
This commit is contained in:
parent
5f7f1092ec
commit
dfd486cd41
@ -203,28 +203,30 @@ func (pb Builder) withPrefix(elements ...string) *Builder {
|
|||||||
|
|
||||||
// verifyPrefix ensures that the tenant and resourceOwner are valid
|
// verifyPrefix ensures that the tenant and resourceOwner are valid
|
||||||
// values, and that the builder has some directory structure.
|
// values, and that the builder has some directory structure.
|
||||||
func (pb Builder) verifyPrefix(tenant, resourceOwner string) error {
|
// func (pb Builder) verifyPrefix(tenant, resourceOwner string) error {
|
||||||
if err := verifyInputValues(tenant, resourceOwner); err != nil {
|
// if err := verifyPrefixValues(tenant, resourceOwner); err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
|
|
||||||
if len(pb.elements) == 0 {
|
// if len(pb.elements) == 0 {
|
||||||
return clues.New("missing path beyond prefix")
|
// return clues.New("missing path beyond prefix")
|
||||||
}
|
// }
|
||||||
|
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Data Layer Path Transformers
|
// Data Layer Path Transformers
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
func (pb Builder) ToStreamStorePath(
|
func (pb Builder) ToStreamStorePath(
|
||||||
tenant, purpose string,
|
tenant string,
|
||||||
service ServiceType,
|
srs []ServiceResource,
|
||||||
isItem bool,
|
isItem bool,
|
||||||
) (Path, error) {
|
) (Path, error) {
|
||||||
if err := verifyInputValues(tenant, purpose); err != nil {
|
cat := DetailsCategory
|
||||||
|
|
||||||
|
if err := verifyPrefixValues(tenant, srs, cat); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,40 +234,18 @@ func (pb Builder) ToStreamStorePath(
|
|||||||
return nil, clues.New("missing path beyond prefix")
|
return nil, clues.New("missing path beyond prefix")
|
||||||
}
|
}
|
||||||
|
|
||||||
metadataService := UnknownService
|
dlrp := newDataLayerResourcePath(pb, tenant, toMetadataServices(srs), cat, isItem)
|
||||||
|
|
||||||
switch service {
|
return &dlrp, nil
|
||||||
case ExchangeService:
|
|
||||||
metadataService = ExchangeMetadataService
|
|
||||||
case OneDriveService:
|
|
||||||
metadataService = OneDriveMetadataService
|
|
||||||
case SharePointService:
|
|
||||||
metadataService = SharePointMetadataService
|
|
||||||
}
|
|
||||||
|
|
||||||
return &dataLayerResourcePath{
|
|
||||||
Builder: *pb.withPrefix(
|
|
||||||
tenant,
|
|
||||||
metadataService.String(),
|
|
||||||
purpose,
|
|
||||||
DetailsCategory.String()),
|
|
||||||
service: metadataService,
|
|
||||||
category: DetailsCategory,
|
|
||||||
hasItem: isItem,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pb Builder) ToServiceCategoryMetadataPath(
|
func (pb Builder) ToServiceCategoryMetadataPath(
|
||||||
tenant, user string,
|
tenant string,
|
||||||
service ServiceType,
|
srs []ServiceResource,
|
||||||
category CategoryType,
|
cat CategoryType,
|
||||||
isItem bool,
|
isItem bool,
|
||||||
) (Path, error) {
|
) (Path, error) {
|
||||||
if err := ValidateServiceAndCategory(service, category); err != nil {
|
if err := verifyPrefixValues(tenant, srs, cat); err != nil {
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := verifyInputValues(tenant, user); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,79 +253,66 @@ func (pb Builder) ToServiceCategoryMetadataPath(
|
|||||||
return nil, clues.New("missing path beyond prefix")
|
return nil, clues.New("missing path beyond prefix")
|
||||||
}
|
}
|
||||||
|
|
||||||
metadataService := UnknownService
|
dlrp := newDataLayerResourcePath(pb, tenant, toMetadataServices(srs), cat, isItem)
|
||||||
|
|
||||||
switch service {
|
return &dlrp, nil
|
||||||
case ExchangeService:
|
|
||||||
metadataService = ExchangeMetadataService
|
|
||||||
case OneDriveService:
|
|
||||||
metadataService = OneDriveMetadataService
|
|
||||||
case SharePointService:
|
|
||||||
metadataService = SharePointMetadataService
|
|
||||||
}
|
|
||||||
|
|
||||||
return &dataLayerResourcePath{
|
|
||||||
Builder: *pb.withPrefix(
|
|
||||||
tenant,
|
|
||||||
metadataService.String(),
|
|
||||||
user,
|
|
||||||
category.String(),
|
|
||||||
),
|
|
||||||
service: metadataService,
|
|
||||||
category: category,
|
|
||||||
hasItem: isItem,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pb Builder) ToDataLayerPath(
|
func (pb Builder) ToDataLayerPath(
|
||||||
tenant, user string,
|
tenant string,
|
||||||
service ServiceType,
|
srs []ServiceResource,
|
||||||
category CategoryType,
|
cat CategoryType,
|
||||||
isItem bool,
|
isItem bool,
|
||||||
) (Path, error) {
|
) (Path, error) {
|
||||||
if err := ValidateServiceAndCategory(service, category); err != nil {
|
if err := verifyPrefixValues(tenant, srs, cat); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := pb.verifyPrefix(tenant, user); err != nil {
|
dlrp := newDataLayerResourcePath(pb, tenant, srs, cat, isItem)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &dataLayerResourcePath{
|
return &dlrp, nil
|
||||||
Builder: *pb.withPrefix(
|
|
||||||
tenant,
|
|
||||||
service.String(),
|
|
||||||
user,
|
|
||||||
category.String()),
|
|
||||||
service: service,
|
|
||||||
category: category,
|
|
||||||
hasItem: isItem,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pb Builder) ToDataLayerExchangePathForCategory(
|
func (pb Builder) ToDataLayerExchangePathForCategory(
|
||||||
tenant, user string,
|
tenant, mailboxID string,
|
||||||
category CategoryType,
|
category CategoryType,
|
||||||
isItem bool,
|
isItem bool,
|
||||||
) (Path, error) {
|
) (Path, error) {
|
||||||
return pb.ToDataLayerPath(tenant, user, ExchangeService, category, isItem)
|
srs, err := NewServiceResources(ExchangeService, mailboxID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pb.ToDataLayerPath(tenant, srs, category, isItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pb Builder) ToDataLayerOneDrivePath(
|
func (pb Builder) ToDataLayerOneDrivePath(
|
||||||
tenant, user string,
|
tenant, userID string,
|
||||||
isItem bool,
|
isItem bool,
|
||||||
) (Path, error) {
|
) (Path, error) {
|
||||||
return pb.ToDataLayerPath(tenant, user, OneDriveService, FilesCategory, isItem)
|
srs, err := NewServiceResources(OneDriveService, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pb.ToDataLayerPath(tenant, srs, FilesCategory, isItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pb Builder) ToDataLayerSharePointPath(
|
func (pb Builder) ToDataLayerSharePointPath(
|
||||||
tenant, site string,
|
tenant, siteID string,
|
||||||
category CategoryType,
|
category CategoryType,
|
||||||
isItem bool,
|
isItem bool,
|
||||||
) (Path, error) {
|
) (Path, error) {
|
||||||
return pb.ToDataLayerPath(tenant, site, SharePointService, category, isItem)
|
srs, err := NewServiceResources(SharePointService, siteID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pb.ToDataLayerPath(tenant, srs, category, isItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: ToDataLayerGroupsPath()
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Stringers and PII Concealer Compliance
|
// Stringers and PII Concealer Compliance
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@ -46,7 +46,10 @@ func (suite *BuilderUnitSuite) TestAppend() {
|
|||||||
func (suite *BuilderUnitSuite) TestAppendItem() {
|
func (suite *BuilderUnitSuite) TestAppendItem() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
|
|
||||||
p, err := Build("t", "ro", ExchangeService, EmailCategory, false, "foo", "bar")
|
srs, err := NewServiceResources(ExchangeService, "ro")
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
p, err := Build("t", srs, EmailCategory, false, "foo", "bar")
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
pb := p.ToBuilder()
|
pb := p.ToBuilder()
|
||||||
@ -339,8 +342,13 @@ func (suite *BuilderUnitSuite) TestFolder() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *BuilderUnitSuite) TestPIIHandling() {
|
func (suite *BuilderUnitSuite) TestPIIHandling() {
|
||||||
p, err := Build("t", "ro", ExchangeService, EventsCategory, true, "dir", "item")
|
t := suite.T()
|
||||||
require.NoError(suite.T(), err)
|
|
||||||
|
srs, err := NewServiceResources(ExchangeService, "ro")
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
p, err := Build("t", srs, EventsCategory, true, "dir", "item")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
@ -75,24 +75,6 @@ var serviceCategories = map[ServiceType]map[CategoryType]struct{}{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateServiceAndCategoryStrings(s, c string) (ServiceType, CategoryType, error) {
|
|
||||||
service := toServiceType(s)
|
|
||||||
if service == UnknownService {
|
|
||||||
return UnknownService, UnknownCategory, clues.Stack(ErrorUnknownService).With("service", fmt.Sprintf("%q", s))
|
|
||||||
}
|
|
||||||
|
|
||||||
category := ToCategoryType(c)
|
|
||||||
if category == UnknownCategory {
|
|
||||||
return UnknownService, UnknownCategory, clues.Stack(ErrorUnknownService).With("category", fmt.Sprintf("%q", c))
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ValidateServiceAndCategory(service, category); err != nil {
|
|
||||||
return UnknownService, UnknownCategory, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return service, category, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ValidateServiceAndCategory(service ServiceType, category CategoryType) error {
|
func ValidateServiceAndCategory(service ServiceType, category CategoryType) error {
|
||||||
cats, ok := serviceCategories[service]
|
cats, ok := serviceCategories[service]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
@ -59,7 +59,10 @@ func (suite *OneDrivePathSuite) Test_ToOneDrivePath() {
|
|||||||
suite.Run(tt.name, func() {
|
suite.Run(tt.name, func() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
|
|
||||||
p, err := path.Build("tenant", "user", path.OneDriveService, path.FilesCategory, false, tt.pathElements...)
|
srs, err := path.NewServiceResources(path.OneDriveService, "user")
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
p, err := path.Build("tenant", srs, path.FilesCategory, false, tt.pathElements...)
|
||||||
require.NoError(suite.T(), err, clues.ToCore(err))
|
require.NoError(suite.T(), err, clues.ToCore(err))
|
||||||
|
|
||||||
got, err := path.ToDrivePath(p)
|
got, err := path.ToDrivePath(p)
|
||||||
|
|||||||
@ -79,10 +79,12 @@ var (
|
|||||||
// string.
|
// string.
|
||||||
type Path interface {
|
type Path interface {
|
||||||
String() string
|
String() string
|
||||||
Service() ServiceType
|
// ServiceResources produces all of the services and subservices, along with
|
||||||
|
// the protected resource paired with the service, as contained in the path,
|
||||||
|
// in their order of appearance.
|
||||||
|
ServiceResources() []ServiceResource
|
||||||
Category() CategoryType
|
Category() CategoryType
|
||||||
Tenant() string
|
Tenant() string
|
||||||
ResourceOwner() string
|
|
||||||
Folder(escaped bool) string
|
Folder(escaped bool) string
|
||||||
Folders() Elements
|
Folders() Elements
|
||||||
Item() string
|
Item() string
|
||||||
@ -132,41 +134,29 @@ type RestorePaths struct {
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
func Build(
|
func Build(
|
||||||
tenant, resourceOwner string,
|
tenant string,
|
||||||
service ServiceType,
|
srs []ServiceResource,
|
||||||
category CategoryType,
|
category CategoryType,
|
||||||
hasItem bool,
|
hasItem bool,
|
||||||
elements ...string,
|
elements ...string,
|
||||||
) (Path, error) {
|
) (Path, error) {
|
||||||
b := Builder{}.Append(elements...)
|
return Builder{}.
|
||||||
|
Append(elements...).
|
||||||
return b.ToDataLayerPath(
|
ToDataLayerPath(tenant, srs, category, hasItem)
|
||||||
tenant, resourceOwner,
|
|
||||||
service, category,
|
|
||||||
hasItem)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildPrefix(
|
func BuildPrefix(
|
||||||
tenant, resourceOwner string,
|
tenant string,
|
||||||
s ServiceType,
|
srs []ServiceResource,
|
||||||
c CategoryType,
|
cat CategoryType,
|
||||||
) (Path, error) {
|
) (Path, error) {
|
||||||
pb := Builder{}
|
if err := verifyPrefixValues(tenant, srs, cat); err != nil {
|
||||||
|
|
||||||
if err := ValidateServiceAndCategory(s, c); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := verifyInputValues(tenant, resourceOwner); err != nil {
|
dlrp := newDataLayerResourcePath(Builder{}, tenant, srs, cat, false)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &dataLayerResourcePath{
|
return &dlrp, nil
|
||||||
Builder: *pb.withPrefix(tenant, s.String(), resourceOwner, c.String()),
|
|
||||||
service: s,
|
|
||||||
category: c,
|
|
||||||
hasItem: false,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromDataLayerPath parses the escaped path p, validates the elements in p
|
// FromDataLayerPath parses the escaped path p, validates the elements in p
|
||||||
@ -186,24 +176,37 @@ func FromDataLayerPath(p string, isItem bool) (Path, error) {
|
|||||||
return nil, clues.Stack(errParsingPath, err).With("path_string", p)
|
return nil, clues.Stack(errParsingPath, err).With("path_string", p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initial check for minimum required elements:
|
||||||
|
// tenant, service, resource, category, container/item
|
||||||
if len(pb.elements) < 5 {
|
if len(pb.elements) < 5 {
|
||||||
return nil, clues.New("path has too few segments").With("path_string", p)
|
return nil, clues.New("path has too few segments").With("path_string", p)
|
||||||
}
|
}
|
||||||
|
|
||||||
service, category, err := validateServiceAndCategoryStrings(
|
srs, catIdx, err := ElementsToServiceResources(pb.elements[1:])
|
||||||
pb.elements[1],
|
|
||||||
pb.elements[3],
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
return nil, clues.Stack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// follow-up check: if more than one service exists, revisit the len check.
|
||||||
|
if len(srs) > 1 && len(pb.elements) < 3+(2*len(srs)) {
|
||||||
|
return nil, clues.New("path has too few segments").With("path_string", p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// +1 to account for slicing the tenant when calling the transformer func.
|
||||||
|
category := ToCategoryType(pb.elements[catIdx+1])
|
||||||
|
|
||||||
|
if err := verifyPrefixValues(pb.elements[0], srs, category); err != nil {
|
||||||
return nil, clues.Stack(errParsingPath, err).With("path_string", p)
|
return nil, clues.Stack(errParsingPath, err).With("path_string", p)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &dataLayerResourcePath{
|
dlrp := dataLayerResourcePath{
|
||||||
Builder: *pb,
|
Builder: *pb,
|
||||||
service: service,
|
serviceResources: srs,
|
||||||
category: category,
|
category: category,
|
||||||
hasItem: isItem,
|
hasItem: isItem,
|
||||||
}, nil
|
}
|
||||||
|
|
||||||
|
return &dlrp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrimTrailingSlash takes an escaped path element and returns an escaped path
|
// TrimTrailingSlash takes an escaped path element and returns an escaped path
|
||||||
@ -290,16 +293,21 @@ func Split(segment string) []string {
|
|||||||
// Unexported Helpers
|
// Unexported Helpers
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
func verifyInputValues(tenant, resourceOwner string) error {
|
func verifyPrefixValues(
|
||||||
|
tenant string,
|
||||||
|
srs []ServiceResource,
|
||||||
|
cat CategoryType,
|
||||||
|
) error {
|
||||||
if len(tenant) == 0 {
|
if len(tenant) == 0 {
|
||||||
return clues.Stack(errMissingSegment, clues.New("tenant"))
|
return clues.Stack(errMissingSegment, clues.New("tenant"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(resourceOwner) == 0 {
|
if err := validateServiceResources(srs); err != nil {
|
||||||
return clues.Stack(errMissingSegment, clues.New("resourceOwner"))
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
// only the final service is checked for its category validity
|
||||||
|
return ValidateServiceAndCategory(srs[len(srs)-1].Service, cat)
|
||||||
}
|
}
|
||||||
|
|
||||||
// escapeElement takes a single path element and escapes all characters that
|
// escapeElement takes a single path element and escapes all characters that
|
||||||
|
|||||||
@ -334,14 +334,12 @@ func (suite *PathUnitSuite) TestFromDataLayerPath() {
|
|||||||
testUser,
|
testUser,
|
||||||
testElement1,
|
testElement1,
|
||||||
testElement2,
|
testElement2,
|
||||||
testElement3,
|
testElement3),
|
||||||
),
|
|
||||||
expectedFolder: fmt.Sprintf(
|
expectedFolder: fmt.Sprintf(
|
||||||
"%s/%s/%s",
|
"%s/%s/%s",
|
||||||
testElementTrimmed,
|
testElementTrimmed,
|
||||||
testElement2,
|
testElement2,
|
||||||
testElement3,
|
testElement3),
|
||||||
),
|
|
||||||
expectedSplit: []string{
|
expectedSplit: []string{
|
||||||
testElementTrimmed,
|
testElementTrimmed,
|
||||||
testElement2,
|
testElement2,
|
||||||
@ -351,8 +349,7 @@ func (suite *PathUnitSuite) TestFromDataLayerPath() {
|
|||||||
expectedItemFolder: fmt.Sprintf(
|
expectedItemFolder: fmt.Sprintf(
|
||||||
"%s/%s",
|
"%s/%s",
|
||||||
testElementTrimmed,
|
testElementTrimmed,
|
||||||
testElement2,
|
testElement2),
|
||||||
),
|
|
||||||
expectedItemSplit: []string{
|
expectedItemSplit: []string{
|
||||||
testElementTrimmed,
|
testElementTrimmed,
|
||||||
testElement2,
|
testElement2,
|
||||||
@ -366,14 +363,12 @@ func (suite *PathUnitSuite) TestFromDataLayerPath() {
|
|||||||
testUser,
|
testUser,
|
||||||
testElementTrimmed,
|
testElementTrimmed,
|
||||||
testElement2,
|
testElement2,
|
||||||
testElement3,
|
testElement3),
|
||||||
),
|
|
||||||
expectedFolder: fmt.Sprintf(
|
expectedFolder: fmt.Sprintf(
|
||||||
"%s/%s/%s",
|
"%s/%s/%s",
|
||||||
testElementTrimmed,
|
testElementTrimmed,
|
||||||
testElement2,
|
testElement2,
|
||||||
testElement3,
|
testElement3),
|
||||||
),
|
|
||||||
expectedSplit: []string{
|
expectedSplit: []string{
|
||||||
testElementTrimmed,
|
testElementTrimmed,
|
||||||
testElement2,
|
testElement2,
|
||||||
@ -383,8 +378,7 @@ func (suite *PathUnitSuite) TestFromDataLayerPath() {
|
|||||||
expectedItemFolder: fmt.Sprintf(
|
expectedItemFolder: fmt.Sprintf(
|
||||||
"%s/%s",
|
"%s/%s",
|
||||||
testElementTrimmed,
|
testElementTrimmed,
|
||||||
testElement2,
|
testElement2),
|
||||||
),
|
|
||||||
expectedItemSplit: []string{
|
expectedItemSplit: []string{
|
||||||
testElementTrimmed,
|
testElementTrimmed,
|
||||||
testElement2,
|
testElement2,
|
||||||
@ -393,21 +387,27 @@ func (suite *PathUnitSuite) TestFromDataLayerPath() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for service, cats := range serviceCategories {
|
for service, cats := range serviceCategories {
|
||||||
|
|
||||||
for cat := range cats {
|
for cat := range cats {
|
||||||
|
|
||||||
for _, item := range isItem {
|
for _, item := range isItem {
|
||||||
suite.Run(fmt.Sprintf("%s-%s-%s", service, cat, item.name), func() {
|
suite.Run(fmt.Sprintf("%s-%s-%s", service, cat, item.name), func() {
|
||||||
|
|
||||||
for _, test := range table {
|
for _, test := range table {
|
||||||
suite.Run(test.name, func() {
|
suite.Run(test.name, func() {
|
||||||
t := suite.T()
|
var (
|
||||||
testPath := fmt.Sprintf(test.unescapedPath, service, cat)
|
t = suite.T()
|
||||||
|
testPath = fmt.Sprintf(test.unescapedPath, service, cat)
|
||||||
|
sr = ServiceResource{service, testUser}
|
||||||
|
)
|
||||||
|
|
||||||
p, err := FromDataLayerPath(testPath, item.isItem)
|
p, err := FromDataLayerPath(testPath, item.isItem)
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
assert.Equal(t, service, p.Service(), "service")
|
assert.Len(t, p.ServiceResources(), 1, "service resources")
|
||||||
|
assert.Equal(t, sr, p.ServiceResources()[0], "service resource")
|
||||||
assert.Equal(t, cat, p.Category(), "category")
|
assert.Equal(t, cat, p.Category(), "category")
|
||||||
assert.Equal(t, testTenant, p.Tenant(), "tenant")
|
assert.Equal(t, testTenant, p.Tenant(), "tenant")
|
||||||
assert.Equal(t, testUser, p.ResourceOwner(), "resource owner")
|
|
||||||
|
|
||||||
fld := p.Folder(false)
|
fld := p.Folder(false)
|
||||||
escfld := p.Folder(true)
|
escfld := p.Folder(true)
|
||||||
@ -435,44 +435,74 @@ func (suite *PathUnitSuite) TestFromDataLayerPath() {
|
|||||||
func (suite *PathUnitSuite) TestBuildPrefix() {
|
func (suite *PathUnitSuite) TestBuildPrefix() {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
service ServiceType
|
|
||||||
category CategoryType
|
|
||||||
tenant string
|
tenant string
|
||||||
owner string
|
srs []ServiceResource
|
||||||
|
category CategoryType
|
||||||
expect string
|
expect string
|
||||||
expectErr require.ErrorAssertionFunc
|
expectErr require.ErrorAssertionFunc
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "ok",
|
name: "ok",
|
||||||
service: ExchangeService,
|
|
||||||
category: ContactsCategory,
|
|
||||||
tenant: "t",
|
tenant: "t",
|
||||||
owner: "ro",
|
srs: []ServiceResource{{ExchangeService, "roo"}},
|
||||||
expect: join([]string{"t", ExchangeService.String(), "ro", ContactsCategory.String()}),
|
category: ContactsCategory,
|
||||||
|
expect: join([]string{"t", ExchangeService.String(), "roo", ContactsCategory.String()}),
|
||||||
|
expectErr: require.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok with subservice",
|
||||||
|
tenant: "t",
|
||||||
|
srs: []ServiceResource{
|
||||||
|
{GroupsService, "roo"},
|
||||||
|
{SharePointService, "oor"},
|
||||||
|
},
|
||||||
|
category: LibrariesCategory,
|
||||||
|
expect: join([]string{
|
||||||
|
"t",
|
||||||
|
GroupsService.String(), "roo",
|
||||||
|
SharePointService.String(), "oor",
|
||||||
|
LibrariesCategory.String()}),
|
||||||
expectErr: require.NoError,
|
expectErr: require.NoError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "bad category",
|
name: "bad category",
|
||||||
service: ExchangeService,
|
srs: []ServiceResource{{ExchangeService, "roo"}},
|
||||||
category: FilesCategory,
|
category: FilesCategory,
|
||||||
tenant: "t",
|
tenant: "t",
|
||||||
owner: "ro",
|
|
||||||
expectErr: require.Error,
|
expectErr: require.Error,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "bad tenant",
|
name: "bad tenant",
|
||||||
service: ExchangeService,
|
|
||||||
category: ContactsCategory,
|
|
||||||
tenant: "",
|
tenant: "",
|
||||||
owner: "ro",
|
srs: []ServiceResource{{ExchangeService, "roo"}},
|
||||||
|
category: ContactsCategory,
|
||||||
expectErr: require.Error,
|
expectErr: require.Error,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "bad owner",
|
name: "bad resource",
|
||||||
service: ExchangeService,
|
|
||||||
category: ContactsCategory,
|
|
||||||
tenant: "t",
|
tenant: "t",
|
||||||
owner: "",
|
srs: []ServiceResource{{ExchangeService, ""}},
|
||||||
|
category: ContactsCategory,
|
||||||
|
expectErr: require.Error,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "bad subservice",
|
||||||
|
tenant: "t",
|
||||||
|
srs: []ServiceResource{
|
||||||
|
{ExchangeService, "roo"},
|
||||||
|
{OneDriveService, "oor"},
|
||||||
|
},
|
||||||
|
category: FilesCategory,
|
||||||
|
expectErr: require.Error,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "bad subservice resource",
|
||||||
|
tenant: "t",
|
||||||
|
srs: []ServiceResource{
|
||||||
|
{GroupsService, "roo"},
|
||||||
|
{SharePointService, ""},
|
||||||
|
},
|
||||||
|
category: LibrariesCategory,
|
||||||
expectErr: require.Error,
|
expectErr: require.Error,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -480,7 +510,7 @@ func (suite *PathUnitSuite) TestBuildPrefix() {
|
|||||||
suite.Run(test.name, func() {
|
suite.Run(test.name, func() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
|
|
||||||
r, err := BuildPrefix(test.tenant, test.owner, test.service, test.category)
|
r, err := BuildPrefix(test.tenant, test.srs, test.category)
|
||||||
test.expectErr(t, err, clues.ToCore(err))
|
test.expectErr(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
if r == nil {
|
if r == nil {
|
||||||
|
|||||||
@ -18,9 +18,28 @@ import (
|
|||||||
// element after the prefix.
|
// element after the prefix.
|
||||||
type dataLayerResourcePath struct {
|
type dataLayerResourcePath struct {
|
||||||
Builder
|
Builder
|
||||||
category CategoryType
|
category CategoryType
|
||||||
service ServiceType
|
serviceResources []ServiceResource
|
||||||
hasItem bool
|
hasItem bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// performs no validation, assumes the caller has validated the inputs.
|
||||||
|
func newDataLayerResourcePath(
|
||||||
|
pb Builder,
|
||||||
|
tenant string,
|
||||||
|
srs []ServiceResource,
|
||||||
|
cat CategoryType,
|
||||||
|
isItem bool,
|
||||||
|
) dataLayerResourcePath {
|
||||||
|
pfx := append([]string{tenant}, ServiceResourcesToElements(srs)...)
|
||||||
|
pfx = append(pfx, cat.String())
|
||||||
|
|
||||||
|
return dataLayerResourcePath{
|
||||||
|
Builder: *pb.withPrefix(pfx...),
|
||||||
|
serviceResources: srs,
|
||||||
|
category: cat,
|
||||||
|
hasItem: isItem,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tenant returns the tenant ID embedded in the dataLayerResourcePath.
|
// Tenant returns the tenant ID embedded in the dataLayerResourcePath.
|
||||||
@ -28,9 +47,8 @@ func (rp dataLayerResourcePath) Tenant() string {
|
|||||||
return rp.Builder.elements[0]
|
return rp.Builder.elements[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Service returns the ServiceType embedded in the dataLayerResourcePath.
|
func (rp dataLayerResourcePath) ServiceResources() []ServiceResource {
|
||||||
func (rp dataLayerResourcePath) Service() ServiceType {
|
return rp.serviceResources
|
||||||
return rp.service
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Category returns the CategoryType embedded in the dataLayerResourcePath.
|
// Category returns the CategoryType embedded in the dataLayerResourcePath.
|
||||||
@ -95,15 +113,18 @@ func (rp dataLayerResourcePath) Item() string {
|
|||||||
// Dir removes the last element from the path. If this would remove a
|
// Dir removes the last element from the path. If this would remove a
|
||||||
// value that is part of the standard prefix structure, an error is returned.
|
// value that is part of the standard prefix structure, an error is returned.
|
||||||
func (rp dataLayerResourcePath) Dir() (Path, error) {
|
func (rp dataLayerResourcePath) Dir() (Path, error) {
|
||||||
if len(rp.elements) <= 4 {
|
// Dir is not allowed to slice off any prefix values.
|
||||||
|
// The prefix len is determined by the length of the number of
|
||||||
|
// service+resource tuples, plus 2 (tenant and category).
|
||||||
|
if len(rp.elements) <= 2+(2*len(rp.serviceResources)) {
|
||||||
return nil, clues.New("unable to shorten path").With("path", rp)
|
return nil, clues.New("unable to shorten path").With("path", rp)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &dataLayerResourcePath{
|
return &dataLayerResourcePath{
|
||||||
Builder: *rp.Builder.Dir(),
|
Builder: *rp.Builder.Dir(),
|
||||||
service: rp.service,
|
serviceResources: rp.serviceResources,
|
||||||
category: rp.category,
|
category: rp.category,
|
||||||
hasItem: false,
|
hasItem: false,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,10 +137,10 @@ func (rp dataLayerResourcePath) Append(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &dataLayerResourcePath{
|
return &dataLayerResourcePath{
|
||||||
Builder: *rp.Builder.Append(elems...),
|
Builder: *rp.Builder.Append(elems...),
|
||||||
service: rp.service,
|
serviceResources: rp.serviceResources,
|
||||||
category: rp.category,
|
category: rp.category,
|
||||||
hasItem: isItem,
|
hasItem: isItem,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -256,10 +256,10 @@ func (suite *DataLayerResourcePath) TestDir() {
|
|||||||
|
|
||||||
func (suite *DataLayerResourcePath) TestToServiceCategoryMetadataPath() {
|
func (suite *DataLayerResourcePath) TestToServiceCategoryMetadataPath() {
|
||||||
tenant := "a-tenant"
|
tenant := "a-tenant"
|
||||||
user := "a-user"
|
resource := "a-resource"
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
service path.ServiceType
|
srs []path.ServiceResource
|
||||||
category path.CategoryType
|
category path.CategoryType
|
||||||
postfix []string
|
postfix []string
|
||||||
expectedService path.ServiceType
|
expectedService path.ServiceType
|
||||||
@ -267,14 +267,14 @@ func (suite *DataLayerResourcePath) TestToServiceCategoryMetadataPath() {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "NoPostfixPasses",
|
name: "NoPostfixPasses",
|
||||||
service: path.ExchangeService,
|
srs: []path.ServiceResource{{path.ExchangeService, resource}},
|
||||||
category: path.EmailCategory,
|
category: path.EmailCategory,
|
||||||
expectedService: path.ExchangeMetadataService,
|
expectedService: path.ExchangeMetadataService,
|
||||||
check: assert.NoError,
|
check: assert.NoError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "PostfixPasses",
|
name: "PostfixPasses",
|
||||||
service: path.ExchangeService,
|
srs: []path.ServiceResource{{path.ExchangeService, resource}},
|
||||||
category: path.EmailCategory,
|
category: path.EmailCategory,
|
||||||
postfix: []string{"a", "b"},
|
postfix: []string{"a", "b"},
|
||||||
expectedService: path.ExchangeMetadataService,
|
expectedService: path.ExchangeMetadataService,
|
||||||
@ -282,48 +282,48 @@ func (suite *DataLayerResourcePath) TestToServiceCategoryMetadataPath() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Fails",
|
name: "Fails",
|
||||||
service: path.ExchangeService,
|
srs: []path.ServiceResource{{path.ExchangeService, resource}},
|
||||||
category: path.FilesCategory,
|
category: path.FilesCategory,
|
||||||
check: assert.Error,
|
check: assert.Error,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Passes",
|
name: "Passes",
|
||||||
service: path.ExchangeService,
|
srs: []path.ServiceResource{{path.ExchangeService, resource}},
|
||||||
category: path.ContactsCategory,
|
category: path.ContactsCategory,
|
||||||
expectedService: path.ExchangeMetadataService,
|
expectedService: path.ExchangeMetadataService,
|
||||||
check: assert.NoError,
|
check: assert.NoError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Passes",
|
name: "Passes",
|
||||||
service: path.ExchangeService,
|
srs: []path.ServiceResource{{path.ExchangeService, resource}},
|
||||||
category: path.EventsCategory,
|
category: path.EventsCategory,
|
||||||
expectedService: path.ExchangeMetadataService,
|
expectedService: path.ExchangeMetadataService,
|
||||||
check: assert.NoError,
|
check: assert.NoError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Passes",
|
name: "Passes",
|
||||||
service: path.OneDriveService,
|
srs: []path.ServiceResource{{path.OneDriveService, resource}},
|
||||||
category: path.FilesCategory,
|
category: path.FilesCategory,
|
||||||
expectedService: path.OneDriveMetadataService,
|
expectedService: path.OneDriveMetadataService,
|
||||||
check: assert.NoError,
|
check: assert.NoError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Passes",
|
name: "Passes",
|
||||||
service: path.SharePointService,
|
srs: []path.ServiceResource{{path.SharePointService, resource}},
|
||||||
category: path.LibrariesCategory,
|
category: path.LibrariesCategory,
|
||||||
expectedService: path.SharePointMetadataService,
|
expectedService: path.SharePointMetadataService,
|
||||||
check: assert.NoError,
|
check: assert.NoError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Passes",
|
name: "Passes",
|
||||||
service: path.SharePointService,
|
srs: []path.ServiceResource{{path.SharePointService, resource}},
|
||||||
category: path.ListsCategory,
|
category: path.ListsCategory,
|
||||||
expectedService: path.SharePointMetadataService,
|
expectedService: path.SharePointMetadataService,
|
||||||
check: assert.NoError,
|
check: assert.NoError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Passes",
|
name: "Passes",
|
||||||
service: path.SharePointService,
|
srs: []path.ServiceResource{{path.SharePointService, resource}},
|
||||||
category: path.PagesCategory,
|
category: path.PagesCategory,
|
||||||
expectedService: path.SharePointMetadataService,
|
expectedService: path.SharePointMetadataService,
|
||||||
check: assert.NoError,
|
check: assert.NoError,
|
||||||
@ -331,27 +331,26 @@ func (suite *DataLayerResourcePath) TestToServiceCategoryMetadataPath() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range table {
|
for _, test := range table {
|
||||||
suite.Run(strings.Join([]string{
|
name := strings.Join([]string{
|
||||||
test.name,
|
test.name,
|
||||||
test.service.String(),
|
test.srs[0].Service.String(),
|
||||||
test.category.String(),
|
test.category.String(),
|
||||||
}, "_"), func() {
|
}, "_")
|
||||||
|
|
||||||
|
suite.Run(name, func() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
pb := path.Builder{}.Append(test.postfix...)
|
pb := path.Builder{}.Append(test.postfix...)
|
||||||
|
|
||||||
p, err := pb.ToServiceCategoryMetadataPath(
|
p, err := pb.ToServiceCategoryMetadataPath(
|
||||||
tenant,
|
tenant,
|
||||||
user,
|
test.srs,
|
||||||
test.service,
|
|
||||||
test.category,
|
test.category,
|
||||||
false)
|
false)
|
||||||
test.check(t, err, clues.ToCore(err))
|
test.check(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
if err != nil {
|
if err == nil {
|
||||||
return
|
assert.Equal(t, test.expectedService, p.ServiceResources()[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, test.expectedService, p.Service())
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,9 +401,9 @@ func (suite *DataLayerResourcePath) TestToExchangePathForCategory() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, testTenant, p.Tenant())
|
assert.Equal(t, testTenant, p.Tenant())
|
||||||
assert.Equal(t, path.ExchangeService, p.Service())
|
assert.Equal(t, path.ExchangeService, p.ServiceResources()[0].Service)
|
||||||
assert.Equal(t, test.category, p.Category())
|
assert.Equal(t, test.category, p.Category())
|
||||||
assert.Equal(t, testUser, p.ResourceOwner())
|
assert.Equal(t, testUser, p.ServiceResources()[0].ProtectedResource)
|
||||||
assert.Equal(t, strings.Join(m.expectedFolders, "/"), p.Folder(false))
|
assert.Equal(t, strings.Join(m.expectedFolders, "/"), p.Folder(false))
|
||||||
assert.Equal(t, path.Elements(m.expectedFolders), p.Folders())
|
assert.Equal(t, path.Elements(m.expectedFolders), p.Folders())
|
||||||
assert.Equal(t, m.expectedItem, p.Item())
|
assert.Equal(t, m.expectedItem, p.Item())
|
||||||
@ -456,7 +455,10 @@ func (suite *PopulatedDataLayerResourcePath) TestService() {
|
|||||||
suite.Run(m.name, func() {
|
suite.Run(m.name, func() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
|
|
||||||
assert.Equal(t, path.ExchangeService, suite.paths[m.isItem].Service())
|
assert.Equal(
|
||||||
|
t,
|
||||||
|
path.ExchangeService,
|
||||||
|
suite.paths[m.isItem].ServiceResources()[0].Service)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -476,7 +478,10 @@ func (suite *PopulatedDataLayerResourcePath) TestResourceOwner() {
|
|||||||
suite.Run(m.name, func() {
|
suite.Run(m.name, func() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
|
|
||||||
assert.Equal(t, testUser, suite.paths[m.isItem].ResourceOwner())
|
assert.Equal(
|
||||||
|
t,
|
||||||
|
testUser,
|
||||||
|
suite.paths[m.isItem].ServiceResources()[0].ProtectedResource)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,118 +20,76 @@ func TestServiceCategoryUnitSuite(t *testing.T) {
|
|||||||
suite.Run(t, s)
|
suite.Run(t, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ServiceCategoryUnitSuite) TestValidateServiceAndCategoryBadStringErrors() {
|
func (suite *ServiceCategoryUnitSuite) TestVerifyPrefixValues() {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
service string
|
service ServiceType
|
||||||
category string
|
category CategoryType
|
||||||
}{
|
check assert.ErrorAssertionFunc
|
||||||
{
|
|
||||||
name: "Service",
|
|
||||||
service: "foo",
|
|
||||||
category: EmailCategory.String(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Category",
|
|
||||||
service: ExchangeService.String(),
|
|
||||||
category: "foo",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range table {
|
|
||||||
suite.Run(test.name, func() {
|
|
||||||
_, _, err := validateServiceAndCategoryStrings(test.service, test.category)
|
|
||||||
assert.Error(suite.T(), err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *ServiceCategoryUnitSuite) TestValidateServiceAndCategory() {
|
|
||||||
table := []struct {
|
|
||||||
name string
|
|
||||||
service string
|
|
||||||
category string
|
|
||||||
expectedService ServiceType
|
|
||||||
expectedCategory CategoryType
|
|
||||||
check assert.ErrorAssertionFunc
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "UnknownService",
|
name: "UnknownService",
|
||||||
service: UnknownService.String(),
|
service: UnknownService,
|
||||||
category: EmailCategory.String(),
|
category: EmailCategory,
|
||||||
check: assert.Error,
|
check: assert.Error,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "UnknownCategory",
|
name: "UnknownCategory",
|
||||||
service: ExchangeService.String(),
|
service: ExchangeService,
|
||||||
category: UnknownCategory.String(),
|
category: UnknownCategory,
|
||||||
check: assert.Error,
|
check: assert.Error,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "BadServiceString",
|
name: "BadServiceType",
|
||||||
service: "foo",
|
service: ServiceType(-1),
|
||||||
category: EmailCategory.String(),
|
category: EmailCategory,
|
||||||
check: assert.Error,
|
check: assert.Error,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "BadCategoryString",
|
name: "BadCategoryType",
|
||||||
service: ExchangeService.String(),
|
service: ExchangeService,
|
||||||
category: "foo",
|
category: CategoryType(-1),
|
||||||
check: assert.Error,
|
check: assert.Error,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ExchangeEmail",
|
name: "ExchangeEmail",
|
||||||
service: ExchangeService.String(),
|
service: ExchangeService,
|
||||||
category: EmailCategory.String(),
|
category: EmailCategory,
|
||||||
expectedService: ExchangeService,
|
check: assert.NoError,
|
||||||
expectedCategory: EmailCategory,
|
|
||||||
check: assert.NoError,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ExchangeContacts",
|
name: "ExchangeContacts",
|
||||||
service: ExchangeService.String(),
|
service: ExchangeService,
|
||||||
category: ContactsCategory.String(),
|
category: ContactsCategory,
|
||||||
expectedService: ExchangeService,
|
check: assert.NoError,
|
||||||
expectedCategory: ContactsCategory,
|
|
||||||
check: assert.NoError,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ExchangeEvents",
|
name: "ExchangeEvents",
|
||||||
service: ExchangeService.String(),
|
service: ExchangeService,
|
||||||
category: EventsCategory.String(),
|
category: EventsCategory,
|
||||||
expectedService: ExchangeService,
|
check: assert.NoError,
|
||||||
expectedCategory: EventsCategory,
|
|
||||||
check: assert.NoError,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "OneDriveFiles",
|
name: "OneDriveFiles",
|
||||||
service: OneDriveService.String(),
|
service: OneDriveService,
|
||||||
category: FilesCategory.String(),
|
category: FilesCategory,
|
||||||
expectedService: OneDriveService,
|
check: assert.NoError,
|
||||||
expectedCategory: FilesCategory,
|
|
||||||
check: assert.NoError,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "SharePointLibraries",
|
name: "SharePointLibraries",
|
||||||
service: SharePointService.String(),
|
service: SharePointService,
|
||||||
category: LibrariesCategory.String(),
|
category: LibrariesCategory,
|
||||||
expectedService: SharePointService,
|
check: assert.NoError,
|
||||||
expectedCategory: LibrariesCategory,
|
|
||||||
check: assert.NoError,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range table {
|
for _, test := range table {
|
||||||
suite.Run(test.name, func() {
|
suite.Run(test.name, func() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
|
|
||||||
s, c, err := validateServiceAndCategoryStrings(test.service, test.category)
|
srs := []ServiceResource{{test.service, "resource"}}
|
||||||
|
|
||||||
|
err := verifyPrefixValues("tid", srs, test.category)
|
||||||
test.check(t, err, clues.ToCore(err))
|
test.check(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal(t, test.expectedService, s)
|
|
||||||
assert.Equal(t, test.expectedCategory, c)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,6 +85,40 @@ func ServiceResourcesToElements(srs []ServiceResource) Elements {
|
|||||||
return es
|
return es
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ElementsToServiceResources turns as many pairs of elems as possible
|
||||||
|
// into ServiceResource tuples. Elems must begin with a service, but
|
||||||
|
// may contain more entries than there are service/resource pairs.
|
||||||
|
// This transformer will continue consuming elements until it finds an
|
||||||
|
// even-numbered index that cannot be cast to a ServiceType.
|
||||||
|
// Returns the serviceResource pairs, the first index containing element
|
||||||
|
// that is not part of a service/resource pair, and an error if elems is
|
||||||
|
// len==0 or contains no services.
|
||||||
|
func ElementsToServiceResources(elems Elements) ([]ServiceResource, int, error) {
|
||||||
|
if len(elems) == 0 {
|
||||||
|
return nil, -1, clues.Wrap(errMissingSegment, "service")
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
srs = make([]ServiceResource, 0)
|
||||||
|
i int
|
||||||
|
)
|
||||||
|
|
||||||
|
for j := 1; i < len(elems); i, j = i+2, j+2 {
|
||||||
|
service := toServiceType(elems[i])
|
||||||
|
if service == UnknownService {
|
||||||
|
if i == 0 {
|
||||||
|
return nil, -1, clues.Wrap(errMissingSegment, "service")
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
srs = append(srs, ServiceResource{service, elems[j]})
|
||||||
|
}
|
||||||
|
|
||||||
|
return srs, i, nil
|
||||||
|
}
|
||||||
|
|
||||||
// checks for the following:
|
// checks for the following:
|
||||||
// 1. each ServiceResource is valid
|
// 1. each ServiceResource is valid
|
||||||
// 2. if len(srs) > 1, srs[i], srs[i+1] pass subservice checks.
|
// 2. if len(srs) > 1, srs[i], srs[i+1] pass subservice checks.
|
||||||
@ -112,3 +146,29 @@ func validateServiceResources(srs []ServiceResource) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// makes a copy of the slice with all of the Services swapped for their
|
||||||
|
// metadata service countterparts.
|
||||||
|
func toMetadataServices(srs []ServiceResource) []ServiceResource {
|
||||||
|
msrs := make([]ServiceResource, 0, len(srs))
|
||||||
|
|
||||||
|
for _, sr := range srs {
|
||||||
|
msr := sr
|
||||||
|
metadataService := UnknownService
|
||||||
|
|
||||||
|
switch sr.Service {
|
||||||
|
case ExchangeService:
|
||||||
|
metadataService = ExchangeMetadataService
|
||||||
|
case OneDriveService:
|
||||||
|
metadataService = OneDriveMetadataService
|
||||||
|
case SharePointService:
|
||||||
|
metadataService = SharePointMetadataService
|
||||||
|
// TODO: add groups
|
||||||
|
}
|
||||||
|
|
||||||
|
msr.Service = metadataService
|
||||||
|
msrs = append(msrs, msr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return msrs
|
||||||
|
}
|
||||||
|
|||||||
@ -125,7 +125,7 @@ func (suite *ServiceResourceUnitSuite) TestValidateServiceResources() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ServiceResourceUnitSuite) TestServiceResourceElements() {
|
func (suite *ServiceResourceUnitSuite) TestServiceResourceToElements() {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
srs []ServiceResource
|
srs []ServiceResource
|
||||||
@ -164,3 +164,80 @@ func (suite *ServiceResourceUnitSuite) TestServiceResourceElements() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *ServiceResourceUnitSuite) TestElementsToServiceResource() {
|
||||||
|
table := []struct {
|
||||||
|
name string
|
||||||
|
elems Elements
|
||||||
|
expectErr assert.ErrorAssertionFunc
|
||||||
|
expectIdx int
|
||||||
|
expectSRS []ServiceResource
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty",
|
||||||
|
elems: Elements{},
|
||||||
|
expectErr: assert.Error,
|
||||||
|
expectIdx: -1,
|
||||||
|
expectSRS: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil",
|
||||||
|
elems: nil,
|
||||||
|
expectErr: assert.Error,
|
||||||
|
expectIdx: -1,
|
||||||
|
expectSRS: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-service 0th elem",
|
||||||
|
elems: Elements{"fnords"},
|
||||||
|
expectErr: assert.Error,
|
||||||
|
expectIdx: -1,
|
||||||
|
expectSRS: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-service 2nd elem",
|
||||||
|
elems: Elements{ExchangeService.String(), "fnords", "smarf"},
|
||||||
|
expectErr: assert.Error,
|
||||||
|
expectIdx: -1,
|
||||||
|
expectSRS: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "single serviceResource",
|
||||||
|
elems: Elements{ExchangeService.String(), "fnords"},
|
||||||
|
expectErr: assert.NoError,
|
||||||
|
expectIdx: 2,
|
||||||
|
expectSRS: []ServiceResource{{ExchangeService, "fnords"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "single serviceResource and extra value",
|
||||||
|
elems: Elements{ExchangeService.String(), "fnords", "smarf"},
|
||||||
|
expectErr: assert.NoError,
|
||||||
|
expectIdx: 2,
|
||||||
|
expectSRS: []ServiceResource{{ExchangeService, "fnords"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple serviceResource",
|
||||||
|
elems: Elements{ExchangeService.String(), "fnords", OneDriveService.String(), "smarf"},
|
||||||
|
expectErr: assert.NoError,
|
||||||
|
expectIdx: 4,
|
||||||
|
expectSRS: []ServiceResource{{ExchangeService, "fnords"}, {OneDriveService, "smarf"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple serviceResource and extra value",
|
||||||
|
elems: Elements{ExchangeService.String(), "fnords", OneDriveService.String(), "smarf", "flaboigans"},
|
||||||
|
expectErr: assert.NoError,
|
||||||
|
expectIdx: 4,
|
||||||
|
expectSRS: []ServiceResource{{ExchangeService, "fnords"}, {OneDriveService, "smarf"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range table {
|
||||||
|
suite.Run(test.name, func() {
|
||||||
|
t := suite.T()
|
||||||
|
|
||||||
|
srs, idx, err := ElementsToServiceResources(test.elems)
|
||||||
|
test.expectErr(t, err, clues.ToCore(err))
|
||||||
|
assert.Equal(t, test.expectIdx, idx)
|
||||||
|
assert.Equal(t, test.expectSRS, srs)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user