github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/app/syncables.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"fmt"
     8  	"net/http"
     9  	"strings"
    10  
    11  	"github.com/mattermost/mattermost-server/v5/mlog"
    12  	"github.com/mattermost/mattermost-server/v5/model"
    13  )
    14  
    15  // createDefaultChannelMemberships adds users to channels based on their group memberships and how those groups are
    16  // configured to sync with channels for group members on or after the given timestamp. If a channelID is given
    17  // only that channel's members are created. If channelID is nil all channel memberships are created.
    18  func (a *App) createDefaultChannelMemberships(since int64, channelID *string) error {
    19  	channelMembers, appErr := a.ChannelMembersToAdd(since, channelID)
    20  	if appErr != nil {
    21  		return appErr
    22  	}
    23  
    24  	for _, userChannel := range channelMembers {
    25  		channel, err := a.GetChannel(userChannel.ChannelID)
    26  		if err != nil {
    27  			return err
    28  		}
    29  
    30  		tmem, err := a.GetTeamMember(channel.TeamId, userChannel.UserID)
    31  		if err != nil && err.Id != "app.team.get_member.missing.app_error" {
    32  			return err
    33  		}
    34  
    35  		// First add user to team
    36  		if tmem == nil {
    37  			_, err = a.AddTeamMember(channel.TeamId, userChannel.UserID)
    38  			if err != nil {
    39  				if err.Id == "api.team.join_user_to_team.allowed_domains.app_error" {
    40  					a.Log().Info("User not added to channel - the domain associated with the user is not in the list of allowed team domains",
    41  						mlog.String("user_id", userChannel.UserID),
    42  						mlog.String("channel_id", userChannel.ChannelID),
    43  						mlog.String("team_id", channel.TeamId),
    44  					)
    45  					continue
    46  				}
    47  				return err
    48  			}
    49  			a.Log().Info("added teammember",
    50  				mlog.String("user_id", userChannel.UserID),
    51  				mlog.String("team_id", channel.TeamId),
    52  			)
    53  		}
    54  
    55  		_, err = a.AddChannelMember(userChannel.UserID, channel, "", "")
    56  		if err != nil {
    57  			if err.Id == "api.channel.add_user.to.channel.failed.deleted.app_error" {
    58  				a.Log().Info("Not adding user to channel because they have already left the team",
    59  					mlog.String("user_id", userChannel.UserID),
    60  					mlog.String("channel_id", userChannel.ChannelID),
    61  				)
    62  			} else {
    63  				return err
    64  			}
    65  		}
    66  
    67  		a.Log().Info("added channelmember",
    68  			mlog.String("user_id", userChannel.UserID),
    69  			mlog.String("channel_id", userChannel.ChannelID),
    70  		)
    71  	}
    72  
    73  	return nil
    74  }
    75  
    76  // createDefaultTeamMemberships adds users to teams based on their group memberships and how those groups are
    77  // configured to sync with teams for group members on or after the given timestamp. If a teamID is given
    78  // only that team's members are created. If teamID is nil all team memberships are created.
    79  func (a *App) createDefaultTeamMemberships(since int64, teamID *string) error {
    80  	teamMembers, appErr := a.TeamMembersToAdd(since, teamID)
    81  	if appErr != nil {
    82  		return appErr
    83  	}
    84  
    85  	for _, userTeam := range teamMembers {
    86  		_, err := a.AddTeamMember(userTeam.TeamID, userTeam.UserID)
    87  		if err != nil {
    88  			if err.Id == "api.team.join_user_to_team.allowed_domains.app_error" {
    89  				a.Log().Info("User not added to team - the domain associated with the user is not in the list of allowed team domains",
    90  					mlog.String("user_id", userTeam.UserID),
    91  					mlog.String("team_id", userTeam.TeamID),
    92  				)
    93  				continue
    94  			}
    95  			return err
    96  		}
    97  
    98  		a.Log().Info("added teammember",
    99  			mlog.String("user_id", userTeam.UserID),
   100  			mlog.String("team_id", userTeam.TeamID),
   101  		)
   102  	}
   103  
   104  	return nil
   105  }
   106  
   107  // CreateDefaultMemberships adds users to teams and channels based on their group memberships and how those groups
   108  // are configured to sync with teams and channels for group members on or after the given timestamp.
   109  func (a *App) CreateDefaultMemberships(since int64) error {
   110  	err := a.createDefaultTeamMemberships(since, nil)
   111  	if err != nil {
   112  		return err
   113  	}
   114  
   115  	err = a.createDefaultChannelMemberships(since, nil)
   116  	if err != nil {
   117  		return err
   118  	}
   119  
   120  	return nil
   121  }
   122  
   123  // DeleteGroupConstrainedMemberships deletes team and channel memberships of users who aren't members of the allowed
   124  // groups of all group-constrained teams and channels.
   125  func (a *App) DeleteGroupConstrainedMemberships() error {
   126  	err := a.deleteGroupConstrainedChannelMemberships(nil)
   127  	if err != nil {
   128  		return err
   129  	}
   130  
   131  	err = a.deleteGroupConstrainedTeamMemberships(nil)
   132  	if err != nil {
   133  		return err
   134  	}
   135  
   136  	return nil
   137  }
   138  
   139  // deleteGroupConstrainedTeamMemberships deletes team memberships of users who aren't members of the allowed
   140  // groups of the given group-constrained team. If a teamID is given then the procedure is scoped to the given team,
   141  // if teamID is nil then the procedure affects all teams.
   142  func (a *App) deleteGroupConstrainedTeamMemberships(teamID *string) error {
   143  	teamMembers, appErr := a.TeamMembersToRemove(teamID)
   144  	if appErr != nil {
   145  		return appErr
   146  	}
   147  
   148  	for _, userTeam := range teamMembers {
   149  		err := a.RemoveUserFromTeam(userTeam.TeamId, userTeam.UserId, "")
   150  		if err != nil {
   151  			return err
   152  		}
   153  
   154  		a.Log().Info("removed teammember",
   155  			mlog.String("user_id", userTeam.UserId),
   156  			mlog.String("team_id", userTeam.TeamId),
   157  		)
   158  	}
   159  
   160  	return nil
   161  }
   162  
   163  // deleteGroupConstrainedChannelMemberships deletes channel memberships of users who aren't members of the allowed
   164  // groups of the given group-constrained channel. If a channelID is given then the procedure is scoped to the given team,
   165  // if channelID is nil then the procedure affects all teams.
   166  func (a *App) deleteGroupConstrainedChannelMemberships(channelID *string) error {
   167  	channelMembers, appErr := a.ChannelMembersToRemove(channelID)
   168  	if appErr != nil {
   169  		return appErr
   170  	}
   171  
   172  	for _, userChannel := range channelMembers {
   173  		channel, err := a.GetChannel(userChannel.ChannelId)
   174  		if err != nil {
   175  			return err
   176  		}
   177  
   178  		err = a.RemoveUserFromChannel(userChannel.UserId, "", channel)
   179  		if err != nil {
   180  			return err
   181  		}
   182  
   183  		a.Log().Info("removed channelmember",
   184  			mlog.String("user_id", userChannel.UserId),
   185  			mlog.String("channel_id", channel.Id),
   186  		)
   187  	}
   188  
   189  	return nil
   190  }
   191  
   192  // SyncSyncableRoles updates the SchemeAdmin field value of the given syncable's members based on the configuration of
   193  // the member's group memberships and the configuration of those groups to the syncable. This method should only
   194  // be invoked on group-synced (aka group-constrained) syncables.
   195  func (a *App) SyncSyncableRoles(syncableID string, syncableType model.GroupSyncableType) *model.AppError {
   196  	permittedAdmins, err := a.Srv().Store.Group().PermittedSyncableAdmins(syncableID, syncableType)
   197  	if err != nil {
   198  		return model.NewAppError("SyncSyncableRoles", "app.select_error", nil, err.Error(), http.StatusInternalServerError)
   199  	}
   200  
   201  	a.Log().Info(
   202  		fmt.Sprintf("Permitted admins for %s", syncableType),
   203  		mlog.String(strings.ToLower(fmt.Sprintf("%s_id", syncableType)), syncableID),
   204  		mlog.Any("permitted_admins", permittedAdmins),
   205  	)
   206  
   207  	switch syncableType {
   208  	case model.GroupSyncableTypeTeam:
   209  		nErr := a.Srv().Store.Team().UpdateMembersRole(syncableID, permittedAdmins)
   210  		if nErr != nil {
   211  			return model.NewAppError("App.SyncSyncableRoles", "app.update_error", nil, nErr.Error(), http.StatusInternalServerError)
   212  		}
   213  		return nil
   214  	case model.GroupSyncableTypeChannel:
   215  		nErr := a.Srv().Store.Channel().UpdateMembersRole(syncableID, permittedAdmins)
   216  		if nErr != nil {
   217  			return model.NewAppError("App.SyncSyncableRoles", "app.update_error", nil, nErr.Error(), http.StatusInternalServerError)
   218  		}
   219  		return nil
   220  	default:
   221  		return model.NewAppError("App.SyncSyncableRoles", "groups.unsupported_syncable_type", map[string]interface{}{"Value": syncableType}, "", http.StatusInternalServerError)
   222  	}
   223  }
   224  
   225  // SyncRolesAndMembership updates the SchemeAdmin status and membership of all of the members of the given
   226  // syncable.
   227  func (a *App) SyncRolesAndMembership(syncableID string, syncableType model.GroupSyncableType) {
   228  	a.SyncSyncableRoles(syncableID, syncableType)
   229  
   230  	lastJob, _ := a.Srv().Store.Job().GetNewestJobByStatusAndType(model.JOB_STATUS_SUCCESS, model.JOB_TYPE_LDAP_SYNC)
   231  	var since int64
   232  	if lastJob != nil {
   233  		since = lastJob.StartAt
   234  	}
   235  
   236  	switch syncableType {
   237  	case model.GroupSyncableTypeTeam:
   238  		a.createDefaultTeamMemberships(since, &syncableID)
   239  		a.deleteGroupConstrainedTeamMemberships(&syncableID)
   240  		a.ClearTeamMembersCache(syncableID)
   241  	case model.GroupSyncableTypeChannel:
   242  		a.createDefaultChannelMemberships(since, &syncableID)
   243  		a.deleteGroupConstrainedChannelMemberships(&syncableID)
   244  		a.ClearChannelMembersCache(syncableID)
   245  	}
   246  }