2019-11-29 12:59:40 +01:00
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
2019-01-10 15:17:31 -05:00
package sqlstore
import (
"database/sql"
"fmt"
2019-06-17 09:51:56 -04:00
"strings"
2019-01-10 15:17:31 -05:00
2019-06-17 09:51:56 -04:00
sq "github.com/Masterminds/squirrel"
2020-06-02 12:28:29 -04:00
"github.com/pkg/errors"
2019-05-10 11:47:21 -04:00
2021-07-22 12:21:47 +05:30
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/store"
2019-01-10 15:17:31 -05:00
)
2019-05-10 11:47:21 -04:00
type selectType int
const (
selectGroups selectType = iota
selectCountGroups
)
2019-01-10 15:17:31 -05:00
type groupTeam struct {
model . GroupSyncable
TeamId string ` db:"TeamId" `
}
type groupChannel struct {
model . GroupSyncable
ChannelId string ` db:"ChannelId" `
}
type groupTeamJoin struct {
groupTeam
TeamDisplayName string ` db:"TeamDisplayName" `
TeamType string ` db:"TeamType" `
}
type groupChannelJoin struct {
groupChannel
ChannelDisplayName string ` db:"ChannelDisplayName" `
TeamDisplayName string ` db:"TeamDisplayName" `
TeamType string ` db:"TeamType" `
ChannelType string ` db:"ChannelType" `
TeamID string ` db:"TeamId" `
}
2019-05-28 16:17:10 +02:00
type SqlGroupStore struct {
2020-12-02 12:06:23 +01:00
* SqlStore
2019-05-28 16:17:10 +02:00
}
2020-12-02 12:06:23 +01:00
func newSqlGroupStore ( sqlStore * SqlStore ) store . GroupStore {
s := & SqlGroupStore { SqlStore : sqlStore }
for _ , db := range sqlStore . GetAllConns ( ) {
2019-01-10 15:17:31 -05:00
groups := db . AddTableWithName ( model . Group { } , "UserGroups" ) . SetKeys ( false , "Id" )
groups . ColMap ( "Id" ) . SetMaxSize ( 26 )
groups . ColMap ( "Name" ) . SetMaxSize ( model . GroupNameMaxLength ) . SetUnique ( true )
groups . ColMap ( "DisplayName" ) . SetMaxSize ( model . GroupDisplayNameMaxLength )
groups . ColMap ( "Description" ) . SetMaxSize ( model . GroupDescriptionMaxLength )
groups . ColMap ( "Source" ) . SetMaxSize ( model . GroupSourceMaxLength )
groups . ColMap ( "RemoteId" ) . SetMaxSize ( model . GroupRemoteIDMaxLength )
groups . SetUniqueTogether ( "Source" , "RemoteId" )
groupMembers := db . AddTableWithName ( model . GroupMember { } , "GroupMembers" ) . SetKeys ( false , "GroupId" , "UserId" )
groupMembers . ColMap ( "GroupId" ) . SetMaxSize ( 26 )
groupMembers . ColMap ( "UserId" ) . SetMaxSize ( 26 )
groupTeams := db . AddTableWithName ( groupTeam { } , "GroupTeams" ) . SetKeys ( false , "GroupId" , "TeamId" )
groupTeams . ColMap ( "GroupId" ) . SetMaxSize ( 26 )
groupTeams . ColMap ( "TeamId" ) . SetMaxSize ( 26 )
groupChannels := db . AddTableWithName ( groupChannel { } , "GroupChannels" ) . SetKeys ( false , "GroupId" , "ChannelId" )
groupChannels . ColMap ( "GroupId" ) . SetMaxSize ( 26 )
groupChannels . ColMap ( "ChannelId" ) . SetMaxSize ( 26 )
}
2019-05-28 16:17:10 +02:00
return s
2019-01-10 15:17:31 -05:00
}
2020-03-03 11:45:49 +01:00
func ( s * SqlGroupStore ) createIndexesIfNotExists ( ) {
2019-01-10 15:17:31 -05:00
s . CreateIndexIfNotExists ( "idx_groupmembers_create_at" , "GroupMembers" , "CreateAt" )
s . CreateIndexIfNotExists ( "idx_usergroups_remote_id" , "UserGroups" , "RemoteId" )
s . CreateIndexIfNotExists ( "idx_usergroups_delete_at" , "UserGroups" , "DeleteAt" )
2019-08-14 14:58:01 +03:00
s . CreateIndexIfNotExists ( "idx_groupteams_teamid" , "GroupTeams" , "TeamId" )
s . CreateIndexIfNotExists ( "idx_groupchannels_channelid" , "GroupChannels" , "ChannelId" )
s . CreateColumnIfNotExistsNoDefault ( "Channels" , "GroupConstrained" , "tinyint(1)" , "boolean" )
s . CreateColumnIfNotExistsNoDefault ( "Teams" , "GroupConstrained" , "tinyint(1)" , "boolean" )
2020-01-10 12:19:39 -05:00
s . CreateIndexIfNotExists ( "idx_groupteams_schemeadmin" , "GroupTeams" , "SchemeAdmin" )
s . CreateIndexIfNotExists ( "idx_groupchannels_schemeadmin" , "GroupChannels" , "SchemeAdmin" )
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) Create ( group * model . Group ) ( * model . Group , error ) {
2020-12-22 19:20:59 +05:30
if group . Id != "" {
2020-11-17 00:32:36 -03:00
return nil , store . NewErrInvalidInput ( "Group" , "id" , group . Id )
2019-07-02 15:50:22 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
if err := group . IsValidForCreate ( ) ; err != nil {
return nil , err
}
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
group . Id = model . NewId ( )
group . CreateAt = model . GetMillis ( )
group . UpdateAt = group . CreateAt
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
if err := s . GetMaster ( ) . Insert ( group ) ; err != nil {
if IsUniqueConstraintError ( err , [ ] string { "Name" , "groups_name_key" } ) {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "Group with name %s already exists" , * group . Name )
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "failed to save Group" )
2019-07-02 15:50:22 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
return group , nil
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) Get ( groupId string ) ( * model . Group , error ) {
2019-07-02 15:50:22 +02:00
var group * model . Group
if err := s . GetReplica ( ) . SelectOne ( & group , "SELECT * from UserGroups WHERE Id = :Id" , map [ string ] interface { } { "Id" : groupId } ) ; err != nil {
if err == sql . ErrNoRows {
2020-11-17 00:32:36 -03:00
return nil , store . NewErrNotFound ( "Group" , groupId )
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to get Group with id=%s" , groupId )
2019-07-02 15:50:22 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
return group , nil
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetByName ( name string , opts model . GroupSearchOpts ) ( * model . Group , error ) {
2019-10-22 14:38:08 -04:00
var group * model . Group
2020-05-12 08:35:03 -07:00
query := s . getQueryBuilder ( ) . Select ( "*" ) . From ( "UserGroups" ) . Where ( sq . Eq { "Name" : name } )
if opts . FilterAllowReference {
query = query . Where ( "AllowReference = true" )
}
queryString , args , err := query . ToSql ( )
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "get_by_name_tosql" )
2020-05-12 08:35:03 -07:00
}
if err := s . GetReplica ( ) . SelectOne ( & group , queryString , args ... ) ; err != nil {
2019-10-22 14:38:08 -04:00
if err == sql . ErrNoRows {
2020-11-17 00:32:36 -03:00
return nil , store . NewErrNotFound ( "Group" , fmt . Sprintf ( "name=%s" , name ) )
2019-10-22 14:38:08 -04:00
}
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to get Group with name=%s" , name )
2019-10-22 14:38:08 -04:00
}
return group , nil
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetByIDs ( groupIDs [ ] string ) ( [ ] * model . Group , error ) {
2019-06-17 09:51:56 -04:00
var groups [ ] * model . Group
query := s . getQueryBuilder ( ) . Select ( "*" ) . From ( "UserGroups" ) . Where ( sq . Eq { "Id" : groupIDs } )
queryString , args , err := query . ToSql ( )
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "get_by_ids_tosql" )
2019-06-17 09:51:56 -04:00
}
if _ , err := s . GetReplica ( ) . Select ( & groups , queryString , args ... ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "failed to find Groups by ids" )
2019-06-17 09:51:56 -04:00
}
return groups , nil
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetByRemoteID ( remoteID string , groupSource model . GroupSource ) ( * model . Group , error ) {
2019-07-02 15:50:22 +02:00
var group * model . Group
if err := s . GetReplica ( ) . SelectOne ( & group , "SELECT * from UserGroups WHERE RemoteId = :RemoteId AND Source = :Source" , map [ string ] interface { } { "RemoteId" : remoteID , "Source" : groupSource } ) ; err != nil {
if err == sql . ErrNoRows {
2020-11-17 00:32:36 -03:00
return nil , store . NewErrNotFound ( "Group" , fmt . Sprintf ( "remoteId=%s" , remoteID ) )
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to get Group with remoteId=%s" , remoteID )
2019-07-02 15:50:22 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
return group , nil
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetAllBySource ( groupSource model . GroupSource ) ( [ ] * model . Group , error ) {
2019-07-02 15:50:22 +02:00
var groups [ ] * model . Group
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
if _ , err := s . GetReplica ( ) . Select ( & groups , "SELECT * from UserGroups WHERE DeleteAt = 0 AND Source = :Source" , map [ string ] interface { } { "Source" : groupSource } ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to find Groups by groupSource=%v" , groupSource )
2019-07-02 15:50:22 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
return groups , nil
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetByUser ( userId string ) ( [ ] * model . Group , error ) {
2019-10-22 14:38:08 -04:00
var groups [ ] * model . Group
query := `
SELECT
UserGroups . *
FROM
GroupMembers
JOIN UserGroups ON UserGroups . Id = GroupMembers . GroupId
WHERE
GroupMembers . DeleteAt = 0
AND UserId = : UserId `
if _ , err := s . GetReplica ( ) . Select ( & groups , query , map [ string ] interface { } { "UserId" : userId } ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to find Groups with userId=%s" , userId )
2019-10-22 14:38:08 -04:00
}
return groups , nil
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) Update ( group * model . Group ) ( * model . Group , error ) {
2019-07-02 15:50:22 +02:00
var retrievedGroup * model . Group
2019-12-18 08:54:09 -05:00
if err := s . GetReplica ( ) . SelectOne ( & retrievedGroup , "SELECT * FROM UserGroups WHERE Id = :Id" , map [ string ] interface { } { "Id" : group . Id } ) ; err != nil {
2019-07-02 15:50:22 +02:00
if err == sql . ErrNoRows {
2020-11-17 00:32:36 -03:00
return nil , store . NewErrNotFound ( "Group" , group . Id )
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to get Group with id=%s" , group . Id )
2019-07-02 15:50:22 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
// If updating DeleteAt it can only be to 0
if group . DeleteAt != retrievedGroup . DeleteAt && group . DeleteAt != 0 {
2020-11-17 00:32:36 -03:00
return nil , errors . New ( "DeleteAt should be 0 when updating" )
2019-07-02 15:50:22 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
// Reset these properties, don't update them based on input
group . CreateAt = retrievedGroup . CreateAt
group . UpdateAt = model . GetMillis ( )
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
if err := group . IsValidForUpdate ( ) ; err != nil {
return nil , err
}
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
rowsChanged , err := s . GetMaster ( ) . Update ( group )
if err != nil {
2020-05-12 08:35:03 -07:00
if IsUniqueConstraintError ( err , [ ] string { "Name" , "groups_name_key" } ) {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "Group with name %s already exists" , * group . Name )
2020-05-12 08:35:03 -07:00
}
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "failed to update Group" )
2019-07-02 15:50:22 +02:00
}
2020-07-18 09:57:58 +05:30
if rowsChanged > 1 {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "multiple Groups were update: %d" , rowsChanged )
2019-07-02 15:50:22 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
return group , nil
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) Delete ( groupID string ) ( * model . Group , error ) {
2019-07-02 15:50:22 +02:00
var group * model . Group
if err := s . GetReplica ( ) . SelectOne ( & group , "SELECT * from UserGroups WHERE Id = :Id AND DeleteAt = 0" , map [ string ] interface { } { "Id" : groupID } ) ; err != nil {
if err == sql . ErrNoRows {
2020-11-17 00:32:36 -03:00
return nil , store . NewErrNotFound ( "Group" , groupID )
2019-05-28 16:17:10 +02:00
}
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to get Group with id=%s" , groupID )
2019-07-02 15:50:22 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
time := model . GetMillis ( )
group . DeleteAt = time
group . UpdateAt = time
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
if _ , err := s . GetMaster ( ) . Update ( group ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to update Group with id=%s" , groupID )
2019-07-02 15:50:22 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 15:50:22 +02:00
return group , nil
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetMemberUsers ( groupID string ) ( [ ] * model . User , error ) {
2019-07-02 17:18:04 +02:00
var groupMembers [ ] * model . User
2019-01-10 15:17:31 -05:00
2019-07-02 17:18:04 +02:00
query := `
2019-04-02 21:02:51 +01:00
SELECT
Users . *
FROM
GroupMembers
2019-01-10 15:17:31 -05:00
JOIN Users ON Users . Id = GroupMembers . UserId
2019-04-02 21:02:51 +01:00
WHERE
GroupMembers . DeleteAt = 0
2019-01-10 15:17:31 -05:00
AND Users . DeleteAt = 0
AND GroupId = : GroupId `
2019-07-02 17:18:04 +02:00
if _ , err := s . GetReplica ( ) . Select ( & groupMembers , query , map [ string ] interface { } { "GroupId" : groupID } ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to find member Users for Group with id=%s" , groupID )
2019-07-02 17:18:04 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 17:18:04 +02:00
return groupMembers , nil
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetMemberUsersPage ( groupID string , page int , perPage int ) ( [ ] * model . User , error ) {
2019-07-02 17:18:04 +02:00
var groupMembers [ ] * model . User
2019-01-10 15:17:31 -05:00
2019-07-02 17:18:04 +02:00
query := `
2019-04-02 21:02:51 +01:00
SELECT
Users . *
FROM
GroupMembers
2019-01-10 15:17:31 -05:00
JOIN Users ON Users . Id = GroupMembers . UserId
2019-04-02 21:02:51 +01:00
WHERE
GroupMembers . DeleteAt = 0
2019-01-10 15:17:31 -05:00
AND Users . DeleteAt = 0
AND GroupId = : GroupId
ORDER BY
GroupMembers . CreateAt DESC
LIMIT
: Limit
OFFSET
: Offset `
2019-07-26 15:18:37 +02:00
if _ , err := s . GetReplica ( ) . Select ( & groupMembers , query , map [ string ] interface { } { "GroupId" : groupID , "Limit" : perPage , "Offset" : page * perPage } ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to find member Users for Group with id=%s" , groupID )
2019-07-02 17:18:04 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 17:18:04 +02:00
return groupMembers , nil
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetMemberCount ( groupID string ) ( int64 , error ) {
2019-07-02 17:18:04 +02:00
query := `
2019-04-02 21:02:51 +01:00
SELECT
count ( * )
FROM
GroupMembers
2019-08-09 14:39:57 -04:00
JOIN Users ON Users . Id = GroupMembers . UserId
2019-04-02 21:02:51 +01:00
WHERE
2019-08-09 14:39:57 -04:00
GroupMembers . GroupId = : GroupId
AND Users . DeleteAt = 0 `
2019-01-10 15:17:31 -05:00
2019-07-02 17:18:04 +02:00
count , err := s . GetReplica ( ) . SelectInt ( query , map [ string ] interface { } { "GroupId" : groupID } )
if err != nil {
2020-11-17 00:32:36 -03:00
return int64 ( 0 ) , errors . Wrapf ( err , "failed to count member Users for Group with id=%s" , groupID )
2019-07-02 17:18:04 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 17:18:04 +02:00
return count , nil
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetMemberUsersInTeam ( groupID string , teamID string ) ( [ ] * model . User , error ) {
2020-04-17 19:22:54 -04:00
var groupMembers [ ] * model . User
query := `
SELECT
Users . *
FROM
GroupMembers
JOIN Users ON Users . Id = GroupMembers . UserId
WHERE
GroupId = : GroupId
AND GroupMembers . UserId IN (
SELECT TeamMembers . UserId
FROM TeamMembers
JOIN Teams ON Teams . Id = : TeamId
WHERE TeamMembers . TeamId = Teams . Id
AND TeamMembers . DeleteAt = 0
)
AND GroupMembers . DeleteAt = 0
AND Users . DeleteAt = 0
`
if _ , err := s . GetReplica ( ) . Select ( & groupMembers , query , map [ string ] interface { } { "GroupId" : groupID , "TeamId" : teamID } ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to member Users for groupId=%s and teamId=%s" , groupID , teamID )
2020-04-17 19:22:54 -04:00
}
return groupMembers , nil
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetMemberUsersNotInChannel ( groupID string , channelID string ) ( [ ] * model . User , error ) {
2020-04-17 19:22:54 -04:00
var groupMembers [ ] * model . User
query := `
SELECT
Users . *
FROM
GroupMembers
JOIN Users ON Users . Id = GroupMembers . UserId
WHERE
GroupId = : GroupId
AND GroupMembers . UserId NOT IN (
SELECT ChannelMembers . UserId
FROM ChannelMembers
WHERE ChannelMembers . ChannelId = : ChannelId
)
AND GroupMembers . UserId IN (
SELECT TeamMembers . UserId
FROM TeamMembers
JOIN Channels ON Channels . Id = : ChannelId
JOIN Teams ON Teams . Id = Channels . TeamId
WHERE TeamMembers . TeamId = Teams . Id
AND TeamMembers . DeleteAt = 0
)
AND GroupMembers . DeleteAt = 0
AND Users . DeleteAt = 0
`
if _ , err := s . GetReplica ( ) . Select ( & groupMembers , query , map [ string ] interface { } { "GroupId" : groupID , "ChannelId" : channelID } ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to member Users for groupId=%s and channelId!=%s" , groupID , channelID )
2020-04-17 19:22:54 -04:00
}
return groupMembers , nil
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) UpsertMember ( groupID string , userID string ) ( * model . GroupMember , error ) {
2019-07-02 17:18:04 +02:00
member := & model . GroupMember {
GroupId : groupID ,
UserId : userID ,
CreateAt : model . GetMillis ( ) ,
2021-07-15 19:40:45 +05:30
DeleteAt : 0 ,
2019-07-02 17:18:04 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 17:18:04 +02:00
if err := member . IsValid ( ) ; err != nil {
return nil , err
}
2019-01-10 15:17:31 -05:00
2019-07-02 17:18:04 +02:00
var retrievedGroup * model . Group
2019-12-18 08:54:09 -05:00
if err := s . GetReplica ( ) . SelectOne ( & retrievedGroup , "SELECT * FROM UserGroups WHERE Id = :Id" , map [ string ] interface { } { "Id" : groupID } ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to get UserGroup with groupId=%s and userId=%s" , groupID , userID )
2019-07-02 17:18:04 +02:00
}
2019-01-10 15:17:31 -05:00
2021-07-15 19:40:45 +05:30
query := s . getQueryBuilder ( ) .
Insert ( "GroupMembers" ) .
Columns ( "GroupId" , "UserId" , "CreateAt" , "DeleteAt" ) .
Values ( member . GroupId , member . UserId , member . CreateAt , member . DeleteAt )
2021-07-12 20:05:36 +02:00
if s . DriverName ( ) == model . DatabaseDriverMysql {
2021-07-15 19:40:45 +05:30
query = query . SuffixExpr ( sq . Expr ( "ON DUPLICATE KEY UPDATE CreateAt = ?, DeleteAt = ?" , member . CreateAt , member . DeleteAt ) )
2021-07-12 20:05:36 +02:00
} else if s . DriverName ( ) == model . DatabaseDriverPostgres {
2021-07-15 19:40:45 +05:30
query = query . SuffixExpr ( sq . Expr ( "ON CONFLICT (groupid, userid) DO UPDATE SET CreateAt = ?, DeleteAt = ?" , member . CreateAt , member . DeleteAt ) )
2019-07-02 17:18:04 +02:00
}
2019-01-10 15:17:31 -05:00
2021-07-15 19:40:45 +05:30
queryString , args , err := query . ToSql ( )
if err != nil {
return nil , errors . Wrap ( err , "failed to generate sqlquery" )
2019-07-02 17:18:04 +02:00
}
2019-01-10 15:17:31 -05:00
2021-07-15 19:40:45 +05:30
if _ , err = s . GetMaster ( ) . Exec ( queryString , args ... ) ; err != nil {
return nil , errors . Wrap ( err , "failed to save GroupMember" )
}
2019-07-02 17:18:04 +02:00
return member , nil
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) DeleteMember ( groupID string , userID string ) ( * model . GroupMember , error ) {
2019-07-02 17:18:04 +02:00
var retrievedMember * model . GroupMember
2019-12-18 08:54:09 -05:00
if err := s . GetReplica ( ) . SelectOne ( & retrievedMember , "SELECT * FROM GroupMembers WHERE GroupId = :GroupId AND UserId = :UserId AND DeleteAt = 0" , map [ string ] interface { } { "GroupId" : groupID , "UserId" : userID } ) ; err != nil {
2019-07-02 17:18:04 +02:00
if err == sql . ErrNoRows {
2020-11-17 00:32:36 -03:00
return nil , store . NewErrNotFound ( "GroupMember" , fmt . Sprintf ( "groupId=%s, userId=%s" , groupID , userID ) )
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to get GroupMember with groupId=%s and userId=%s" , groupID , userID )
2019-07-02 17:18:04 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 17:18:04 +02:00
retrievedMember . DeleteAt = model . GetMillis ( )
2019-01-10 15:17:31 -05:00
2019-07-02 17:18:04 +02:00
if _ , err := s . GetMaster ( ) . Update ( retrievedMember ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to update GroupMember with groupId=%s and userId=%s" , groupID , userID )
2019-07-02 17:18:04 +02:00
}
2019-01-10 15:17:31 -05:00
2019-07-02 17:18:04 +02:00
return retrievedMember , nil
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) PermanentDeleteMembersByUser ( userId string ) error {
2019-10-24 17:31:17 -04:00
if _ , err := s . GetMaster ( ) . Exec ( "DELETE FROM GroupMembers WHERE UserId = :UserId" , map [ string ] interface { } { "UserId" : userId } ) ; err != nil {
2020-11-17 00:32:36 -03:00
return errors . Wrapf ( err , "failed to permanent delete GroupMember with userId=%s" , userId )
2019-10-24 17:31:17 -04:00
}
return nil
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) CreateGroupSyncable ( groupSyncable * model . GroupSyncable ) ( * model . GroupSyncable , error ) {
2019-05-31 18:27:56 +02:00
if err := groupSyncable . IsValid ( ) ; err != nil {
return nil , err
}
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
// Reset values that shouldn't be updatable by parameter
groupSyncable . DeleteAt = 0
groupSyncable . CreateAt = model . GetMillis ( )
groupSyncable . UpdateAt = groupSyncable . CreateAt
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
var insertErr error
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
switch groupSyncable . Type {
case model . GroupSyncableTypeTeam :
if _ , err := s . Team ( ) . Get ( groupSyncable . SyncableId ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , err
2019-05-28 16:17:10 +02:00
}
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
insertErr = s . GetMaster ( ) . Insert ( groupSyncableToGroupTeam ( groupSyncable ) )
case model . GroupSyncableTypeChannel :
2021-05-26 10:12:34 -04:00
var channel * model . Channel
channel , err := s . Channel ( ) . Get ( groupSyncable . SyncableId , false )
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , err
2019-05-28 16:17:10 +02:00
}
2019-05-31 18:27:56 +02:00
insertErr = s . GetMaster ( ) . Insert ( groupSyncableToGroupChannel ( groupSyncable ) )
2021-05-26 10:12:34 -04:00
groupSyncable . TeamID = channel . TeamId
2019-05-31 18:27:56 +02:00
default :
2020-11-17 00:32:36 -03:00
return nil , fmt . Errorf ( "invalid GroupSyncableType: %s" , groupSyncable . Type )
2019-05-31 18:27:56 +02:00
}
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
if insertErr != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( insertErr , "unable to insert GroupSyncable" )
2019-05-31 18:27:56 +02:00
}
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
return groupSyncable , nil
}
2019-01-10 15:17:31 -05:00
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetGroupSyncable ( groupID string , syncableID string , syncableType model . GroupSyncableType ) ( * model . GroupSyncable , error ) {
2019-05-31 18:27:56 +02:00
groupSyncable , err := s . getGroupSyncable ( groupID , syncableID , syncableType )
if err != nil {
if err == sql . ErrNoRows {
2020-11-17 00:32:36 -03:00
return nil , store . NewErrNotFound ( "GroupSyncable" , fmt . Sprintf ( "groupId=%s, syncableId=%s, syncableType=%s" , groupID , syncableID , syncableType ) )
2019-05-31 18:27:56 +02:00
}
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to find GroupSyncable with groupId=%s, syncableId=%s, syncableType=%s" , groupID , syncableID , syncableType )
2019-05-31 18:27:56 +02:00
}
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
return groupSyncable , nil
2019-01-10 15:17:31 -05:00
}
2019-05-28 16:17:10 +02:00
func ( s * SqlGroupStore ) getGroupSyncable ( groupID string , syncableID string , syncableType model . GroupSyncableType ) ( * model . GroupSyncable , error ) {
2019-01-10 15:17:31 -05:00
var err error
var result interface { }
switch syncableType {
case model . GroupSyncableTypeTeam :
2019-12-18 08:54:09 -05:00
result , err = s . GetReplica ( ) . Get ( groupTeam { } , groupID , syncableID )
2019-01-10 15:17:31 -05:00
case model . GroupSyncableTypeChannel :
2019-12-18 08:54:09 -05:00
result , err = s . GetReplica ( ) . Get ( groupChannel { } , groupID , syncableID )
2019-01-10 15:17:31 -05:00
}
if err != nil {
return nil , err
}
if result == nil {
return nil , sql . ErrNoRows
}
groupSyncable := model . GroupSyncable { }
switch syncableType {
case model . GroupSyncableTypeTeam :
groupTeam := result . ( * groupTeam )
groupSyncable . SyncableId = groupTeam . TeamId
groupSyncable . GroupId = groupTeam . GroupId
groupSyncable . AutoAdd = groupTeam . AutoAdd
groupSyncable . CreateAt = groupTeam . CreateAt
groupSyncable . DeleteAt = groupTeam . DeleteAt
groupSyncable . UpdateAt = groupTeam . UpdateAt
groupSyncable . Type = syncableType
case model . GroupSyncableTypeChannel :
groupChannel := result . ( * groupChannel )
groupSyncable . SyncableId = groupChannel . ChannelId
groupSyncable . GroupId = groupChannel . GroupId
groupSyncable . AutoAdd = groupChannel . AutoAdd
groupSyncable . CreateAt = groupChannel . CreateAt
groupSyncable . DeleteAt = groupChannel . DeleteAt
groupSyncable . UpdateAt = groupChannel . UpdateAt
groupSyncable . Type = syncableType
default :
return nil , fmt . Errorf ( "unable to convert syncableType: %s" , syncableType . String ( ) )
}
return & groupSyncable , nil
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetAllGroupSyncablesByGroupId ( groupID string , syncableType model . GroupSyncableType ) ( [ ] * model . GroupSyncable , error ) {
2019-05-31 18:27:56 +02:00
args := map [ string ] interface { } { "GroupId" : groupID }
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
groupSyncables := [ ] * model . GroupSyncable { }
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
switch syncableType {
case model . GroupSyncableTypeTeam :
sqlQuery := `
2019-01-10 15:17:31 -05:00
SELECT
2019-04-02 21:02:51 +01:00
GroupTeams . * ,
Teams . DisplayName AS TeamDisplayName ,
2019-01-10 15:17:31 -05:00
Teams . Type AS TeamType
2019-04-02 21:02:51 +01:00
FROM
2019-01-10 15:17:31 -05:00
GroupTeams
JOIN Teams ON Teams . Id = GroupTeams . TeamId
2019-04-02 21:02:51 +01:00
WHERE
2019-01-10 15:17:31 -05:00
GroupId = : GroupId AND GroupTeams . DeleteAt = 0 `
2019-05-31 18:27:56 +02:00
results := [ ] * groupTeamJoin { }
2019-12-18 08:54:09 -05:00
_ , err := s . GetReplica ( ) . Select ( & results , sqlQuery , args )
2019-05-31 18:27:56 +02:00
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to find GroupTeams with groupId=%s" , groupID )
2019-05-31 18:27:56 +02:00
}
for _ , result := range results {
groupSyncable := & model . GroupSyncable {
SyncableId : result . TeamId ,
GroupId : result . GroupId ,
AutoAdd : result . AutoAdd ,
CreateAt : result . CreateAt ,
DeleteAt : result . DeleteAt ,
UpdateAt : result . UpdateAt ,
Type : syncableType ,
TeamDisplayName : result . TeamDisplayName ,
TeamType : result . TeamType ,
2020-01-10 12:19:39 -05:00
SchemeAdmin : result . SchemeAdmin ,
2019-05-28 16:17:10 +02:00
}
2019-05-31 18:27:56 +02:00
groupSyncables = append ( groupSyncables , groupSyncable )
}
case model . GroupSyncableTypeChannel :
sqlQuery := `
2019-01-10 15:17:31 -05:00
SELECT
2019-04-02 21:02:51 +01:00
GroupChannels . * ,
Channels . DisplayName AS ChannelDisplayName ,
2019-01-10 15:17:31 -05:00
Teams . DisplayName AS TeamDisplayName ,
Channels . Type As ChannelType ,
Teams . Type As TeamType ,
Teams . Id AS TeamId
2019-04-02 21:02:51 +01:00
FROM
GroupChannels
2019-01-10 15:17:31 -05:00
JOIN Channels ON Channels . Id = GroupChannels . ChannelId
JOIN Teams ON Teams . Id = Channels . TeamId
2019-04-02 21:02:51 +01:00
WHERE
2019-01-10 15:17:31 -05:00
GroupId = : GroupId AND GroupChannels . DeleteAt = 0 `
2019-05-31 18:27:56 +02:00
results := [ ] * groupChannelJoin { }
2019-12-18 08:54:09 -05:00
_ , err := s . GetReplica ( ) . Select ( & results , sqlQuery , args )
2019-05-31 18:27:56 +02:00
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to find GroupChannels with groupId=%s" , groupID )
2019-05-31 18:27:56 +02:00
}
for _ , result := range results {
groupSyncable := & model . GroupSyncable {
SyncableId : result . ChannelId ,
GroupId : result . GroupId ,
AutoAdd : result . AutoAdd ,
CreateAt : result . CreateAt ,
DeleteAt : result . DeleteAt ,
UpdateAt : result . UpdateAt ,
Type : syncableType ,
ChannelDisplayName : result . ChannelDisplayName ,
ChannelType : result . ChannelType ,
TeamDisplayName : result . TeamDisplayName ,
TeamType : result . TeamType ,
TeamID : result . TeamID ,
2020-01-10 12:19:39 -05:00
SchemeAdmin : result . SchemeAdmin ,
2019-01-10 15:17:31 -05:00
}
2019-05-31 18:27:56 +02:00
groupSyncables = append ( groupSyncables , groupSyncable )
2019-01-10 15:17:31 -05:00
}
2019-05-31 18:27:56 +02:00
}
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
return groupSyncables , nil
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) UpdateGroupSyncable ( groupSyncable * model . GroupSyncable ) ( * model . GroupSyncable , error ) {
2019-05-31 18:27:56 +02:00
retrievedGroupSyncable , err := s . getGroupSyncable ( groupSyncable . GroupId , groupSyncable . SyncableId , groupSyncable . Type )
if err != nil {
if err == sql . ErrNoRows {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( store . NewErrNotFound ( "GroupSyncable" , fmt . Sprintf ( "groupId=%s, syncableId=%s, syncableType=%s" , groupSyncable . GroupId , groupSyncable . SyncableId , groupSyncable . Type ) ) , "GroupSyncable not found" )
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to find GroupSyncable with groupId=%s, syncableId=%s, syncableType=%s" , groupSyncable . GroupId , groupSyncable . SyncableId , groupSyncable . Type )
2019-05-31 18:27:56 +02:00
}
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
if err := groupSyncable . IsValid ( ) ; err != nil {
return nil , err
}
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
// If updating DeleteAt it can only be to 0
if groupSyncable . DeleteAt != retrievedGroupSyncable . DeleteAt && groupSyncable . DeleteAt != 0 {
2020-11-17 00:32:36 -03:00
return nil , errors . New ( "DeleteAt should be 0 when updating" )
2019-05-31 18:27:56 +02:00
}
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
// Reset these properties, don't update them based on input
groupSyncable . CreateAt = retrievedGroupSyncable . CreateAt
groupSyncable . UpdateAt = model . GetMillis ( )
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
switch groupSyncable . Type {
case model . GroupSyncableTypeTeam :
_ , err = s . GetMaster ( ) . Update ( groupSyncableToGroupTeam ( groupSyncable ) )
case model . GroupSyncableTypeChannel :
2021-05-26 10:12:34 -04:00
// We need to get the TeamId so redux can manage channels when teams are unlinked
var channel * model . Channel
channel , channelErr := s . Channel ( ) . Get ( groupSyncable . SyncableId , false )
if channelErr != nil {
return nil , channelErr
}
2019-05-31 18:27:56 +02:00
_ , err = s . GetMaster ( ) . Update ( groupSyncableToGroupChannel ( groupSyncable ) )
2021-05-26 10:12:34 -04:00
groupSyncable . TeamID = channel . TeamId
2019-05-31 18:27:56 +02:00
default :
2020-11-17 00:32:36 -03:00
return nil , fmt . Errorf ( "invalid GroupSyncableType: %s" , groupSyncable . Type )
2019-05-31 18:27:56 +02:00
}
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "failed to update GroupSyncable" )
2019-05-31 18:27:56 +02:00
}
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
return groupSyncable , nil
}
2019-01-10 15:17:31 -05:00
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) DeleteGroupSyncable ( groupID string , syncableID string , syncableType model . GroupSyncableType ) ( * model . GroupSyncable , error ) {
2019-05-31 18:27:56 +02:00
groupSyncable , err := s . getGroupSyncable ( groupID , syncableID , syncableType )
if err != nil {
if err == sql . ErrNoRows {
2020-11-17 00:32:36 -03:00
return nil , store . NewErrNotFound ( "GroupSyncable" , fmt . Sprintf ( "groupId=%s, syncableId=%s, syncableType=%s" , groupID , syncableID , syncableType ) )
2019-01-10 15:17:31 -05:00
}
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to find GroupSyncable with groupId=%s, syncableId=%s, syncableType=%s" , groupID , syncableID , syncableType )
2019-05-31 18:27:56 +02:00
}
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
if groupSyncable . DeleteAt != 0 {
2020-11-17 00:32:36 -03:00
return nil , store . NewErrInvalidInput ( "GroupSyncable" , "<groupId, syncableId, syncableType>" , fmt . Sprintf ( "<%s, %s, %s>" , groupSyncable . GroupId , groupSyncable . SyncableId , groupSyncable . Type ) )
2019-05-31 18:27:56 +02:00
}
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
time := model . GetMillis ( )
groupSyncable . DeleteAt = time
groupSyncable . UpdateAt = time
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
switch groupSyncable . Type {
case model . GroupSyncableTypeTeam :
_ , err = s . GetMaster ( ) . Update ( groupSyncableToGroupTeam ( groupSyncable ) )
case model . GroupSyncableTypeChannel :
_ , err = s . GetMaster ( ) . Update ( groupSyncableToGroupChannel ( groupSyncable ) )
default :
2020-11-17 00:32:36 -03:00
return nil , fmt . Errorf ( "invalid GroupSyncableType: %s" , groupSyncable . Type )
2019-05-31 18:27:56 +02:00
}
2019-01-10 15:17:31 -05:00
2019-05-31 18:27:56 +02:00
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "failed to update GroupSyncable" )
2019-05-31 18:27:56 +02:00
}
return groupSyncable , nil
2019-01-10 15:17:31 -05:00
}
2021-05-04 12:37:36 -04:00
func ( s * SqlGroupStore ) TeamMembersToAdd ( since int64 , teamID * string , includeRemovedMembers bool ) ( [ ] * model . UserTeamIDPair , error ) {
2020-11-17 00:32:36 -03:00
builder := s . getQueryBuilder ( ) . Select ( "GroupMembers.UserId" , "GroupTeams.TeamId" ) .
2020-01-20 09:10:25 -05:00
From ( "GroupMembers" ) .
Join ( "GroupTeams ON GroupTeams.GroupId = GroupMembers.GroupId" ) .
Join ( "UserGroups ON UserGroups.Id = GroupMembers.GroupId" ) .
Join ( "Teams ON Teams.Id = GroupTeams.TeamId" ) .
Where ( sq . Eq {
"UserGroups.DeleteAt" : 0 ,
"GroupTeams.DeleteAt" : 0 ,
"GroupTeams.AutoAdd" : true ,
"GroupMembers.DeleteAt" : 0 ,
"Teams.DeleteAt" : 0 ,
2021-05-04 12:37:36 -04:00
} )
2020-01-20 09:10:25 -05:00
2021-05-04 12:37:36 -04:00
if ! includeRemovedMembers {
builder = builder .
JoinClause ( "LEFT OUTER JOIN TeamMembers ON TeamMembers.TeamId = GroupTeams.TeamId AND TeamMembers.UserId = GroupMembers.UserId" ) .
Where ( sq . Eq { "TeamMembers.UserId" : nil } ) .
Where ( sq . Or {
sq . GtOrEq { "GroupMembers.CreateAt" : since } ,
sq . GtOrEq { "GroupTeams.UpdateAt" : since } ,
} )
}
2020-01-20 09:10:25 -05:00
if teamID != nil {
2020-11-17 00:32:36 -03:00
builder = builder . Where ( sq . Eq { "Teams.Id" : * teamID } )
2020-01-20 09:10:25 -05:00
}
2020-11-17 00:32:36 -03:00
query , params , err := builder . ToSql ( )
2020-01-20 09:10:25 -05:00
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "team_members_to_add_tosql" )
2020-01-20 09:10:25 -05:00
}
2019-01-10 15:17:31 -05:00
2019-05-30 20:38:22 +02:00
var teamMembers [ ] * model . UserTeamIDPair
2019-01-10 15:17:31 -05:00
2021-03-12 12:37:30 -05:00
_ , err = s . GetMaster ( ) . Select ( & teamMembers , query , params ... )
2019-05-30 20:38:22 +02:00
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "failed to find UserTeamIDPairs" )
2019-05-30 20:38:22 +02:00
}
2019-01-10 15:17:31 -05:00
2019-05-30 20:38:22 +02:00
return teamMembers , nil
2019-01-10 15:17:31 -05:00
}
2021-05-04 12:37:36 -04:00
func ( s * SqlGroupStore ) ChannelMembersToAdd ( since int64 , channelID * string , includeRemovedMembers bool ) ( [ ] * model . UserChannelIDPair , error ) {
2020-11-17 00:32:36 -03:00
builder := s . getQueryBuilder ( ) . Select ( "GroupMembers.UserId" , "GroupChannels.ChannelId" ) .
2020-01-20 09:10:25 -05:00
From ( "GroupMembers" ) .
Join ( "GroupChannels ON GroupChannels.GroupId = GroupMembers.GroupId" ) .
Join ( "UserGroups ON UserGroups.Id = GroupMembers.GroupId" ) .
Join ( "Channels ON Channels.Id = GroupChannels.ChannelId" ) .
Where ( sq . Eq {
2021-05-04 12:37:36 -04:00
"UserGroups.DeleteAt" : 0 ,
"GroupChannels.DeleteAt" : 0 ,
"GroupChannels.AutoAdd" : true ,
"GroupMembers.DeleteAt" : 0 ,
"Channels.DeleteAt" : 0 ,
} )
if ! includeRemovedMembers {
builder = builder .
JoinClause ( "LEFT OUTER JOIN ChannelMemberHistory ON ChannelMemberHistory.ChannelId = GroupChannels.ChannelId AND ChannelMemberHistory.UserId = GroupMembers.UserId" ) .
Where ( sq . Eq {
"ChannelMemberHistory.UserId" : nil ,
"ChannelMemberHistory.LeaveTime" : nil ,
} ) .
Where ( sq . Or {
sq . GtOrEq { "GroupMembers.CreateAt" : since } ,
sq . GtOrEq { "GroupChannels.UpdateAt" : since } ,
} )
}
2020-01-20 09:10:25 -05:00
if channelID != nil {
2020-11-17 00:32:36 -03:00
builder = builder . Where ( sq . Eq { "Channels.Id" : * channelID } )
2020-01-20 09:10:25 -05:00
}
2020-11-17 00:32:36 -03:00
query , params , err := builder . ToSql ( )
2020-01-20 09:10:25 -05:00
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "channel_members_to_add_tosql" )
2020-01-20 09:10:25 -05:00
}
2019-01-10 15:17:31 -05:00
2019-05-30 20:38:22 +02:00
var channelMembers [ ] * model . UserChannelIDPair
2019-01-10 15:17:31 -05:00
2021-03-12 12:37:30 -05:00
_ , err = s . GetMaster ( ) . Select ( & channelMembers , query , params ... )
2019-05-30 20:38:22 +02:00
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "failed to find UserChannelIDPairs" )
2019-05-30 20:38:22 +02:00
}
2019-01-10 15:17:31 -05:00
2019-05-30 20:38:22 +02:00
return channelMembers , nil
2019-01-10 15:17:31 -05:00
}
func groupSyncableToGroupTeam ( groupSyncable * model . GroupSyncable ) * groupTeam {
return & groupTeam {
GroupSyncable : * groupSyncable ,
TeamId : groupSyncable . SyncableId ,
}
}
func groupSyncableToGroupChannel ( groupSyncable * model . GroupSyncable ) * groupChannel {
return & groupChannel {
GroupSyncable : * groupSyncable ,
ChannelId : groupSyncable . SyncableId ,
}
}
2019-04-02 09:22:50 -04:00
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) TeamMembersToRemove ( teamID * string ) ( [ ] * model . TeamMember , error ) {
2020-01-20 09:10:25 -05:00
whereStmt := `
( TeamMembers . TeamId ,
TeamMembers . UserId )
NOT IN (
SELECT
Teams . Id AS TeamId ,
GroupMembers . UserId
FROM
Teams
JOIN GroupTeams ON GroupTeams . TeamId = Teams . Id
JOIN UserGroups ON UserGroups . Id = GroupTeams . GroupId
JOIN GroupMembers ON GroupMembers . GroupId = UserGroups . Id
WHERE
Teams . GroupConstrained = TRUE
AND GroupTeams . DeleteAt = 0
AND UserGroups . DeleteAt = 0
AND Teams . DeleteAt = 0
AND GroupMembers . DeleteAt = 0
GROUP BY
Teams . Id ,
GroupMembers . UserId ) `
2020-11-17 00:32:36 -03:00
builder := s . getQueryBuilder ( ) . Select (
2020-01-20 09:10:25 -05:00
"TeamMembers.TeamId" ,
"TeamMembers.UserId" ,
"TeamMembers.Roles" ,
"TeamMembers.DeleteAt" ,
"TeamMembers.SchemeUser" ,
"TeamMembers.SchemeAdmin" ,
"(TeamMembers.SchemeGuest IS NOT NULL AND TeamMembers.SchemeGuest) AS SchemeGuest" ,
) .
From ( "TeamMembers" ) .
Join ( "Teams ON Teams.Id = TeamMembers.TeamId" ) .
LeftJoin ( "Bots ON Bots.UserId = TeamMembers.UserId" ) .
Where ( sq . Eq { "TeamMembers.DeleteAt" : 0 , "Teams.DeleteAt" : 0 , "Teams.GroupConstrained" : true , "Bots.UserId" : nil } ) .
Where ( whereStmt )
if teamID != nil {
2020-11-17 00:32:36 -03:00
builder = builder . Where ( sq . Eq { "TeamMembers.TeamId" : * teamID } )
2020-01-20 09:10:25 -05:00
}
2020-11-17 00:32:36 -03:00
query , params , err := builder . ToSql ( )
2020-01-20 09:10:25 -05:00
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "team_members_to_remove_tosql" )
2020-01-20 09:10:25 -05:00
}
2019-04-02 09:22:50 -04:00
2019-05-30 20:38:22 +02:00
var teamMembers [ ] * model . TeamMember
2019-04-02 09:22:50 -04:00
2020-11-17 00:32:36 -03:00
_ , err = s . GetReplica ( ) . Select ( & teamMembers , query , params ... )
2019-05-30 20:38:22 +02:00
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "failed to find TeamMembers" )
2019-05-30 20:38:22 +02:00
}
2019-04-02 09:22:50 -04:00
2019-05-30 20:38:22 +02:00
return teamMembers , nil
2019-04-02 09:22:50 -04:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) CountGroupsByChannel ( channelId string , opts model . GroupSearchOpts ) ( int64 , error ) {
2019-05-30 20:39:43 +02:00
countQuery := s . groupsBySyncableBaseQuery ( model . GroupSyncableTypeChannel , selectCountGroups , channelId , opts )
2019-05-15 12:03:47 -04:00
2019-05-30 20:39:43 +02:00
countQueryString , args , err := countQuery . ToSql ( )
if err != nil {
2020-11-17 00:32:36 -03:00
return int64 ( 0 ) , errors . Wrap ( err , "count_groups_by_channel_tosql" )
2019-05-30 20:39:43 +02:00
}
2019-05-15 12:03:47 -04:00
2019-05-30 20:39:43 +02:00
count , err := s . GetReplica ( ) . SelectInt ( countQueryString , args ... )
if err != nil {
2020-11-17 00:32:36 -03:00
return int64 ( 0 ) , errors . Wrapf ( err , "failed to count Groups by channel with channelId=%s" , channelId )
2019-05-30 20:39:43 +02:00
}
2019-05-15 12:03:47 -04:00
2019-05-30 20:39:43 +02:00
return count , nil
2019-05-15 12:03:47 -04:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetGroupsByChannel ( channelId string , opts model . GroupSearchOpts ) ( [ ] * model . GroupWithSchemeAdmin , error ) {
2019-05-30 20:39:43 +02:00
query := s . groupsBySyncableBaseQuery ( model . GroupSyncableTypeChannel , selectGroups , channelId , opts )
2019-05-15 12:03:47 -04:00
2019-05-30 20:39:43 +02:00
if opts . PageOpts != nil {
offset := uint64 ( opts . PageOpts . Page * opts . PageOpts . PerPage )
query = query . OrderBy ( "ug.DisplayName" ) . Limit ( uint64 ( opts . PageOpts . PerPage ) ) . Offset ( offset )
}
2019-05-15 12:03:47 -04:00
2019-05-30 20:39:43 +02:00
queryString , args , err := query . ToSql ( )
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "get_groups_by_channel_tosql" )
2019-05-30 20:39:43 +02:00
}
2019-04-02 21:02:51 +01:00
2020-01-10 12:19:39 -05:00
var groups [ ] * model . GroupWithSchemeAdmin
2019-04-02 21:02:51 +01:00
2019-05-30 20:39:43 +02:00
_ , err = s . GetReplica ( ) . Select ( & groups , queryString , args ... )
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to find Groups with channelId=%s" , channelId )
2019-05-30 20:39:43 +02:00
}
2019-04-02 21:02:51 +01:00
2019-05-30 20:39:43 +02:00
return groups , nil
2019-04-02 21:02:51 +01:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) ChannelMembersToRemove ( channelID * string ) ( [ ] * model . ChannelMember , error ) {
2020-01-20 09:10:25 -05:00
whereStmt := `
( ChannelMembers . ChannelId ,
ChannelMembers . UserId )
NOT IN (
SELECT
Channels . Id AS ChannelId ,
GroupMembers . UserId
FROM
Channels
JOIN GroupChannels ON GroupChannels . ChannelId = Channels . Id
JOIN UserGroups ON UserGroups . Id = GroupChannels . GroupId
JOIN GroupMembers ON GroupMembers . GroupId = UserGroups . Id
WHERE
Channels . GroupConstrained = TRUE
AND GroupChannels . DeleteAt = 0
AND UserGroups . DeleteAt = 0
AND Channels . DeleteAt = 0
AND GroupMembers . DeleteAt = 0
GROUP BY
Channels . Id ,
GroupMembers . UserId ) `
2020-11-17 00:32:36 -03:00
builder := s . getQueryBuilder ( ) . Select (
2020-01-20 09:10:25 -05:00
"ChannelMembers.ChannelId" ,
"ChannelMembers.UserId" ,
"ChannelMembers.LastViewedAt" ,
"ChannelMembers.MsgCount" ,
2021-03-31 16:51:02 +03:00
"ChannelMembers.MsgCountRoot" ,
2020-01-20 09:10:25 -05:00
"ChannelMembers.MentionCount" ,
2021-04-01 14:43:09 +03:00
"ChannelMembers.MentionCountRoot" ,
2020-01-20 09:10:25 -05:00
"ChannelMembers.NotifyProps" ,
"ChannelMembers.LastUpdateAt" ,
"ChannelMembers.LastUpdateAt" ,
"ChannelMembers.SchemeUser" ,
"ChannelMembers.SchemeAdmin" ,
"(ChannelMembers.SchemeGuest IS NOT NULL AND ChannelMembers.SchemeGuest) AS SchemeGuest" ,
) .
From ( "ChannelMembers" ) .
Join ( "Channels ON Channels.Id = ChannelMembers.ChannelId" ) .
LeftJoin ( "Bots ON Bots.UserId = ChannelMembers.UserId" ) .
Where ( sq . Eq { "Channels.DeleteAt" : 0 , "Channels.GroupConstrained" : true , "Bots.UserId" : nil } ) .
Where ( whereStmt )
if channelID != nil {
2020-11-17 00:32:36 -03:00
builder = builder . Where ( sq . Eq { "ChannelMembers.ChannelId" : * channelID } )
2020-01-20 09:10:25 -05:00
}
2020-11-17 00:32:36 -03:00
query , params , err := builder . ToSql ( )
2020-01-20 09:10:25 -05:00
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "channel_members_to_remove_tosql" )
2020-01-20 09:10:25 -05:00
}
2019-04-02 09:22:50 -04:00
2019-05-30 20:38:22 +02:00
var channelMembers [ ] * model . ChannelMember
2019-04-02 09:22:50 -04:00
2020-11-17 00:32:36 -03:00
_ , err = s . GetReplica ( ) . Select ( & channelMembers , query , params ... )
2019-05-30 20:38:22 +02:00
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "failed to find ChannelMembers" )
2019-05-30 20:38:22 +02:00
}
2019-04-02 09:22:50 -04:00
2019-05-30 20:38:22 +02:00
return channelMembers , nil
2019-04-02 09:22:50 -04:00
}
2019-04-02 21:02:51 +01:00
2019-06-25 08:18:48 -04:00
func ( s * SqlGroupStore ) groupsBySyncableBaseQuery ( st model . GroupSyncableType , t selectType , syncableID string , opts model . GroupSearchOpts ) sq . SelectBuilder {
2019-05-10 11:47:21 -04:00
selectStrs := map [ selectType ] string {
2020-01-10 12:19:39 -05:00
selectGroups : "ug.*, gs.SchemeAdmin AS SyncableSchemeAdmin" ,
2019-05-10 11:47:21 -04:00
selectCountGroups : "COUNT(*)" ,
}
2019-05-15 12:03:47 -04:00
var table string
var idCol string
if st == model . GroupSyncableTypeTeam {
table = "GroupTeams"
idCol = "TeamId"
} else {
table = "GroupChannels"
idCol = "ChannelId"
}
2019-05-10 11:47:21 -04:00
query := s . getQueryBuilder ( ) .
Select ( selectStrs [ t ] ) .
2019-05-15 12:03:47 -04:00
From ( fmt . Sprintf ( "%s gs" , table ) ) .
LeftJoin ( "UserGroups ug ON gs.GroupId = ug.Id" ) .
Where ( fmt . Sprintf ( "ug.DeleteAt = 0 AND gs.%s = ? AND gs.DeleteAt = 0" , idCol ) , syncableID )
2019-05-10 11:47:21 -04:00
if opts . IncludeMemberCount && t == selectGroups {
query = s . getQueryBuilder ( ) .
2020-01-10 12:19:39 -05:00
Select ( fmt . Sprintf ( "ug.*, coalesce(Members.MemberCount, 0) AS MemberCount, Group%ss.SchemeAdmin AS SyncableSchemeAdmin" , st ) ) .
2019-05-10 11:47:21 -04:00
From ( "UserGroups ug" ) .
2019-08-09 14:39:57 -04:00
LeftJoin ( "(SELECT GroupMembers.GroupId, COUNT(*) AS MemberCount FROM GroupMembers LEFT JOIN Users ON Users.Id = GroupMembers.UserId WHERE GroupMembers.DeleteAt = 0 AND Users.DeleteAt = 0 GROUP BY GroupId) AS Members ON Members.GroupId = ug.Id" ) .
2019-05-15 12:03:47 -04:00
LeftJoin ( fmt . Sprintf ( "%[1]s ON %[1]s.GroupId = ug.Id" , table ) ) .
2020-01-27 11:45:14 -05:00
Where ( fmt . Sprintf ( "ug.DeleteAt = 0 AND %[1]s.DeleteAt = 0 AND %[1]s.%[2]s = ?" , table , idCol ) , syncableID ) .
2019-05-10 11:47:21 -04:00
OrderBy ( "ug.DisplayName" )
}
2020-04-13 11:37:29 -07:00
if opts . FilterAllowReference && t == selectGroups {
query = query . Where ( "ug.AllowReference = true" )
}
2021-01-25 11:15:17 +01:00
if opts . Q != "" {
2020-04-13 11:37:29 -07:00
pattern := fmt . Sprintf ( "%%%s%%" , sanitizeSearchTerm ( opts . Q , "\\" ) )
operatorKeyword := "ILIKE"
2021-07-12 20:05:36 +02:00
if s . DriverName ( ) == model . DatabaseDriverMysql {
2020-04-13 11:37:29 -07:00
operatorKeyword = "LIKE"
}
query = query . Where ( fmt . Sprintf ( "(ug.Name %[1]s ? OR ug.DisplayName %[1]s ?)" , operatorKeyword ) , pattern , pattern )
}
return query
}
2021-02-04 11:38:05 +06:00
func ( s * SqlGroupStore ) getGroupsAssociatedToChannelsByTeam ( teamID string , opts model . GroupSearchOpts ) sq . SelectBuilder {
2020-04-13 11:37:29 -07:00
query := s . getQueryBuilder ( ) .
Select ( "gc.ChannelId, ug.*, gc.SchemeAdmin AS SyncableSchemeAdmin" ) .
From ( "UserGroups ug" ) .
2020-05-12 08:35:03 -07:00
LeftJoin ( `
( SELECT
2020-04-13 11:37:29 -07:00
GroupChannels . GroupId , GroupChannels . ChannelId , GroupChannels . DeleteAt , GroupChannels . SchemeAdmin
FROM
GroupChannels
LEFT JOIN
Channels ON ( Channels . Id = GroupChannels . ChannelId )
WHERE
GroupChannels . DeleteAt = 0
AND Channels . DeleteAt = 0
2020-05-12 08:35:03 -07:00
AND Channels . TeamId = ? ) AS gc ON gc . GroupId = ug . Id ` , teamID ) .
2020-04-13 11:37:29 -07:00
Where ( "ug.DeleteAt = 0 AND gc.DeleteAt = 0" ) .
OrderBy ( "ug.DisplayName" )
if opts . IncludeMemberCount {
query = s . getQueryBuilder ( ) .
Select ( "gc.ChannelId, ug.*, coalesce(Members.MemberCount, 0) AS MemberCount, gc.SchemeAdmin AS SyncableSchemeAdmin" ) .
From ( "UserGroups ug" ) .
2020-05-12 08:35:03 -07:00
LeftJoin ( `
( SELECT
2020-04-13 11:37:29 -07:00
GroupChannels . ChannelId , GroupChannels . DeleteAt , GroupChannels . GroupId , GroupChannels . SchemeAdmin
FROM
GroupChannels
LEFT JOIN
Channels ON ( Channels . Id = GroupChannels . ChannelId )
WHERE
GroupChannels . DeleteAt = 0
AND Channels . DeleteAt = 0
2020-05-12 08:35:03 -07:00
AND Channels . TeamId = ? ) AS gc ON gc . GroupId = ug . Id ` , teamID ) .
2020-04-13 11:37:29 -07:00
LeftJoin ( ` (
SELECT
GroupMembers . GroupId , COUNT ( * ) AS MemberCount
FROM
GroupMembers
LEFT JOIN
Users ON Users . Id = GroupMembers . UserId
WHERE
GroupMembers . DeleteAt = 0
AND Users . DeleteAt = 0
GROUP BY GroupId ) AS Members
ON Members . GroupId = ug . Id ` ) .
Where ( "ug.DeleteAt = 0 AND gc.DeleteAt = 0" ) .
OrderBy ( "ug.DisplayName" )
}
if opts . FilterAllowReference {
query = query . Where ( "ug.AllowReference = true" )
}
2021-01-25 11:15:17 +01:00
if opts . Q != "" {
2019-09-11 10:56:12 +02:00
pattern := fmt . Sprintf ( "%%%s%%" , sanitizeSearchTerm ( opts . Q , "\\" ) )
2019-05-10 11:47:21 -04:00
operatorKeyword := "ILIKE"
2021-07-12 20:05:36 +02:00
if s . DriverName ( ) == model . DatabaseDriverMysql {
2019-05-10 11:47:21 -04:00
operatorKeyword = "LIKE"
}
query = query . Where ( fmt . Sprintf ( "(ug.Name %[1]s ? OR ug.DisplayName %[1]s ?)" , operatorKeyword ) , pattern , pattern )
}
return query
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) CountGroupsByTeam ( teamId string , opts model . GroupSearchOpts ) ( int64 , error ) {
2019-05-30 20:39:43 +02:00
countQuery := s . groupsBySyncableBaseQuery ( model . GroupSyncableTypeTeam , selectCountGroups , teamId , opts )
2019-05-10 11:47:21 -04:00
2019-05-30 20:39:43 +02:00
countQueryString , args , err := countQuery . ToSql ( )
if err != nil {
2020-11-17 00:32:36 -03:00
return int64 ( 0 ) , errors . Wrap ( err , "count_groups_by_team_tosql" )
2019-05-30 20:39:43 +02:00
}
2019-05-10 11:47:21 -04:00
2019-05-30 20:39:43 +02:00
count , err := s . GetReplica ( ) . SelectInt ( countQueryString , args ... )
if err != nil {
2020-11-17 00:32:36 -03:00
return int64 ( 0 ) , errors . Wrapf ( err , "failed to count Groups with teamId=%s" , teamId )
2019-05-30 20:39:43 +02:00
}
2019-05-10 11:47:21 -04:00
2019-05-30 20:39:43 +02:00
return count , nil
2019-05-10 11:47:21 -04:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetGroupsByTeam ( teamId string , opts model . GroupSearchOpts ) ( [ ] * model . GroupWithSchemeAdmin , error ) {
2019-05-30 20:39:43 +02:00
query := s . groupsBySyncableBaseQuery ( model . GroupSyncableTypeTeam , selectGroups , teamId , opts )
2019-05-10 11:47:21 -04:00
2019-05-30 20:39:43 +02:00
if opts . PageOpts != nil {
offset := uint64 ( opts . PageOpts . Page * opts . PageOpts . PerPage )
query = query . OrderBy ( "ug.DisplayName" ) . Limit ( uint64 ( opts . PageOpts . PerPage ) ) . Offset ( offset )
}
2019-05-10 11:47:21 -04:00
2019-05-30 20:39:43 +02:00
queryString , args , err := query . ToSql ( )
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "get_groups_by_team_tosql" )
2019-05-30 20:39:43 +02:00
}
2019-04-02 21:02:51 +01:00
2020-01-10 12:19:39 -05:00
var groups [ ] * model . GroupWithSchemeAdmin
2019-04-02 21:02:51 +01:00
2019-05-30 20:39:43 +02:00
_ , err = s . GetReplica ( ) . Select ( & groups , queryString , args ... )
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to find Groups with teamId=%s" , teamId )
2019-05-30 20:39:43 +02:00
}
2019-04-02 21:02:51 +01:00
2019-05-30 20:39:43 +02:00
return groups , nil
2019-04-02 21:02:51 +01:00
}
2019-05-10 11:47:21 -04:00
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetGroupsAssociatedToChannelsByTeam ( teamId string , opts model . GroupSearchOpts ) ( map [ string ] [ ] * model . GroupWithSchemeAdmin , error ) {
2021-02-04 11:38:05 +06:00
query := s . getGroupsAssociatedToChannelsByTeam ( teamId , opts )
2020-04-13 11:37:29 -07:00
if opts . PageOpts != nil {
offset := uint64 ( opts . PageOpts . Page * opts . PageOpts . PerPage )
query = query . OrderBy ( "ug.DisplayName" ) . Limit ( uint64 ( opts . PageOpts . PerPage ) ) . Offset ( offset )
}
queryString , args , err := query . ToSql ( )
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "get_groups_associated_to_channel_by_team_tosql" )
2020-04-13 11:37:29 -07:00
}
var tgroups [ ] * model . GroupsAssociatedToChannelWithSchemeAdmin
_ , err = s . GetReplica ( ) . Select ( & tgroups , queryString , args ... )
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to find Groups with teamId=%s" , teamId )
2020-04-13 11:37:29 -07:00
}
groups := map [ string ] [ ] * model . GroupWithSchemeAdmin { }
for _ , tgroup := range tgroups {
var group = model . GroupWithSchemeAdmin { }
group . Group = tgroup . Group
group . SchemeAdmin = tgroup . SchemeAdmin
if val , ok := groups [ tgroup . ChannelId ] ; ok {
groups [ tgroup . ChannelId ] = append ( val , & group )
} else {
groups [ tgroup . ChannelId ] = [ ] * model . GroupWithSchemeAdmin { & group }
}
}
return groups , nil
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GetGroups ( page , perPage int , opts model . GroupSearchOpts ) ( [ ] * model . Group , error ) {
2019-05-30 20:39:43 +02:00
var groups [ ] * model . Group
2019-05-10 11:47:21 -04:00
2020-01-27 11:45:14 -05:00
groupsQuery := s . getQueryBuilder ( ) . Select ( "g.*" )
2019-05-10 11:47:21 -04:00
2019-05-30 20:39:43 +02:00
if opts . IncludeMemberCount {
groupsQuery = s . getQueryBuilder ( ) .
Select ( "g.*, coalesce(Members.MemberCount, 0) AS MemberCount" ) .
2020-01-27 11:45:14 -05:00
LeftJoin ( "(SELECT GroupMembers.GroupId, COUNT(*) AS MemberCount FROM GroupMembers LEFT JOIN Users ON Users.Id = GroupMembers.UserId WHERE GroupMembers.DeleteAt = 0 AND Users.DeleteAt = 0 GROUP BY GroupId) AS Members ON Members.GroupId = g.Id" )
2019-05-30 20:39:43 +02:00
}
2019-05-10 11:47:21 -04:00
2020-01-27 11:45:14 -05:00
groupsQuery = groupsQuery .
From ( "UserGroups g" ) .
OrderBy ( "g.DisplayName" )
2020-05-07 14:35:09 -06:00
if opts . Since > 0 {
groupsQuery = groupsQuery . Where ( sq . Gt {
"g.UpdateAt" : opts . Since ,
} )
} else {
groupsQuery = groupsQuery . Where ( "g.DeleteAt = 0" )
}
2020-04-17 19:22:54 -04:00
if perPage != 0 {
groupsQuery = groupsQuery .
Limit ( uint64 ( perPage ) ) .
Offset ( uint64 ( page * perPage ) )
}
2020-04-13 11:37:29 -07:00
if opts . FilterAllowReference {
groupsQuery = groupsQuery . Where ( "g.AllowReference = true" )
}
2021-01-25 11:15:17 +01:00
if opts . Q != "" {
2019-09-11 10:56:12 +02:00
pattern := fmt . Sprintf ( "%%%s%%" , sanitizeSearchTerm ( opts . Q , "\\" ) )
2019-05-30 20:39:43 +02:00
operatorKeyword := "ILIKE"
2021-07-12 20:05:36 +02:00
if s . DriverName ( ) == model . DatabaseDriverMysql {
2019-05-30 20:39:43 +02:00
operatorKeyword = "LIKE"
2019-05-10 11:47:21 -04:00
}
2019-05-30 20:39:43 +02:00
groupsQuery = groupsQuery . Where ( fmt . Sprintf ( "(g.Name %[1]s ? OR g.DisplayName %[1]s ?)" , operatorKeyword ) , pattern , pattern )
}
2019-05-10 11:47:21 -04:00
2019-05-30 20:39:43 +02:00
if len ( opts . NotAssociatedToTeam ) == 26 {
groupsQuery = groupsQuery . Where ( `
2019-05-10 11:47:21 -04:00
g . Id NOT IN (
2020-01-20 09:10:25 -05:00
SELECT
Id
FROM
2019-05-10 11:47:21 -04:00
UserGroups
JOIN GroupTeams ON GroupTeams . GroupId = UserGroups . Id
2020-01-20 09:10:25 -05:00
WHERE
2019-05-10 11:47:21 -04:00
GroupTeams . DeleteAt = 0
AND UserGroups . DeleteAt = 0
AND GroupTeams . TeamId = ?
)
` , opts . NotAssociatedToTeam )
2019-05-30 20:39:43 +02:00
}
2019-05-10 11:47:21 -04:00
2019-05-30 20:39:43 +02:00
if len ( opts . NotAssociatedToChannel ) == 26 {
groupsQuery = groupsQuery . Where ( `
2019-05-15 12:03:47 -04:00
g . Id NOT IN (
2020-01-20 09:10:25 -05:00
SELECT
Id
FROM
2019-05-15 12:03:47 -04:00
UserGroups
JOIN GroupChannels ON GroupChannels . GroupId = UserGroups . Id
2020-01-20 09:10:25 -05:00
WHERE
2019-05-15 12:03:47 -04:00
GroupChannels . DeleteAt = 0
AND UserGroups . DeleteAt = 0
AND GroupChannels . ChannelId = ?
)
` , opts . NotAssociatedToChannel )
2019-05-30 20:39:43 +02:00
}
2019-05-15 12:03:47 -04:00
2020-05-29 10:46:52 -04:00
if opts . FilterParentTeamPermitted && len ( opts . NotAssociatedToChannel ) == 26 {
groupsQuery = groupsQuery . Where ( `
2020-06-04 11:31:07 -04:00
CASE
WHEN (
SELECT
Teams . GroupConstrained
FROM
Teams
JOIN Channels ON Channels . TeamId = Teams . Id
WHERE
Channels . Id = ?
) THEN g . Id IN (
2020-05-29 10:46:52 -04:00
SELECT
GroupId
FROM
GroupTeams
WHERE
GroupTeams . DeleteAt = 0
AND GroupTeams . TeamId = (
SELECT
TeamId
FROM
Channels
WHERE
Id = ?
)
)
2020-06-04 11:31:07 -04:00
ELSE TRUE
END
` , opts . NotAssociatedToChannel , opts . NotAssociatedToChannel )
2020-05-29 10:46:52 -04:00
}
2019-05-30 20:39:43 +02:00
queryString , args , err := groupsQuery . ToSql ( )
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "get_groups_tosql" )
2019-05-30 20:39:43 +02:00
}
2019-05-10 11:47:21 -04:00
2019-05-30 20:39:43 +02:00
if _ , err = s . GetReplica ( ) . Select ( & groups , queryString , args ... ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "failed to find Groups" )
2019-05-30 20:39:43 +02:00
}
2019-05-10 11:47:21 -04:00
2019-05-30 20:39:43 +02:00
return groups , nil
2019-05-10 11:47:21 -04:00
}
2019-06-17 09:51:56 -04:00
2019-06-25 08:18:48 -04:00
func ( s * SqlGroupStore ) teamMembersMinusGroupMembersQuery ( teamID string , groupIDs [ ] string , isCount bool ) sq . SelectBuilder {
2019-06-17 09:51:56 -04:00
var selectStr string
if isCount {
selectStr = "count(DISTINCT Users.Id)"
} else {
2019-09-26 14:11:55 -04:00
tmpl := "Users.*, coalesce(TeamMembers.SchemeGuest, false), TeamMembers.SchemeAdmin, TeamMembers.SchemeUser, %s AS GroupIDs"
2021-07-12 20:05:36 +02:00
if s . DriverName ( ) == model . DatabaseDriverMysql {
2019-06-17 09:51:56 -04:00
selectStr = fmt . Sprintf ( tmpl , "group_concat(UserGroups.Id)" )
} else {
selectStr = fmt . Sprintf ( tmpl , "string_agg(UserGroups.Id, ',')" )
}
}
subQuery := s . getQueryBuilder ( ) . Select ( "GroupMembers.UserId" ) .
From ( "GroupMembers" ) .
Join ( "UserGroups ON UserGroups.Id = GroupMembers.GroupId" ) .
Where ( "GroupMembers.DeleteAt = 0" ) .
Where ( fmt . Sprintf ( "GroupMembers.GroupId IN ('%s')" , strings . Join ( groupIDs , "', '" ) ) )
2020-11-17 00:32:36 -03:00
query , _ := subQuery . MustSql ( )
2019-06-17 09:51:56 -04:00
2020-11-17 00:32:36 -03:00
builder := s . getQueryBuilder ( ) . Select ( selectStr ) .
2019-06-17 09:51:56 -04:00
From ( "TeamMembers" ) .
Join ( "Teams ON Teams.Id = TeamMembers.TeamId" ) .
Join ( "Users ON Users.Id = TeamMembers.UserId" ) .
LeftJoin ( "Bots ON Bots.UserId = TeamMembers.UserId" ) .
2019-07-30 12:04:08 -04:00
LeftJoin ( "GroupMembers ON GroupMembers.UserId = Users.Id" ) .
LeftJoin ( "UserGroups ON UserGroups.Id = GroupMembers.GroupId" ) .
2019-06-17 09:51:56 -04:00
Where ( "TeamMembers.DeleteAt = 0" ) .
Where ( "Teams.DeleteAt = 0" ) .
Where ( "Users.DeleteAt = 0" ) .
Where ( "Bots.UserId IS NULL" ) .
Where ( "Teams.Id = ?" , teamID ) .
2020-11-17 00:32:36 -03:00
Where ( fmt . Sprintf ( "Users.Id NOT IN (%s)" , query ) )
2019-06-17 09:51:56 -04:00
if ! isCount {
2020-11-17 00:32:36 -03:00
builder = builder . GroupBy ( "Users.Id, TeamMembers.SchemeGuest, TeamMembers.SchemeAdmin, TeamMembers.SchemeUser" )
2019-06-17 09:51:56 -04:00
}
2020-11-17 00:32:36 -03:00
return builder
2019-06-17 09:51:56 -04:00
}
// TeamMembersMinusGroupMembers returns the set of users on the given team minus the set of users in the given
// groups.
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) TeamMembersMinusGroupMembers ( teamID string , groupIDs [ ] string , page , perPage int ) ( [ ] * model . UserWithGroups , error ) {
2019-06-17 09:51:56 -04:00
query := s . teamMembersMinusGroupMembersQuery ( teamID , groupIDs , false )
2019-07-30 12:04:08 -04:00
query = query . OrderBy ( "Users.Username ASC" ) . Limit ( uint64 ( perPage ) ) . Offset ( uint64 ( page * perPage ) )
2019-06-17 09:51:56 -04:00
queryString , args , err := query . ToSql ( )
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "team_members_minus_group_members" )
2019-06-17 09:51:56 -04:00
}
var users [ ] * model . UserWithGroups
if _ , err = s . GetReplica ( ) . Select ( & users , queryString , args ... ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "failed to find UserWithGroups" )
2019-06-17 09:51:56 -04:00
}
return users , nil
}
// CountTeamMembersMinusGroupMembers returns the count of the set of users on the given team minus the set of users
// in the given groups.
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) CountTeamMembersMinusGroupMembers ( teamID string , groupIDs [ ] string ) ( int64 , error ) {
2019-06-17 09:51:56 -04:00
queryString , args , err := s . teamMembersMinusGroupMembersQuery ( teamID , groupIDs , true ) . ToSql ( )
if err != nil {
2020-11-17 00:32:36 -03:00
return 0 , errors . Wrap ( err , "count_team_members_minus_group_members_tosql" )
2019-06-17 09:51:56 -04:00
}
var count int64
if count , err = s . GetReplica ( ) . SelectInt ( queryString , args ... ) ; err != nil {
2020-11-17 00:32:36 -03:00
return 0 , errors . Wrap ( err , "failed to count TeamMembers minus GroupMembers" )
2019-06-17 09:51:56 -04:00
}
return count , nil
}
2019-06-17 11:04:27 -04:00
2019-06-25 08:18:48 -04:00
func ( s * SqlGroupStore ) channelMembersMinusGroupMembersQuery ( channelID string , groupIDs [ ] string , isCount bool ) sq . SelectBuilder {
2019-06-17 11:04:27 -04:00
var selectStr string
if isCount {
selectStr = "count(DISTINCT Users.Id)"
} else {
2019-09-26 14:11:55 -04:00
tmpl := "Users.*, coalesce(ChannelMembers.SchemeGuest, false), ChannelMembers.SchemeAdmin, ChannelMembers.SchemeUser, %s AS GroupIDs"
2021-07-12 20:05:36 +02:00
if s . DriverName ( ) == model . DatabaseDriverMysql {
2019-06-17 11:04:27 -04:00
selectStr = fmt . Sprintf ( tmpl , "group_concat(UserGroups.Id)" )
} else {
selectStr = fmt . Sprintf ( tmpl , "string_agg(UserGroups.Id, ',')" )
}
}
subQuery := s . getQueryBuilder ( ) . Select ( "GroupMembers.UserId" ) .
From ( "GroupMembers" ) .
Join ( "UserGroups ON UserGroups.Id = GroupMembers.GroupId" ) .
Where ( "GroupMembers.DeleteAt = 0" ) .
Where ( fmt . Sprintf ( "GroupMembers.GroupId IN ('%s')" , strings . Join ( groupIDs , "', '" ) ) )
2020-11-17 00:32:36 -03:00
query , _ := subQuery . MustSql ( )
2019-06-17 11:04:27 -04:00
2020-11-17 00:32:36 -03:00
builder := s . getQueryBuilder ( ) . Select ( selectStr ) .
2019-06-17 11:04:27 -04:00
From ( "ChannelMembers" ) .
Join ( "Channels ON Channels.Id = ChannelMembers.ChannelId" ) .
Join ( "Users ON Users.Id = ChannelMembers.UserId" ) .
LeftJoin ( "Bots ON Bots.UserId = ChannelMembers.UserId" ) .
2019-07-30 12:04:08 -04:00
LeftJoin ( "GroupMembers ON GroupMembers.UserId = Users.Id" ) .
LeftJoin ( "UserGroups ON UserGroups.Id = GroupMembers.GroupId" ) .
2019-06-17 11:04:27 -04:00
Where ( "Channels.DeleteAt = 0" ) .
Where ( "Users.DeleteAt = 0" ) .
Where ( "Bots.UserId IS NULL" ) .
Where ( "Channels.Id = ?" , channelID ) .
2020-11-17 00:32:36 -03:00
Where ( fmt . Sprintf ( "Users.Id NOT IN (%s)" , query ) )
2019-06-17 11:04:27 -04:00
if ! isCount {
2020-11-17 00:32:36 -03:00
builder = builder . GroupBy ( "Users.Id, ChannelMembers.SchemeGuest, ChannelMembers.SchemeAdmin, ChannelMembers.SchemeUser" )
2019-06-17 11:04:27 -04:00
}
2020-11-17 00:32:36 -03:00
return builder
2019-06-17 11:04:27 -04:00
}
// ChannelMembersMinusGroupMembers returns the set of users in the given channel minus the set of users in the given
// groups.
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) ChannelMembersMinusGroupMembers ( channelID string , groupIDs [ ] string , page , perPage int ) ( [ ] * model . UserWithGroups , error ) {
2019-06-17 11:04:27 -04:00
query := s . channelMembersMinusGroupMembersQuery ( channelID , groupIDs , false )
2019-07-30 12:04:08 -04:00
query = query . OrderBy ( "Users.Username ASC" ) . Limit ( uint64 ( perPage ) ) . Offset ( uint64 ( page * perPage ) )
2019-06-17 11:04:27 -04:00
queryString , args , err := query . ToSql ( )
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "channel_members_minus_group_members_tosql" )
2019-06-17 11:04:27 -04:00
}
var users [ ] * model . UserWithGroups
if _ , err = s . GetReplica ( ) . Select ( & users , queryString , args ... ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "failed to find UserWithGroups" )
2019-06-17 11:04:27 -04:00
}
return users , nil
}
// CountChannelMembersMinusGroupMembers returns the count of the set of users in the given channel minus the set of users
// in the given groups.
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) CountChannelMembersMinusGroupMembers ( channelID string , groupIDs [ ] string ) ( int64 , error ) {
2019-06-17 11:04:27 -04:00
queryString , args , err := s . channelMembersMinusGroupMembersQuery ( channelID , groupIDs , true ) . ToSql ( )
if err != nil {
2020-11-17 00:32:36 -03:00
return 0 , errors . Wrap ( err , "count_channel_members_minus_group_members_tosql" )
2019-06-17 11:04:27 -04:00
}
var count int64
if count , err = s . GetReplica ( ) . SelectInt ( queryString , args ... ) ; err != nil {
2020-11-17 00:32:36 -03:00
return 0 , errors . Wrap ( err , "failed to count ChannelMembers" )
2019-06-17 11:04:27 -04:00
}
return count , nil
}
2020-01-10 12:19:39 -05:00
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) AdminRoleGroupsForSyncableMember ( userID , syncableID string , syncableType model . GroupSyncableType ) ( [ ] string , error ) {
2020-01-10 12:19:39 -05:00
var groupIds [ ] string
2020-11-17 00:32:36 -03:00
query := fmt . Sprintf ( `
2020-01-20 09:10:25 -05:00
SELECT
2020-01-10 12:19:39 -05:00
GroupMembers . GroupId
2020-01-20 09:10:25 -05:00
FROM
GroupMembers
INNER JOIN
2020-01-10 12:19:39 -05:00
Group % [ 1 ] ss ON Group % [ 1 ] ss . GroupId = GroupMembers . GroupId
2020-01-20 09:10:25 -05:00
WHERE
GroupMembers . UserId = : UserId
AND GroupMembers . DeleteAt = 0
AND % [ 1 ] sId = : % [ 1 ] sId
AND Group % [ 1 ] ss . DeleteAt = 0
2020-01-10 12:19:39 -05:00
AND Group % [ 1 ] ss . SchemeAdmin = TRUE ` , syncableType )
2020-11-17 00:32:36 -03:00
_ , err := s . GetReplica ( ) . Select ( & groupIds , query , map [ string ] interface { } { "UserId" : userID , fmt . Sprintf ( "%sId" , syncableType ) : syncableID } )
2020-01-10 12:19:39 -05:00
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "failed to find Group ids" )
2020-01-10 12:19:39 -05:00
}
return groupIds , nil
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) PermittedSyncableAdmins ( syncableID string , syncableType model . GroupSyncableType ) ( [ ] string , error ) {
builder := s . getQueryBuilder ( ) . Select ( "UserId" ) .
2020-01-10 12:19:39 -05:00
From ( fmt . Sprintf ( "Group%ss" , syncableType ) ) .
Join ( fmt . Sprintf ( "GroupMembers ON GroupMembers.GroupId = Group%ss.GroupId AND Group%[1]ss.SchemeAdmin = TRUE AND GroupMembers.DeleteAt = 0" , syncableType . String ( ) ) ) . Where ( fmt . Sprintf ( "Group%[1]ss.%[1]sId = ?" , syncableType . String ( ) ) , syncableID )
2020-11-17 00:32:36 -03:00
query , args , err := builder . ToSql ( )
2020-01-10 12:19:39 -05:00
if err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrap ( err , "permitted_syncable_admins_tosql" )
2020-01-10 12:19:39 -05:00
}
var userIDs [ ] string
2021-03-12 12:37:30 -05:00
if _ , err = s . GetMaster ( ) . Select ( & userIDs , query , args ... ) ; err != nil {
2020-11-17 00:32:36 -03:00
return nil , errors . Wrapf ( err , "failed to find User ids" )
2020-01-10 12:19:39 -05:00
}
return userIDs , nil
}
2020-02-06 09:25:36 -05:00
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GroupCount ( ) ( int64 , error ) {
2020-02-06 09:25:36 -05:00
return s . countTable ( "UserGroups" )
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GroupTeamCount ( ) ( int64 , error ) {
2020-02-06 09:25:36 -05:00
return s . countTable ( "GroupTeams" )
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GroupChannelCount ( ) ( int64 , error ) {
2020-02-06 09:25:36 -05:00
return s . countTable ( "GroupChannels" )
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GroupMemberCount ( ) ( int64 , error ) {
2020-02-06 09:25:36 -05:00
return s . countTable ( "GroupMembers" )
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) DistinctGroupMemberCount ( ) ( int64 , error ) {
2020-05-22 10:56:15 -04:00
return s . countTableWithSelectAndWhere ( "COUNT(DISTINCT UserId)" , "GroupMembers" , nil )
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) GroupCountWithAllowReference ( ) ( int64 , error ) {
2020-05-22 10:56:15 -04:00
return s . countTableWithSelectAndWhere ( "COUNT(*)" , "UserGroups" , sq . Eq { "AllowReference" : true , "DeleteAt" : 0 } )
2020-02-06 09:25:36 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) countTable ( tableName string ) ( int64 , error ) {
2020-05-22 10:56:15 -04:00
return s . countTableWithSelectAndWhere ( "COUNT(*)" , tableName , nil )
2020-02-06 09:25:36 -05:00
}
2020-11-17 00:32:36 -03:00
func ( s * SqlGroupStore ) countTableWithSelectAndWhere ( selectStr , tableName string , whereStmt map [ string ] interface { } ) ( int64 , error ) {
2020-05-22 10:56:15 -04:00
if whereStmt == nil {
whereStmt = sq . Eq { "DeleteAt" : 0 }
}
query := s . getQueryBuilder ( ) . Select ( selectStr ) . From ( tableName ) . Where ( whereStmt )
2020-02-06 09:25:36 -05:00
sql , args , err := query . ToSql ( )
if err != nil {
2020-11-17 00:32:36 -03:00
return 0 , errors . Wrap ( err , "count_table_with_select_and_where_tosql" )
2020-02-06 09:25:36 -05:00
}
count , err := s . GetReplica ( ) . SelectInt ( sql , args ... )
if err != nil {
2020-11-17 00:32:36 -03:00
return 0 , errors . Wrapf ( err , "failed to count from table %s" , tableName )
2020-02-06 09:25:36 -05:00
}
return count , nil
}