MM-10140: API Implementation for Schemes related Endpoints (#8615)

* Implement basic scheme CRUD endpoints.

* Get All Schemes (Paged) Endpoint and store plumbing.

* Add get teams/channels for schemes.

* Fix unit tests.

* Review fixes.

* More review fixes.
Этот коммит содержится в:
George Goldberg
2018-05-03 14:00:26 +01:00
коммит произвёл Martin Kraft
родитель 7d5e85e413
Коммит 60cf74352f
22 изменённых файлов: 1303 добавлений и 5 удалений

Просмотреть файл

@@ -292,3 +292,9 @@ func (s *LayeredSchemeStore) Delete(schemeId string) StoreChannel {
return supplier.SchemeDelete(s.TmpContext, schemeId)
})
}
func (s *LayeredSchemeStore) GetAllPage(scope string, offset int, limit int) StoreChannel {
return s.RunQuery(func(supplier LayeredStoreSupplier) *LayeredStoreSupplierResult {
return supplier.SchemeGetAllPage(s.TmpContext, scope, offset, limit)
})
}

Просмотреть файл

@@ -42,4 +42,5 @@ type LayeredStoreSupplier interface {
SchemeSave(ctx context.Context, scheme *model.Scheme, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
SchemeGet(ctx context.Context, schemeId string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
SchemeDelete(ctx context.Context, schemeId string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
SchemeGetAllPage(ctx context.Context, scope string, offset int, limit int, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
}

Просмотреть файл

@@ -42,3 +42,7 @@ func (s *LocalCacheSupplier) SchemeDelete(ctx context.Context, schemeId string,
return s.Next().SchemeDelete(ctx, schemeId, hints...)
}
func (s *LocalCacheSupplier) SchemeGetAllPage(ctx context.Context, scope string, offset int, limit int, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
return s.Next().SchemeGetAllPage(ctx, scope, offset, limit, hints...)
}

Просмотреть файл

@@ -23,3 +23,8 @@ func (s *RedisSupplier) SchemeDelete(ctx context.Context, schemeId string, hints
// TODO: Redis caching.
return s.Next().SchemeDelete(ctx, schemeId, hints...)
}
func (s *RedisSupplier) SchemeGetAllPage(ctx context.Context, scope string, offset int, limit int, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
// TODO: Redis caching.
return s.Next().SchemeGetAllPage(ctx, scope, offset, limit, hints...)
}

Просмотреть файл

@@ -1730,7 +1730,7 @@ func (s SqlChannelStore) GetMembersByIds(channelId string, userIds []string) sto
func (s SqlChannelStore) GetChannelsByScheme(schemeId string, offset int, limit int) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
var channels []*model.Channel
var channels model.ChannelList
_, err := s.GetReplica().Select(&channels, "SELECT * FROM Channels WHERE SchemeId = :SchemeId ORDER BY DisplayName LIMIT :Limit OFFSET :Offset", map[string]interface{}{"SchemeId": schemeId, "Offset": offset, "Limit": limit})
if err != nil {
result.Err = model.NewAppError("SqlChannelStore.GetChannelsByScheme", "store.sql_channel.get_by_scheme.app_error", nil, "schemeId="+schemeId+" "+err.Error(), http.StatusInternalServerError)

Просмотреть файл

@@ -270,3 +270,22 @@ func (s *SqlSupplier) SchemeDelete(ctx context.Context, schemeId string, hints .
return result
}
func (s *SqlSupplier) SchemeGetAllPage(ctx context.Context, scope string, offset int, limit int, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
result := store.NewSupplierResult()
var schemes []*model.Scheme
scopeClause := ""
if len(scope) > 0 {
scopeClause = " AND Scope=:Scope "
}
if _, err := s.GetReplica().Select(&schemes, "SELECT * from Schemes WHERE DeleteAt = 0 "+scopeClause+" ORDER BY CreateAt DESC LIMIT :Limit OFFSET :Offset", map[string]interface{}{"Limit": limit, "Offset": offset, "Scope": scope}); err != nil {
result.Err = model.NewAppError("SqlSchemeStore.Get", "store.sql_scheme.get.app_error", nil, err.Error(), http.StatusInternalServerError)
}
result.Data = schemes
return result
}

Просмотреть файл

@@ -485,5 +485,6 @@ type RoleStore interface {
type SchemeStore interface {
Save(scheme *model.Scheme) StoreChannel
Get(schemeId string) StoreChannel
GetAllPage(scope string, offset int, limit int) StoreChannel
Delete(schemeId string) StoreChannel
}

Просмотреть файл

@@ -2239,18 +2239,18 @@ func testChannelStoreGetChannelsByScheme(t *testing.T, ss store.Store) {
// Get the channels by a valid Scheme ID.
res1 := <-ss.Channel().GetChannelsByScheme(s1.Id, 0, 100)
assert.Nil(t, res1.Err)
d1 := res1.Data.([]*model.Channel)
d1 := res1.Data.(model.ChannelList)
assert.Len(t, d1, 2)
// Get the channels by a valid Scheme ID where there aren't any matching Channel.
res2 := <-ss.Channel().GetChannelsByScheme(s2.Id, 0, 100)
assert.Nil(t, res2.Err)
d2 := res2.Data.([]*model.Channel)
d2 := res2.Data.(model.ChannelList)
assert.Len(t, d2, 0)
// Get the channels by an invalid Scheme ID.
res3 := <-ss.Channel().GetChannelsByScheme(model.NewId(), 0, 100)
assert.Nil(t, res3.Err)
d3 := res3.Data.([]*model.Channel)
d3 := res3.Data.(model.ChannelList)
assert.Len(t, d3, 0)
}

Просмотреть файл

@@ -632,6 +632,29 @@ func (_m *LayeredStoreDatabaseLayer) SchemeGet(ctx context.Context, schemeId str
return r0
}
// SchemeGetAllPage provides a mock function with given fields: ctx, scope, offset, limit, hints
func (_m *LayeredStoreDatabaseLayer) SchemeGetAllPage(ctx context.Context, scope string, offset int, limit int, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
_va := make([]interface{}, len(hints))
for _i := range hints {
_va[_i] = hints[_i]
}
var _ca []interface{}
_ca = append(_ca, ctx, scope, offset, limit)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
var r0 *store.LayeredStoreSupplierResult
if rf, ok := ret.Get(0).(func(context.Context, string, int, int, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
r0 = rf(ctx, scope, offset, limit, hints...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
}
}
return r0
}
// SchemeSave provides a mock function with given fields: ctx, scheme, hints
func (_m *LayeredStoreDatabaseLayer) SchemeSave(ctx context.Context, scheme *model.Scheme, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
_va := make([]interface{}, len(hints))

Просмотреть файл

@@ -329,6 +329,29 @@ func (_m *LayeredStoreSupplier) SchemeGet(ctx context.Context, schemeId string,
return r0
}
// SchemeGetAllPage provides a mock function with given fields: ctx, scope, offset, limit, hints
func (_m *LayeredStoreSupplier) SchemeGetAllPage(ctx context.Context, scope string, offset int, limit int, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
_va := make([]interface{}, len(hints))
for _i := range hints {
_va[_i] = hints[_i]
}
var _ca []interface{}
_ca = append(_ca, ctx, scope, offset, limit)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
var r0 *store.LayeredStoreSupplierResult
if rf, ok := ret.Get(0).(func(context.Context, string, int, int, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
r0 = rf(ctx, scope, offset, limit, hints...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
}
}
return r0
}
// SchemeSave provides a mock function with given fields: ctx, scheme, hints
func (_m *LayeredStoreSupplier) SchemeSave(ctx context.Context, scheme *model.Scheme, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
_va := make([]interface{}, len(hints))

Просмотреть файл

@@ -45,6 +45,22 @@ func (_m *SchemeStore) Get(schemeId string) store.StoreChannel {
return r0
}
// GetAllPage provides a mock function with given fields: scope, offset, limit
func (_m *SchemeStore) GetAllPage(scope string, offset int, limit int) store.StoreChannel {
ret := _m.Called(scope, offset, limit)
var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func(string, int, int) store.StoreChannel); ok {
r0 = rf(scope, offset, limit)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(store.StoreChannel)
}
}
return r0
}
// Save provides a mock function with given fields: scheme
func (_m *SchemeStore) Save(scheme *model.Scheme) store.StoreChannel {
ret := _m.Called(scheme)

Просмотреть файл

@@ -143,6 +143,20 @@ func (_m *SqlStore) CreateColumnIfNotExists(tableName string, columnName string,
return r0
}
// CreateColumnIfNotExistsNoDefault provides a mock function with given fields: tableName, columnName, mySqlColType, postgresColType
func (_m *SqlStore) CreateColumnIfNotExistsNoDefault(tableName string, columnName string, mySqlColType string, postgresColType string) bool {
ret := _m.Called(tableName, columnName, mySqlColType, postgresColType)
var r0 bool
if rf, ok := ret.Get(0).(func(string, string, string, string) bool); ok {
r0 = rf(tableName, columnName, mySqlColType, postgresColType)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// CreateCompositeIndexIfNotExists provides a mock function with given fields: indexName, tableName, columnNames
func (_m *SqlStore) CreateCompositeIndexIfNotExists(indexName string, tableName string, columnNames []string) bool {
ret := _m.Called(indexName, tableName, columnNames)

Просмотреть файл

@@ -17,6 +17,7 @@ func TestSchemeStore(t *testing.T, ss store.Store) {
t.Run("Save", func(t *testing.T) { testSchemeStoreSave(t, ss) })
t.Run("Get", func(t *testing.T) { testSchemeStoreGet(t, ss) })
t.Run("GetAllPage", func(t *testing.T) { testSchemeStoreGetAllPage(t, ss) })
t.Run("Delete", func(t *testing.T) { testSchemeStoreDelete(t, ss) })
}
@@ -171,6 +172,66 @@ func testSchemeStoreGet(t *testing.T, ss store.Store) {
assert.NotNil(t, res3.Err)
}
func testSchemeStoreGetAllPage(t *testing.T, ss store.Store) {
// Save a scheme to test with.
schemes := []*model.Scheme{
{
Name: model.NewId(),
Description: model.NewId(),
Scope: model.SCHEME_SCOPE_TEAM,
},
{
Name: model.NewId(),
Description: model.NewId(),
Scope: model.SCHEME_SCOPE_CHANNEL,
},
{
Name: model.NewId(),
Description: model.NewId(),
Scope: model.SCHEME_SCOPE_TEAM,
},
{
Name: model.NewId(),
Description: model.NewId(),
Scope: model.SCHEME_SCOPE_CHANNEL,
},
}
for _, scheme := range schemes {
store.Must(ss.Scheme().Save(scheme))
}
r1 := <-ss.Scheme().GetAllPage("", 0, 2)
assert.Nil(t, r1.Err)
s1 := r1.Data.([]*model.Scheme)
assert.Len(t, s1, 2)
r2 := <-ss.Scheme().GetAllPage("", 2, 2)
assert.Nil(t, r2.Err)
s2 := r2.Data.([]*model.Scheme)
assert.Len(t, s2, 2)
assert.NotEqual(t, s1[0].Name, s2[0].Name)
assert.NotEqual(t, s1[0].Name, s2[1].Name)
assert.NotEqual(t, s1[1].Name, s2[0].Name)
assert.NotEqual(t, s1[1].Name, s2[1].Name)
r3 := <-ss.Scheme().GetAllPage("team", 0, 1000)
assert.Nil(t, r3.Err)
s3 := r3.Data.([]*model.Scheme)
assert.NotZero(t, len(s3))
for _, s := range s3 {
assert.Equal(t, "team", s.Scope)
}
r4 := <-ss.Scheme().GetAllPage("channel", 0, 1000)
assert.Nil(t, r4.Err)
s4 := r4.Data.([]*model.Scheme)
assert.NotZero(t, len(s4))
for _, s := range s4 {
assert.Equal(t, "channel", s.Scope)
}
}
func testSchemeStoreDelete(t *testing.T, ss store.Store) {
// Save a new scheme.
s1 := &model.Scheme{