GraphQL (part 1): Store layer (#19465)
We add the necessary store methods to use GraphQL ```release-note NONE ```
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
e9a777f4e2
Коммит
a733fb840d
@@ -255,3 +255,24 @@ func (s SqlChannelMemberHistoryStore) PermanentDeleteBatch(endTime int64, limit
|
||||
}
|
||||
return rowsAffected, nil
|
||||
}
|
||||
|
||||
// GetChannelsLeftSince returns list of channels that the user has left after a given time,
|
||||
// but has not rejoined again.
|
||||
func (s SqlChannelMemberHistoryStore) GetChannelsLeftSince(userID string, since int64) ([]string, error) {
|
||||
query, params, err := s.getQueryBuilder().
|
||||
Select("ChannelId").
|
||||
From("ChannelMemberHistory").
|
||||
GroupBy("ChannelId").
|
||||
Where(sq.Eq{"UserId": userID}).
|
||||
Having("MAX(LeaveTime) > MAX(JoinTime) AND MAX(LeaveTime) IS NOT NULL AND MAX(LeaveTime) >= ?", since).ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "channel_member_history_to_sql")
|
||||
}
|
||||
channelIds := []string{}
|
||||
err = s.GetReplicaX().Select(&channelIds, query, params...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetChannelsLeftSince userId=%s since=%d", userID, since)
|
||||
}
|
||||
|
||||
return channelIds, nil
|
||||
}
|
||||
|
||||
@@ -1084,37 +1084,105 @@ func (s SqlChannelStore) PermanentDeleteMembersByChannel(channelId string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetChannels(teamId string, userId string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, error) {
|
||||
func (s SqlChannelStore) GetChannels(teamId string, userId string, opts *model.ChannelSearchOpts) (model.ChannelList, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select("Channels.*").
|
||||
From("Channels, ChannelMembers").
|
||||
Select("ch.*").
|
||||
From("Channels ch, ChannelMembers cm").
|
||||
Where(
|
||||
sq.And{
|
||||
sq.Expr("Id = ChannelId"),
|
||||
sq.Eq{"UserId": userId},
|
||||
sq.Expr("ch.Id = cm.ChannelId"),
|
||||
sq.Eq{"cm.UserId": userId},
|
||||
},
|
||||
).
|
||||
OrderBy("DisplayName")
|
||||
OrderBy("ch.DisplayName")
|
||||
|
||||
if teamId != "" {
|
||||
query = query.Where(sq.Or{
|
||||
sq.Eq{"TeamId": teamId},
|
||||
sq.Eq{"TeamId": ""},
|
||||
sq.Eq{"ch.TeamId": teamId},
|
||||
sq.Eq{"ch.TeamId": ""},
|
||||
})
|
||||
}
|
||||
|
||||
if includeDeleted {
|
||||
if lastDeleteAt != 0 {
|
||||
if opts.IncludeDeleted {
|
||||
if opts.LastDeleteAt != 0 {
|
||||
// We filter by non-archived, and archived >= a timestamp.
|
||||
query = query.Where(sq.Or{
|
||||
sq.Eq{"DeleteAt": 0},
|
||||
sq.GtOrEq{"DeleteAt": lastDeleteAt},
|
||||
sq.Eq{"ch.DeleteAt": 0},
|
||||
sq.GtOrEq{"ch.DeleteAt": opts.LastDeleteAt},
|
||||
})
|
||||
}
|
||||
// If lastDeleteAt is not set, we include everything. That means no filter is needed.
|
||||
// If opts.LastDeleteAt is not set, we include everything. That means no filter is needed.
|
||||
} else {
|
||||
// Don't include archived channels.
|
||||
query = query.Where(sq.Eq{"DeleteAt": 0})
|
||||
query = query.Where(sq.Eq{"ch.DeleteAt": 0})
|
||||
}
|
||||
|
||||
if opts.LastUpdateAt > 0 {
|
||||
query = query.Where(sq.GtOrEq{"ch.UpdateAt": opts.LastUpdateAt})
|
||||
}
|
||||
|
||||
channels := model.ChannelList{}
|
||||
sql, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "getchannels_tosql")
|
||||
}
|
||||
|
||||
err = s.GetReplicaX().Select(&channels, sql, args...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get channels with TeamId=%s and UserId=%s", teamId, userId)
|
||||
}
|
||||
|
||||
if len(channels) == 0 {
|
||||
return nil, store.NewErrNotFound("Channel", "userId="+userId)
|
||||
}
|
||||
|
||||
return channels, nil
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetChannelsWithCursor(teamId string, userId string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select("ch.*").
|
||||
From("Channels ch, ChannelMembers cm").
|
||||
Where(
|
||||
sq.And{
|
||||
sq.Expr("ch.Id = cm.ChannelId"),
|
||||
sq.Eq{"cm.UserId": userId},
|
||||
},
|
||||
).
|
||||
OrderBy("ch.Id")
|
||||
|
||||
if opts.PerPage != nil {
|
||||
// The limit is verified at the GraphQL layer.
|
||||
query = query.Limit(uint64(*opts.PerPage))
|
||||
}
|
||||
|
||||
if afterChannelID != "" {
|
||||
query = query.Where(sq.Gt{"ch.Id": afterChannelID})
|
||||
}
|
||||
|
||||
if teamId != "" {
|
||||
query = query.Where(sq.Or{
|
||||
sq.Eq{"ch.TeamId": teamId},
|
||||
sq.Eq{"ch.TeamId": ""},
|
||||
})
|
||||
}
|
||||
|
||||
if opts.IncludeDeleted {
|
||||
if opts.LastDeleteAt != 0 {
|
||||
// We filter by non-archived, and archived >= a timestamp.
|
||||
query = query.Where(sq.Or{
|
||||
sq.Eq{"ch.DeleteAt": 0},
|
||||
sq.GtOrEq{"ch.DeleteAt": opts.LastDeleteAt},
|
||||
})
|
||||
}
|
||||
// If opts.LastDeleteAt is not set, we include everything. That means no filter is needed.
|
||||
} else {
|
||||
// Don't include archived channels.
|
||||
query = query.Where(sq.Eq{"ch.DeleteAt": 0})
|
||||
}
|
||||
|
||||
if opts.LastUpdateAt > 0 {
|
||||
query = query.Where(sq.GtOrEq{"ch.UpdateAt": opts.LastUpdateAt})
|
||||
}
|
||||
|
||||
channels := model.ChannelList{}
|
||||
@@ -2773,6 +2841,56 @@ func (s SqlChannelStore) GetMembersForUser(teamId string, userId string) (model.
|
||||
return dbMembers.ToModel(), nil
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetMembersForUserWithCursor(userID, afterChannel, afterUser string, limit, lastUpdateAt int) (model.ChannelMembers, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select("ChannelMembers.*",
|
||||
"TeamScheme.DefaultChannelGuestRole TeamSchemeDefaultGuestRole",
|
||||
"TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole",
|
||||
"TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole",
|
||||
"ChannelScheme.DefaultChannelGuestRole ChannelSchemeDefaultGuestRole",
|
||||
"ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole",
|
||||
"ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole").
|
||||
From("ChannelMembers").
|
||||
InnerJoin("Channels ON ChannelMembers.ChannelId = Channels.Id").
|
||||
LeftJoin("Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id").
|
||||
LeftJoin("Teams ON Channels.TeamId = Teams.Id").
|
||||
LeftJoin("Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id").
|
||||
Where(sq.Eq{
|
||||
"ChannelMembers.UserId": userID,
|
||||
"Channels.DeleteAt": 0,
|
||||
}).
|
||||
OrderBy("ChannelId, UserId ASC").
|
||||
// The limit is verified at the GraphQL layer.
|
||||
Limit(uint64(limit))
|
||||
|
||||
if afterChannel != "" && afterUser != "" {
|
||||
query = query.Where(sq.Or{
|
||||
sq.Gt{"ChannelMembers.ChannelId": afterChannel},
|
||||
sq.And{
|
||||
sq.Eq{"ChannelMembers.ChannelId": afterChannel},
|
||||
sq.Gt{"ChannelMembers.UserId": afterUser},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if lastUpdateAt != 0 {
|
||||
query = query.Where(sq.GtOrEq{"ChannelMembers.LastUpdateAt": lastUpdateAt})
|
||||
}
|
||||
|
||||
queryString, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getMembersForUserWithCursor_tosql")
|
||||
}
|
||||
|
||||
dbMembers := channelMemberWithSchemeRolesList{}
|
||||
err = s.GetReplicaX().Select(&dbMembers, queryString, args...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to find ChannelMembers data with userId=%s", userID)
|
||||
}
|
||||
|
||||
return dbMembers.ToModel(), nil
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetMembersForUserWithPagination(userId string, page, perPage int) (model.ChannelMembersWithTeamData, error) {
|
||||
dbMembers := channelMemberWithTeamWithSchemeRolesList{}
|
||||
offset := page * perPage
|
||||
@@ -3470,6 +3588,43 @@ func (s SqlChannelStore) GetMembersByChannelIds(channelIds []string, userId stri
|
||||
return dbMembers.ToModel(), nil
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetMembersInfoByChannelIds(channelIDs []string) (map[string][]*model.User, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select("Channels.Id as ChannelId, Users.Id, Users.FirstName, Users.LastName, Users.Nickname, Users.Username").
|
||||
From("ChannelMembers as cm").
|
||||
Join("Channels ON cm.ChannelId = Channels.Id").
|
||||
Join("Users ON cm.UserId = Users.Id").
|
||||
Where(sq.Eq{
|
||||
"Channels.Id": channelIDs,
|
||||
"Channels.DeleteAt": 0,
|
||||
})
|
||||
|
||||
sql, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "dm_gm_names_tosql")
|
||||
}
|
||||
|
||||
res := []*struct {
|
||||
model.User
|
||||
ChannelId string
|
||||
}{}
|
||||
|
||||
if err := s.GetReplicaX().Select(&res, sql, args...); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to find channels display name")
|
||||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
return nil, store.NewErrNotFound("User", fmt.Sprintf("%v", channelIDs))
|
||||
}
|
||||
|
||||
userInfo := make(map[string][]*model.User)
|
||||
for _, item := range res {
|
||||
userInfo[item.ChannelId] = append(userInfo[item.ChannelId], &item.User)
|
||||
}
|
||||
|
||||
return userInfo, nil
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetChannelsByScheme(schemeId string, offset int, limit int) (model.ChannelList, error) {
|
||||
channels := model.ChannelList{}
|
||||
err := s.GetReplicaX().Select(&channels, "SELECT * FROM Channels WHERE SchemeId = ? ORDER BY DisplayName LIMIT ? OFFSET ?", schemeId, limit, offset)
|
||||
|
||||
Ссылка в новой задаче
Block a user