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.
Этот коммит содержится в:
коммит произвёл
Martin Kraft
родитель
7d5e85e413
Коммит
60cf74352f
@@ -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{
|
||||
|
||||
Ссылка в новой задаче
Block a user