MM-32133 shared channel username collisions (#17347)

Support for handling username collisions between remote clusters. Users belonging to remote clusters have their username changed to include the remote name e.g. wiggin becomes wiggin:mattermost.

@mentions are also modified so the munged username is replaced with the original username when the post is sync'd with the remote the user belongs to.

When adding remote users:
- append the remote name to the username with colon separator
- append the remote name to the email address with colon separator
- store the original username and email address in user props
- when resolving @mentions replace with the stored original username
Этот коммит содержится в:
Doug Lauder
2021-04-13 10:40:12 -04:00
коммит произвёл GitHub
родитель 869da7a78b
Коммит f69cb38249
28 изменённых файлов: 544 добавлений и 147 удалений

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

@@ -66,7 +66,7 @@ func (mrcs *mockRemoteClusterService) SendFile(ctx context.Context, us *model.Up
return nil
}
func (mrcs *mockRemoteClusterService) AcceptInvitation(invite *model.RemoteClusterInvite, name string, creatorId string, teamId string, siteURL string) (*model.RemoteCluster, error) {
func (mrcs *mockRemoteClusterService) AcceptInvitation(invite *model.RemoteClusterInvite, name string, displayName string, creatorId string, teamId string, siteURL string) (*model.RemoteCluster, error) {
return nil, nil
}

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

@@ -19,7 +19,7 @@ func TestAddRemoteCluster(t *testing.T) {
remoteCluster := &model.RemoteCluster{
RemoteTeamId: model.NewId(),
DisplayName: "test",
Name: "test",
SiteURL: "http://localhost:8065",
Token: "test",
RemoteToken: "test",
@@ -42,7 +42,7 @@ func TestAddRemoteCluster(t *testing.T) {
remoteCluster := &model.RemoteCluster{
RemoteTeamId: model.NewId(),
DisplayName: "test",
Name: "test",
SiteURL: "http://localhost:8065",
Token: "test",
RemoteToken: "test",
@@ -76,7 +76,7 @@ func TestUpdateRemoteCluster(t *testing.T) {
remoteCluster := &model.RemoteCluster{
RemoteTeamId: model.NewId(),
DisplayName: "test",
Name: "test",
SiteURL: "http://localhost:8065",
Token: "test",
RemoteToken: "test",
@@ -86,7 +86,7 @@ func TestUpdateRemoteCluster(t *testing.T) {
otherRemoteCluster := &model.RemoteCluster{
RemoteTeamId: model.NewId(),
DisplayName: "test",
Name: "test",
SiteURL: "http://localhost:8066",
Token: "test",
RemoteToken: "test",
@@ -113,7 +113,7 @@ func TestUpdateRemoteCluster(t *testing.T) {
remoteCluster := &model.RemoteCluster{
RemoteTeamId: model.NewId(),
DisplayName: "test",
Name: "test",
SiteURL: "http://localhost:8065",
Token: "test",
RemoteToken: "test",
@@ -123,7 +123,7 @@ func TestUpdateRemoteCluster(t *testing.T) {
otherRemoteCluster := &model.RemoteCluster{
RemoteTeamId: model.NewId(),
DisplayName: "test",
Name: "test",
SiteURL: "http://localhost:8066",
Token: "test",
RemoteToken: "test",

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

@@ -448,7 +448,7 @@ func TestGetRemoteClusterSession(t *testing.T) {
rc := model.RemoteCluster{
RemoteId: remoteId,
RemoteTeamId: model.NewId(),
DisplayName: "test",
Name: "test",
Token: token,
CreatorId: model.NewId(),
}

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

@@ -40,10 +40,12 @@ func (rp *RemoteProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Co
invite := model.NewAutocompleteData("invite", "", T("api.command_remote.invite.help"))
invite.AddNamedTextArgument("password", T("api.command_remote.invite_password.help"), T("api.command_remote.invite_password.hint"), "", true)
invite.AddNamedTextArgument("name", T("api.command_remote.name.help"), T("api.command_remote.name.hint"), "", true)
invite.AddNamedTextArgument("displayname", T("api.command_remote.displayname.help"), T("api.command_remote.displayname.hint"), "", false)
accept := model.NewAutocompleteData("accept", "", T("api.command_remote.accept.help"))
accept.AddNamedTextArgument("password", T("api.command_remote.invite_password.help"), T("api.command_remote.invite_password.hint"), "", true)
accept.AddNamedTextArgument("name", T("api.command_remote.name.help"), T("api.command_remote.name.hint"), "", true)
accept.AddNamedTextArgument("displayname", T("api.command_remote.displayname.help"), T("api.command_remote.displayname.hint"), "", false)
accept.AddNamedTextArgument("invite", T("api.command_remote.invitation.help"), T("api.command_remote.invitation.hint"), "", true)
remove := model.NewAutocompleteData("remove", "", T("api.command_remote.remove.help"))
@@ -114,6 +116,7 @@ func (rp *RemoteProvider) doInvite(a *app.App, args *model.CommandArgs, margs ma
if name == "" {
return responsef(args.T("api.command_remote.missing_empty", map[string]interface{}{"Arg": "name"}))
}
displayname := margs["displayname"]
url := a.GetSiteURL()
if url == "" {
@@ -121,7 +124,8 @@ func (rp *RemoteProvider) doInvite(a *app.App, args *model.CommandArgs, margs ma
}
rc := &model.RemoteCluster{
DisplayName: name,
Name: name,
DisplayName: displayname,
Token: model.NewId(),
CreatorId: args.UserId,
}
@@ -159,6 +163,7 @@ func (rp *RemoteProvider) doAccept(a *app.App, args *model.CommandArgs, margs ma
if name == "" {
return responsef(args.T("api.command_remote.missing_empty", map[string]interface{}{"Arg": "name"}))
}
displayname := margs["displayname"]
blob := margs["invite"]
if blob == "" {
@@ -186,7 +191,7 @@ func (rp *RemoteProvider) doAccept(a *app.App, args *model.CommandArgs, margs ma
return responsef(args.T("api.command_remote.site_url_not_set"))
}
rc, err := rcs.AcceptInvitation(invite, name, args.UserId, args.TeamId, url)
rc, err := rcs.AcceptInvitation(invite, name, displayname, args.UserId, args.TeamId, url)
if err != nil {
return responsef(args.T("api.command_remote.accept_invitation.error", map[string]interface{}{"Error": err.Error()}))
}
@@ -241,7 +246,7 @@ func (rp *RemoteProvider) doStatus(a *app.App, args *model.CommandArgs, _ map[st
lastPing := formatTimestamp(model.GetTimeForMillis(rc.LastPingAt))
fmt.Fprintf(&sb, "| %s | %s | %s | %s | %s | %s |\n", rc.DisplayName, rc.SiteURL, rc.RemoteId, accepted, online, lastPing)
fmt.Fprintf(&sb, "| %s | %s | %s | %s | %s | %s | %s |\n", rc.Name, rc.DisplayName, rc.SiteURL, rc.RemoteId, accepted, online, lastPing)
}
return responsef(sb.String())
}