update selector to match current design (#266)
* update selector to match current design The selector design is progressing in the Showdown doc. This updates the existing structs to match the expectations in that doc.
This commit is contained in:
parent
cdf368ad20
commit
25a1e972e6
@ -1,129 +1,258 @@
|
||||
package selectors
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Exchange provides an api for scoping
|
||||
// data in the Exchange service.
|
||||
type Exchange struct {
|
||||
Selector
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
// Selectors
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// ToExchange transforms the generic selector into an Exchange.
|
||||
// Errors if the service defined by the selector is not ServiceExchange.
|
||||
func (s Selector) ToExchange() (*Exchange, error) {
|
||||
if s.service != ServiceExchange {
|
||||
return nil, badCastErr(ServiceExchange, s.service)
|
||||
type (
|
||||
// exchange provides an api for selecting
|
||||
// data scopes applicable to the Exchange service.
|
||||
exchange struct {
|
||||
Selector
|
||||
}
|
||||
src := Exchange{s}
|
||||
return &src, nil
|
||||
}
|
||||
|
||||
// ExchangeBackup provides an api for selecting
|
||||
// data scopes applicable to the Exchange service,
|
||||
// plus backup-specific methods.
|
||||
ExchangeBackup struct {
|
||||
exchange
|
||||
}
|
||||
|
||||
// ExchangeRestore provides an api for selecting
|
||||
// data scopes applicable to the Exchange service,
|
||||
// plus restore-specific methods.
|
||||
ExchangeRestore struct {
|
||||
exchange
|
||||
}
|
||||
)
|
||||
|
||||
// NewExchange produces a new Selector with the service set to ServiceExchange.
|
||||
func NewExchange(tenantID string) *Exchange {
|
||||
src := Exchange{
|
||||
newSelector(tenantID, ServiceExchange),
|
||||
func NewExchangeBackup() *ExchangeBackup {
|
||||
src := ExchangeBackup{
|
||||
exchange{
|
||||
newSelector(ServiceExchange, ""),
|
||||
},
|
||||
}
|
||||
return &src
|
||||
}
|
||||
|
||||
// ToExchangeBackup transforms the generic selector into an ExchangeBackup.
|
||||
// Errors if the service defined by the selector is not ServiceExchange.
|
||||
func (s Selector) ToExchangeBackup() (*ExchangeBackup, error) {
|
||||
if s.Service != ServiceExchange {
|
||||
return nil, badCastErr(ServiceExchange, s.Service)
|
||||
}
|
||||
src := ExchangeBackup{exchange{s}}
|
||||
return &src, nil
|
||||
}
|
||||
|
||||
// NewExchangeRestore produces a new Selector with the service set to ServiceExchange.
|
||||
func NewExchangeRestore(restorePointID string) *ExchangeRestore {
|
||||
src := ExchangeRestore{
|
||||
exchange{
|
||||
newSelector(ServiceExchange, restorePointID),
|
||||
},
|
||||
}
|
||||
return &src
|
||||
}
|
||||
|
||||
// ToExchangeRestore transforms the generic selector into an ExchangeRestore.
|
||||
// Errors if the service defined by the selector is not ServiceExchange.
|
||||
func (s Selector) ToExchangeRestore() (*ExchangeRestore, error) {
|
||||
if s.Service != ServiceExchange {
|
||||
return nil, badCastErr(ServiceExchange, s.Service)
|
||||
}
|
||||
src := ExchangeRestore{exchange{s}}
|
||||
return &src, nil
|
||||
}
|
||||
|
||||
// IncludeContacts selects the specified contacts owned by the user.
|
||||
func (s *exchange) IncludeContacts(u string, vs ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// IncludeContactFolders selects the specified contactFolders owned by the user.
|
||||
func (s *exchange) IncludeContactFolders(u string, vs ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// IncludeEvents selects the specified events owned by the user.
|
||||
func (s *exchange) IncludeEvents(u string, vs ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// IncludeMail selects the specified mail messages within the given folder,
|
||||
// owned by the user.
|
||||
func (s *exchange) IncludeMail(u, f string, vs ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// IncludeMailFolders selects the specified mail folders owned by the user.
|
||||
func (s *exchange) IncludeMailFolders(u string, vs ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// IncludeUsers selects the specified users. All of their data is included.
|
||||
func (s *exchange) IncludeUsers(us ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// ExcludeContacts selects the specified contacts owned by the user.
|
||||
func (s *exchange) ExcludeContacts(u string, vs ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// ExcludeContactFolders selects the specified contactFolders owned by the user.
|
||||
func (s *exchange) ExcludeContactFolders(u string, vs ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// ExcludeEvents selects the specified events owned by the user.
|
||||
func (s *exchange) ExcludeEvents(u string, vs ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// ExcludeMail selects the specified mail messages within the given folder,
|
||||
// owned by the user.
|
||||
func (s *exchange) ExcludeMail(u, f string, vs ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// ExcludeMailFolders selects the specified mail folders owned by the user.
|
||||
func (s *exchange) ExcludeMailFolders(u string, vs ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// ExcludeUsers selects the specified users. All of their data is excluded.
|
||||
func (s *exchange) ExcludeUsers(us ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Destination
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type ExchangeDestination Destination
|
||||
|
||||
func NewExchangeDestination() ExchangeDestination {
|
||||
return ExchangeDestination{}
|
||||
}
|
||||
|
||||
// GetOrDefault gets the destination of the provided category. If no
|
||||
// destination is set, returns the current value.
|
||||
func (d ExchangeDestination) GetOrDefault(cat exchangeCategory, current string) string {
|
||||
dest, ok := d[cat.String()]
|
||||
if !ok {
|
||||
return current
|
||||
}
|
||||
return dest
|
||||
}
|
||||
|
||||
// Sets the destination value of the provided category. Returns an error
|
||||
// if a destination is already declared for that category.
|
||||
func (d ExchangeDestination) Set(cat exchangeCategory, dest string) error {
|
||||
if len(dest) == 0 {
|
||||
return nil
|
||||
}
|
||||
cs := cat.String()
|
||||
if curr, ok := d[cs]; ok {
|
||||
return existingDestinationErr(cs, curr)
|
||||
}
|
||||
d[cs] = dest
|
||||
return nil
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Scopes
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type (
|
||||
// exchangeScope specifies the data available
|
||||
// when interfacing with the Exchange service.
|
||||
exchangeScope map[string]string
|
||||
// exchangeCategory enumerates the type of the lowest level
|
||||
// of data () in a scope.
|
||||
exchangeCategory int
|
||||
)
|
||||
|
||||
// Scopes retrieves the list of exchangeScopes in the selector.
|
||||
func (s *Exchange) Scopes() []exchangeScope {
|
||||
func (s *exchange) Scopes() []exchangeScope {
|
||||
scopes := []exchangeScope{}
|
||||
for _, v := range s.scopes {
|
||||
for _, v := range s.Includes {
|
||||
scopes = append(scopes, exchangeScope(v))
|
||||
}
|
||||
return scopes
|
||||
}
|
||||
|
||||
// the following are called by the client to specify the constraints
|
||||
// each call appends one or more scopes to the selector.
|
||||
|
||||
// Users selects the specified users. All of their data is included.
|
||||
func (s *Exchange) Users(us ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// Contacts selects the specified contacts owned by the user.
|
||||
func (s *Exchange) Contacts(u string, vs ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// Events selects the specified events owned by the user.
|
||||
func (s *Exchange) Events(u string, vs ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// MailFolders selects the specified mail folders owned by the user.
|
||||
func (s *Exchange) MailFolders(u string, vs ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// MailMessages selects the specified mail messages within the given folder,
|
||||
// owned by the user.
|
||||
func (s *Exchange) MailMessages(u, f string, vs ...string) {
|
||||
// todo
|
||||
}
|
||||
|
||||
// -----------------------
|
||||
|
||||
// exchangeScope specifies the data available
|
||||
// when interfacing with the Exchange service.
|
||||
type exchangeScope map[string]string
|
||||
|
||||
type exchangeCategory int
|
||||
|
||||
// exchangeCategory describes the type of data in scope.
|
||||
//go:generate stringer -type=exchangeCategory
|
||||
const (
|
||||
ExchangeCategoryUnknown exchangeCategory = iota
|
||||
ExchangeContact
|
||||
ExchangeContactFolder
|
||||
ExchangeEvent
|
||||
ExchangeFolder
|
||||
ExchangeMail
|
||||
ExchangeMailFolder
|
||||
ExchangeUser
|
||||
)
|
||||
|
||||
// String complies with the stringer interface, so that exchangeCategories
|
||||
// can be added into the scope map.
|
||||
func (ec exchangeCategory) String() string {
|
||||
return strconv.Itoa(int(ec))
|
||||
func exchangeCatAtoI(s string) exchangeCategory {
|
||||
switch s {
|
||||
case ExchangeContact.String():
|
||||
return ExchangeContact
|
||||
case ExchangeContactFolder.String():
|
||||
return ExchangeContactFolder
|
||||
case ExchangeEvent.String():
|
||||
return ExchangeEvent
|
||||
case ExchangeMail.String():
|
||||
return ExchangeMail
|
||||
case ExchangeMailFolder.String():
|
||||
return ExchangeMailFolder
|
||||
case ExchangeUser.String():
|
||||
return ExchangeUser
|
||||
default:
|
||||
return ExchangeCategoryUnknown
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
exchangeScopeKeyContactID = ExchangeContact.String()
|
||||
exchangeScopeKeyEventID = ExchangeEvent.String()
|
||||
exchangeScopeKeyFolderID = ExchangeFolder.String()
|
||||
exchangeScopeKeyMessageID = ExchangeMail.String()
|
||||
exchangeScopeKeyUserID = ExchangeUser.String()
|
||||
)
|
||||
|
||||
// Category describes the type of the data in scope.
|
||||
func (s exchangeScope) Category() exchangeCategory {
|
||||
return exchangeCategory(getIota(s, scopeKeyCategory))
|
||||
return exchangeCatAtoI(s[scopeKeyCategory])
|
||||
}
|
||||
|
||||
// Granularity describes the breadth of data in scope.
|
||||
func (s exchangeScope) Granularity() scopeGranularity {
|
||||
return granularityOf(s)
|
||||
// IncludeCategory checks whether the scope includes a
|
||||
// certain category of data.
|
||||
// Ex: to check if the scope includes mail data:
|
||||
// s.IncludesCategory(selector.ExchangeMail)
|
||||
func (s exchangeScope) IncludesCategory(cat exchangeCategory) bool {
|
||||
sCat := s.Category()
|
||||
if cat == ExchangeCategoryUnknown || sCat == ExchangeCategoryUnknown {
|
||||
return false
|
||||
}
|
||||
if cat == ExchangeUser || sCat == ExchangeUser {
|
||||
return true
|
||||
}
|
||||
switch sCat {
|
||||
case ExchangeContact, ExchangeContactFolder:
|
||||
return cat == ExchangeContact || cat == ExchangeContactFolder
|
||||
case ExchangeEvent:
|
||||
return cat == ExchangeEvent
|
||||
case ExchangeMail, ExchangeMailFolder:
|
||||
return cat == ExchangeMail || cat == ExchangeMailFolder
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s exchangeScope) UserID() string {
|
||||
return s[exchangeScopeKeyUserID]
|
||||
}
|
||||
|
||||
func (s exchangeScope) ContactID() string {
|
||||
return s[exchangeScopeKeyContactID]
|
||||
}
|
||||
|
||||
func (s exchangeScope) EventID() string {
|
||||
return s[exchangeScopeKeyEventID]
|
||||
}
|
||||
|
||||
func (s exchangeScope) FolderID() string {
|
||||
return s[exchangeScopeKeyFolderID]
|
||||
}
|
||||
|
||||
func (s exchangeScope) MessageID() string {
|
||||
return s[exchangeScopeKeyMessageID]
|
||||
// Get returns the data category in the scope. If the scope
|
||||
// contains all data types for a user, it'll return the
|
||||
// ExchangeUser category.
|
||||
func (s exchangeScope) Get(cat exchangeCategory) []string {
|
||||
v, ok := s[cat.String()]
|
||||
if !ok {
|
||||
return []string{None}
|
||||
}
|
||||
return strings.Split(v, ",")
|
||||
}
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
package selectors_test
|
||||
package selectors
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/alcionai/corso/pkg/selectors"
|
||||
)
|
||||
|
||||
type ExchangeSourceSuite struct {
|
||||
@ -17,10 +16,205 @@ func TestExchangeSourceSuite(t *testing.T) {
|
||||
suite.Run(t, new(ExchangeSourceSuite))
|
||||
}
|
||||
|
||||
func (suite *ExchangeSourceSuite) TestNewExchangeSource() {
|
||||
func (suite *ExchangeSourceSuite) TestNewExchangeBackup() {
|
||||
t := suite.T()
|
||||
es := selectors.NewExchange("tid")
|
||||
assert.Equal(t, es.TenantID, "tid")
|
||||
assert.Equal(t, es.Service(), selectors.ServiceExchange)
|
||||
assert.NotZero(t, es.Scopes())
|
||||
eb := NewExchangeBackup()
|
||||
assert.Equal(t, eb.Service, ServiceExchange)
|
||||
assert.Zero(t, eb.RestorePointID)
|
||||
assert.NotZero(t, eb.Scopes())
|
||||
}
|
||||
|
||||
func (suite *ExchangeSourceSuite) TestToExchangeBackup() {
|
||||
t := suite.T()
|
||||
eb := NewExchangeBackup()
|
||||
s := eb.Selector
|
||||
eb, err := s.ToExchangeBackup()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, eb.Service, ServiceExchange)
|
||||
assert.Zero(t, eb.RestorePointID)
|
||||
assert.NotZero(t, eb.Scopes())
|
||||
}
|
||||
|
||||
func (suite *ExchangeSourceSuite) TestNewExchangeRestore() {
|
||||
t := suite.T()
|
||||
er := NewExchangeRestore("rpid")
|
||||
assert.Equal(t, er.Service, ServiceExchange)
|
||||
assert.Equal(t, er.RestorePointID, "rpid")
|
||||
assert.NotZero(t, er.Scopes())
|
||||
}
|
||||
|
||||
func (suite *ExchangeSourceSuite) TestToExchangeRestore() {
|
||||
t := suite.T()
|
||||
eb := NewExchangeRestore("rpid")
|
||||
s := eb.Selector
|
||||
eb, err := s.ToExchangeRestore()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, eb.Service, ServiceExchange)
|
||||
assert.Equal(t, eb.RestorePointID, "rpid")
|
||||
assert.NotZero(t, eb.Scopes())
|
||||
}
|
||||
|
||||
func (suite *ExchangeSourceSuite) TestNewExchangeDestination() {
|
||||
t := suite.T()
|
||||
dest := NewExchangeDestination()
|
||||
assert.Len(t, dest, 0)
|
||||
}
|
||||
|
||||
func (suite *ExchangeSourceSuite) TestExchangeDestination_Set() {
|
||||
dest := NewExchangeDestination()
|
||||
|
||||
table := []exchangeCategory{
|
||||
ExchangeCategoryUnknown,
|
||||
ExchangeContact,
|
||||
ExchangeContactFolder,
|
||||
ExchangeEvent,
|
||||
ExchangeMail,
|
||||
ExchangeMailFolder,
|
||||
ExchangeUser,
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.String(), func(t *testing.T) {
|
||||
assert.NoError(t, dest.Set(test, "foo"))
|
||||
assert.Error(t, dest.Set(test, "foo"))
|
||||
})
|
||||
}
|
||||
|
||||
assert.NoError(suite.T(), dest.Set(ExchangeUser, ""))
|
||||
}
|
||||
|
||||
func (suite *ExchangeSourceSuite) TestExchangeDestination_GetOrDefault() {
|
||||
dest := NewExchangeDestination()
|
||||
|
||||
table := []exchangeCategory{
|
||||
ExchangeCategoryUnknown,
|
||||
ExchangeContact,
|
||||
ExchangeContactFolder,
|
||||
ExchangeEvent,
|
||||
ExchangeMail,
|
||||
ExchangeMailFolder,
|
||||
ExchangeUser,
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.String(), func(t *testing.T) {
|
||||
assert.Equal(t, "bar", dest.GetOrDefault(test, "bar"))
|
||||
assert.NoError(t, dest.Set(test, "foo"))
|
||||
assert.Equal(t, "foo", dest.GetOrDefault(test, "bar"))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var allScopesExceptUnknown = map[string]string{
|
||||
ExchangeContact.String(): All,
|
||||
ExchangeContactFolder.String(): All,
|
||||
ExchangeEvent.String(): All,
|
||||
ExchangeMail.String(): All,
|
||||
ExchangeMailFolder.String(): All,
|
||||
ExchangeUser.String(): All,
|
||||
}
|
||||
|
||||
func (suite *ExchangeSourceSuite) TestExchangeBackup_Scopes() {
|
||||
eb := NewExchangeBackup()
|
||||
eb.Includes = []map[string]string{allScopesExceptUnknown}
|
||||
// todo: swap the above for this
|
||||
// eb := NewExchangeBackup().IncludeUsers(All)
|
||||
|
||||
scopes := eb.Scopes()
|
||||
assert.Len(suite.T(), scopes, 1)
|
||||
assert.Equal(
|
||||
suite.T(),
|
||||
allScopesExceptUnknown,
|
||||
map[string]string(scopes[0]))
|
||||
}
|
||||
|
||||
func (suite *ExchangeSourceSuite) TestExchangeScope_Category() {
|
||||
table := []struct {
|
||||
is exchangeCategory
|
||||
expect exchangeCategory
|
||||
check assert.ComparisonAssertionFunc
|
||||
}{
|
||||
{ExchangeCategoryUnknown, ExchangeCategoryUnknown, assert.Equal},
|
||||
{ExchangeCategoryUnknown, ExchangeUser, assert.NotEqual},
|
||||
{ExchangeContact, ExchangeContact, assert.Equal},
|
||||
{ExchangeContact, ExchangeMailFolder, assert.NotEqual},
|
||||
{ExchangeContactFolder, ExchangeContactFolder, assert.Equal},
|
||||
{ExchangeContactFolder, ExchangeMailFolder, assert.NotEqual},
|
||||
{ExchangeEvent, ExchangeEvent, assert.Equal},
|
||||
{ExchangeEvent, ExchangeContact, assert.NotEqual},
|
||||
{ExchangeMail, ExchangeMail, assert.Equal},
|
||||
{ExchangeMail, ExchangeMailFolder, assert.NotEqual},
|
||||
{ExchangeMailFolder, ExchangeMailFolder, assert.Equal},
|
||||
{ExchangeMailFolder, ExchangeContactFolder, assert.NotEqual},
|
||||
{ExchangeUser, ExchangeUser, assert.Equal},
|
||||
{ExchangeUser, ExchangeCategoryUnknown, assert.NotEqual},
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.is.String()+test.expect.String(), func(t *testing.T) {
|
||||
eb := NewExchangeBackup()
|
||||
eb.Includes = []map[string]string{{scopeKeyCategory: test.is.String()}}
|
||||
scope := eb.Scopes()[0]
|
||||
test.check(t, test.expect, scope.Category())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *ExchangeSourceSuite) TestExchangeScope_IncludesCategory() {
|
||||
table := []struct {
|
||||
is exchangeCategory
|
||||
expect exchangeCategory
|
||||
check assert.BoolAssertionFunc
|
||||
}{
|
||||
{ExchangeCategoryUnknown, ExchangeCategoryUnknown, assert.False},
|
||||
{ExchangeCategoryUnknown, ExchangeUser, assert.False},
|
||||
{ExchangeContact, ExchangeContactFolder, assert.True},
|
||||
{ExchangeContact, ExchangeMailFolder, assert.False},
|
||||
{ExchangeContactFolder, ExchangeContact, assert.True},
|
||||
{ExchangeContactFolder, ExchangeMailFolder, assert.False},
|
||||
{ExchangeEvent, ExchangeUser, assert.True},
|
||||
{ExchangeEvent, ExchangeContact, assert.False},
|
||||
{ExchangeMail, ExchangeMailFolder, assert.True},
|
||||
{ExchangeMail, ExchangeContact, assert.False},
|
||||
{ExchangeMailFolder, ExchangeMail, assert.True},
|
||||
{ExchangeMailFolder, ExchangeContactFolder, assert.False},
|
||||
{ExchangeUser, ExchangeUser, assert.True},
|
||||
{ExchangeUser, ExchangeCategoryUnknown, assert.False},
|
||||
{ExchangeUser, ExchangeMail, assert.True},
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.is.String()+test.expect.String(), func(t *testing.T) {
|
||||
eb := NewExchangeBackup()
|
||||
eb.Includes = []map[string]string{{scopeKeyCategory: test.is.String()}}
|
||||
scope := eb.Scopes()[0]
|
||||
test.check(t, scope.IncludesCategory(test.expect))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *ExchangeSourceSuite) TestExchangeScope_Get() {
|
||||
eb := NewExchangeBackup()
|
||||
eb.Includes = []map[string]string{allScopesExceptUnknown}
|
||||
// todo: swap the above for this
|
||||
// eb := NewExchangeBackup().IncludeUsers(All)
|
||||
|
||||
scope := eb.Scopes()[0]
|
||||
|
||||
table := []exchangeCategory{
|
||||
ExchangeContact,
|
||||
ExchangeContactFolder,
|
||||
ExchangeEvent,
|
||||
ExchangeMail,
|
||||
ExchangeMailFolder,
|
||||
ExchangeUser,
|
||||
}
|
||||
|
||||
assert.Equal(
|
||||
suite.T(),
|
||||
[]string{None},
|
||||
scope.Get(ExchangeCategoryUnknown))
|
||||
|
||||
expect := []string{All}
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.String(), func(t *testing.T) {
|
||||
assert.Equal(t, expect, scope.Get(test))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
29
src/pkg/selectors/exchangecategory_string.go
Normal file
29
src/pkg/selectors/exchangecategory_string.go
Normal file
@ -0,0 +1,29 @@
|
||||
// Code generated by "stringer -type=exchangeCategory"; DO NOT EDIT.
|
||||
|
||||
package selectors
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[ExchangeCategoryUnknown-0]
|
||||
_ = x[ExchangeContact-1]
|
||||
_ = x[ExchangeContactFolder-2]
|
||||
_ = x[ExchangeEvent-3]
|
||||
_ = x[ExchangeMail-4]
|
||||
_ = x[ExchangeMailFolder-5]
|
||||
_ = x[ExchangeUser-6]
|
||||
}
|
||||
|
||||
const _exchangeCategory_name = "ExchangeCategoryUnknownExchangeContactExchangeContactFolderExchangeEventExchangeMailExchangeMailFolderExchangeUser"
|
||||
|
||||
var _exchangeCategory_index = [...]uint8{0, 23, 38, 59, 72, 84, 102, 114}
|
||||
|
||||
func (i exchangeCategory) String() string {
|
||||
if i < 0 || i >= exchangeCategory(len(_exchangeCategory_index)-1) {
|
||||
return "exchangeCategory(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _exchangeCategory_name[_exchangeCategory_index[i]:_exchangeCategory_index[i+1]]
|
||||
}
|
||||
@ -1,8 +1,6 @@
|
||||
package selectors
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@ -17,71 +15,57 @@ const (
|
||||
var ErrorBadSelectorCast = errors.New("wrong selector service type")
|
||||
|
||||
const (
|
||||
scopeKeyGranularity = "granularity"
|
||||
scopeKeyCategory = "category"
|
||||
scopeKeyCategory = "category"
|
||||
)
|
||||
|
||||
const (
|
||||
// All is the wildcard value used to express "all data of <type>"
|
||||
// Ex: Events(u1, All) => all events for user u1.
|
||||
All = "*"
|
||||
// Ex: {user: u1, events: All) => all events for user u1.
|
||||
All = "ß∂ƒ∑´®≈ç√¬˜"
|
||||
// None is usesd to express "no data of <type>"
|
||||
// Ex: {user: u1, events: None} => no events for user u1.
|
||||
None = "√ç≈œ´∆¬˚¨π"
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Selector
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// The core selector. Has no api for setting or retrieving data.
|
||||
// Is only used to pass along more specific selector instances.
|
||||
type Selector struct {
|
||||
TenantID string // The tenant making the request.
|
||||
service service // The service scope of the data. Exchange, Teams, Sharepoint, etc.
|
||||
scopes []map[string]string // A slice of scopes. Expected to get cast to fooScope within each service handler.
|
||||
RestorePointID string `json:"restorePointID,omitempty"` // A restore point id, used only by restore operations.
|
||||
Service service `json:"service,omitempty"` // The service scope of the data. Exchange, Teams, Sharepoint, etc.
|
||||
Excludes []map[string]string `json:"exclusions,omitempty"` // A slice of exclusions. Each exclusion applies to all inclusions.
|
||||
Includes []map[string]string `json:"scopes,omitempty"` // A slice of inclusions. Expected to get cast to a service wrapper within each service handler.
|
||||
}
|
||||
|
||||
// helper for specific selector instance constructors.
|
||||
func newSelector(tenantID string, s service) Selector {
|
||||
func newSelector(s service, restorePointID string) Selector {
|
||||
return Selector{
|
||||
TenantID: tenantID,
|
||||
service: s,
|
||||
scopes: []map[string]string{},
|
||||
RestorePointID: restorePointID,
|
||||
Service: s,
|
||||
Excludes: []map[string]string{},
|
||||
Includes: []map[string]string{},
|
||||
}
|
||||
}
|
||||
|
||||
// Service return the service enum for the selector.
|
||||
func (s Selector) Service() service {
|
||||
return s.service
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
// Destination
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type Destination map[string]string
|
||||
|
||||
var ErrorDestinationAlreadySet = errors.New("destination is already declared")
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func badCastErr(cast, is service) error {
|
||||
return errors.Wrapf(ErrorBadSelectorCast, "%s service is not %s", cast, is)
|
||||
}
|
||||
|
||||
type scopeGranularity int
|
||||
|
||||
// granularity expresses the breadth of the request
|
||||
const (
|
||||
GranularityUnknown scopeGranularity = iota
|
||||
SingleItem
|
||||
AllIn
|
||||
)
|
||||
|
||||
// String complies with the stringer interface, so that granularities
|
||||
// can be added into the scope map.
|
||||
func (g scopeGranularity) String() string {
|
||||
return strconv.Itoa(int(g))
|
||||
}
|
||||
|
||||
func granularityOf(selector map[string]string) scopeGranularity {
|
||||
return scopeGranularity(getIota(selector, scopeKeyGranularity))
|
||||
}
|
||||
|
||||
// retrieves the iota, stored as a string, and transforms it to
|
||||
// an int. Any errors will return a 0 by default.
|
||||
func getIota(m map[string]string, key string) int {
|
||||
v, ok := m[key]
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
i, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return i
|
||||
func existingDestinationErr(category, is string) error {
|
||||
return errors.Wrapf(ErrorDestinationAlreadySet, "%s destination already set to %s", category, is)
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package selectors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -18,48 +17,19 @@ func TestSelectorSuite(t *testing.T) {
|
||||
|
||||
func (suite *SelectorSuite) TestNewSelector() {
|
||||
t := suite.T()
|
||||
s := newSelector("tid", ServiceUnknown)
|
||||
s := newSelector(ServiceUnknown, "rpid")
|
||||
assert.NotNil(t, s)
|
||||
assert.Equal(t, s.TenantID, "tid")
|
||||
assert.Equal(t, s.service, ServiceUnknown)
|
||||
assert.NotNil(t, s.scopes)
|
||||
}
|
||||
|
||||
func (suite *SelectorSuite) TestSelector_Service() {
|
||||
table := []service{
|
||||
ServiceUnknown,
|
||||
ServiceExchange,
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.T().Run(fmt.Sprintf("testing %d", test), func(t *testing.T) {
|
||||
s := newSelector("tid", test)
|
||||
assert.Equal(t, s.Service(), test)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *SelectorSuite) TestGetIota() {
|
||||
table := []struct {
|
||||
name string
|
||||
val string
|
||||
expect int
|
||||
}{
|
||||
{"zero", "0", 0},
|
||||
{"positive", "1", 1},
|
||||
{"negative", "-1", -1},
|
||||
{"empty", "", 0},
|
||||
{"NaN", "fnords", 0},
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
m := map[string]string{"test": test.val}
|
||||
result := getIota(m, "test")
|
||||
assert.Equal(t, result, test.expect)
|
||||
})
|
||||
}
|
||||
assert.Equal(t, s.Service, ServiceUnknown)
|
||||
assert.Equal(t, s.RestorePointID, "rpid")
|
||||
assert.NotNil(t, s.Includes)
|
||||
}
|
||||
|
||||
func (suite *SelectorSuite) TestBadCastErr() {
|
||||
err := badCastErr(ServiceUnknown, ServiceExchange)
|
||||
assert.Error(suite.T(), err)
|
||||
}
|
||||
|
||||
func (suite *SelectorSuite) TestExistingDestinationErr() {
|
||||
err := existingDestinationErr("foo", "bar")
|
||||
assert.Error(suite.T(), err)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user